1. 程式人生 > >Spring RestTemplate中常見的請求方式

Spring RestTemplate中常見的請求方式

1.基本概念

Spring RestTemplate 是 Spring 提供的用於訪問 Rest 服務的客戶端,RestTemplate 提供了多種便捷訪問遠端Http服務的方法,能夠大大提高客戶端的編寫效率,所以很多客戶端比如 Android或者第三方服務商都是使用 RestTemplate 請求 restful 服務

藉助 RestTemplate,Spring應用能夠方便地使用REST資源 .Spring的 RestTemplate訪問使用了模版方法的設計模式.

2.Spring 中如何使用Rest資源

RestTemplate中定義了11個獨立的方法,分別是:

  • delete()  :在特定的URL上對資源執行HTTP DELETE操作
  • getForEntity() :傳送一個HTTP GET請求,返回的ResponseEntity包含了響應體所對映成的物件
  • getForObject() :傳送一個HTTP GET請求,返回的請求體將對映為一個自定義物件
  • postForEntity() :POST 資料到一個URL,返回包含一個物件的ResponseEntity,這個物件是從響應體中對映得到的
  • postForObject(): POST 資料到一個URL,返回根據響應體匹配形成的物件
  • headForHeaders(): 傳送HTTP HEAD請求,返回包含特定資源URL的HTTP頭
  • optionsForAllow() :傳送HTTP OPTIONS請求,返回對特定URL的Allow頭資訊
  • postForLocation(): POST 資料到一個URL,返回新建立資源的URL
  • put() :PUT 資源到特定的URL
  • execute() :在URL上執行特定的HTTP方法,返回一個從響應體對映得到的物件
  • exchange()  :在URL上執行特定的HTTP方法,返回包含物件的ResponseEntity,這個物件是從響應體中對映得到的

其中前十個方法分別有三個過載形式,以getForObject為例:第一個引數是介面的url,第二個引數是接收的返回值的型別,第三個是你要傳的引數,可以為多個Object物件,也可以是一個Map .而返回型別則是傳入第二個引數對應的型別.

 <T> T getForObject(String var1, Class<T> var2, Object... var3) throws RestClientException;

 <T> T getForObject(String var1, Class<T> var2, Map<String, ?> var3) throws RestClientException;

 <T> T getForObject(URI var1, Class<T> var2) throws RestClientException;

而最後一個exchange方法有8個過載形式,你可以自由的組裝REST呼叫方法,而返回的結果都是響應體所對映成的物件-ResponseEntity:

 <T> ResponseEntity<T> exchange(String var1, HttpMethod var2, HttpEntity<?> var3, Class<T> var4, Object... var5) throws RestClientException;

    <T> ResponseEntity<T> exchange(String var1, HttpMethod var2, HttpEntity<?> var3, Class<T> var4, Map<String, ?> var5) throws RestClientException;

    <T> ResponseEntity<T> exchange(URI var1, HttpMethod var2, HttpEntity<?> var3, Class<T> var4) throws RestClientException;

    <T> ResponseEntity<T> exchange(String var1, HttpMethod var2, HttpEntity<?> var3, ParameterizedTypeReference<T> var4, Object... var5) throws RestClientException;

    <T> ResponseEntity<T> exchange(String var1, HttpMethod var2, HttpEntity<?> var3, ParameterizedTypeReference<T> var4, Map<String, ?> var5) throws RestClientException;

    <T> ResponseEntity<T> exchange(URI var1, HttpMethod var2, HttpEntity<?> var3, ParameterizedTypeReference<T> var4) throws RestClientException;

    <T> ResponseEntity<T> exchange(RequestEntity<?> var1, Class<T> var2) throws RestClientException;

    <T> ResponseEntity<T> exchange(RequestEntity<?> var1, ParameterizedTypeReference<T> var2) throws RestClientException;

 

其中ResponseEntity物件繼承於HttpEntity ,在HttpEntity的基礎上又封裝了一個HttpStatus屬性 .

這樣如果返回ResponseEntity物件的話,我們可以拿到所有的關於請求的資訊,包括了 請求頭,請求狀態 ,和請求體的資訊.如:

 

例項:

介面提供方:

介面呼叫 :

@Service
@Transactional
public class XXXServiceImpl implements XXXService{



	@Autowired
	private XXXMapper mapper;
	@Autowired
	private RestTemplate restTemplate;


	private final static Logger logger = LoggerFactory.getLogger(XXXServiceImpl.class);


	@Value(value = "${esb.product.url}")
	private String  url;
	@Value(value = "${esb.product.username}")
	private  String  username;
	@Value(value = "${esb.product.password}")
	private  String  password;


	/**
	 * @Author younus
	 * @Description // 呼叫介面
	 * @Param
	 **/
	@Override
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	public void getEsbProductMultiples() {
		HttpHeaders headers = createHeaders(username, password);
		HttpEntity requestWithBasicAuth = new HttpEntity(headers);
		//介面返回的資料
		EsbProductMultiple datas= restTemplate.postForObject(url, requestWithBasicAuth, EsbProductMultiple.class);
		List<PubProductMutiple> pubProductMutiples=datas.getProductMutiples();
		if (pubProductMutiples != null && !pubProductMutiples.isEmpty()&& "S".equals(datas.getRetStatus())){
			//生成批次號
			String uuid= UUID.randomUUID().toString().replaceAll("-","");
			//具體業務邏輯
            
			}
		
	logger.info("-----------------------介面呼叫完成------------------------");
		}

	}

//模擬頭資訊
	private HttpHeaders createHeaders(String username, String password){
		return new HttpHeaders() {{
			String auth = username + ":" + password;
			byte[] encodedAuth = Base64.encodeBase64(
					auth.getBytes(Charset.forName("US-ASCII")) );
			String authHeader = "Basic " + new String( encodedAuth );
			set( "Authorization", authHeader );
		}};
	}
}

可以看到呼叫postForObject()會將結果封裝為我們自定義的物件.

 

excute方法

所有的get、post、delete、put、options、head、exchange方法最終呼叫的都是excute()方法,excute()方法只是將String格式的URI轉成了java.net.URI,之後呼叫了doExecute方法。舉個栗子:

public <T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Map<String, ?> urlVariables) throws RestClientException {
        RequestCallback requestCallback = this.acceptHeaderRequestCallback(responseType);
        ResponseExtractor<ResponseEntity<T>> responseExtractor = this.responseEntityExtractor(responseType);
        return (ResponseEntity)this.execute(url, HttpMethod.GET, requestCallback, responseExtractor, urlVariables);
    }

呼叫過程:

execute方法:

 public <T> T execute(String url, HttpMethod method, RequestCallback requestCallback, ResponseExtractor<T> responseExtractor, Object... urlVariables) throws RestClientException {
        URI expanded = this.getUriTemplateHandler().expand(url, urlVariables);
        return this.doExecute(expanded, method, requestCallback, responseExtractor);
    }