Spring RestTemplate配置及講解

HttpClient 與 RestTemplate 都是Java代碼發送http請求的工具。


HttpClient

  • HttpClient 是apache的開源,須要引入兩個包:httpclient-4.2.4.jar 和 httpcore-4.2.2.jar

RestTemplate

  • RestTemplate 是Spring的封裝,須要spring的包 spring-web-3.0.7.RELEASE.jar

  • 目前咱們使用Spring boot框架做爲開發主框架,如下對RestTemplate,以及咱們代碼中封裝的發送http請求的方法作一些講解。

同步RestTemplate配置

RestConfig.javajava

package com.shanyuan.platform.ms.base.rest.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

/**
* restTemplate配置
* @author yangjian 2017/09/28
*
*/
@Component
@Configuration
public class RestConfig {

@Bean
public RestTemplate restTemplate(ClientHttpRequestFactory factory){
return new RestTemplate(factory);
}

@Bean
public ClientHttpRequestFactory simpleClientHttpRequestFactory(){
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
factory.setReadTimeout(5000);//ms
factory.setConnectTimeout(15000);//ms
return factory;
}

}

異步RestTemplate配置

  • AsyncRestConfig.java
package com.shanyuan.platform.ms.base.rest.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.AsyncClientHttpRequestFactory;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.client.AsyncRestTemplate;

@Component
@Configuration
public class AsyncRestConfig {

@Bean
public AsyncRestTemplate asyncRestTemplate(){
return new AsyncRestTemplate();
}

public AsyncClientHttpRequestFactory clientHttpRequestFactory(){
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
factory.setReadTimeout(5000);
factory.setReadTimeout(5000);
return factory;

}
}

咱們項目中若是要使用Resttemplate註解的話須要對Bean進行配置。配置完成以後就能夠直接注入 RestTemplate 和 AsyncRestTemplate 進行get或者post或者其餘方式進行訪問了,目前最經常使用的請求方式爲get與post,因此代碼中只對這兩種請求進行了封裝,而且針對同一類型請求,基於參數以及其餘需求作了不一樣封裝。


  • RestService.java
package com.shanyuan.platform.ms.base.rest.service;

import java.util.HashMap;
import java.util.Map;

import org.springframework.http.HttpHeaders;
import org.springframework.util.LinkedMultiValueMap;

import com.alibaba.fastjson.JSONObject;
import com.shanyuan.platform.ms.base.common.ServiceResult;

/**
* restService接口
* @author yangjian 2017/09/28
*
*/
public interface RestService {

/**
* get請求
* @param map
* @param url
* @return
*/
public ServiceResult parseGetResult(Map<String, Object> map, String url);

/**
* get請求
* @param map
* @param url
* @return
*/
public ServiceResult parseGetResult(HashMap<String, Object> map, String url);

/**
* 無參或已拼接參數get請求
* @param url
* @return
*/
public ServiceResult parseGetResult(String url);

/**
* post請求
* @param map
* @param url
* @return
*/
public ServiceResult parsePostResult(LinkedMultiValueMap<String, Object> map, String url);

/**
* 帶有請求頭的post請求
* @param httpHeader
* @param params
* @param url
* @return
*/
public ServiceResult parsePostResultWithHeader(HttpHeaders httpHeader, JSONObject params, String url);

}

  • AsyncService.java
package com.shanyuan.platform.ms.base.rest.service;

import java.util.HashMap;
import java.util.Map;

import org.springframework.http.HttpHeaders;
import org.springframework.util.LinkedMultiValueMap;

import com.alibaba.fastjson.JSONObject;
import com.shanyuan.platform.ms.base.common.ServiceResult;

/**
* 異步rest請求接口
* @author win10
*
*/
public interface AsyncRestService {

/**
* get請求
* @param map
* @param url
* @return
*/
public ServiceResult parseGetResult(Map<String, Object> map, String url);

/**
* get請求
* @param url
* @return
*/
public ServiceResult parseGetResult(String url);

/**
* get請求
* @param map
* @param url
* @return
*/
public ServiceResult parseGetResult(HashMap<String, Object> map, String url);

/**
* post請求
* @param map
* @param url
* @return
*/
public ServiceResult parsePostResult(LinkedMultiValueMap<String, Object> map, String url);

/**
* 帶header的http請求
* @param headers
* @param params
* @param url
* @return
*/
public ServiceResult parsePostResultWithHeader(HttpHeaders headers, JSONObject params, String url);

}

  • 抽象接口,對不一樣請求方式及同一請求方式的不一樣實現進行封裝

  • RestServiceImpl.java
package com.shanyuan.platform.ms.base.rest.service.impl;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.web.client.RestTemplate;

import com.alibaba.fastjson.JSONObject;
import com.shanyuan.platform.ms.base.common.BaseService;
import com.shanyuan.platform.ms.base.common.ServiceResult;
import com.shanyuan.platform.ms.base.exception.CoreServiceExcepType;
import com.shanyuan.platform.ms.base.exception.CoreServiceException;
import com.shanyuan.platform.ms.base.rest.service.RestService;

@Service
public class RestServiceImpl extends BaseService implements RestService{

protected Logger logger = LoggerFactory.getLogger(getClass());

@Autowired
private RestTemplate restTemplate;

/**
* 發送get請求
* @param map 參數map
* @param url 請求地址,參數拼接在連接中,用通配符表明
* 示例 :
* Map<String, Object> map = new HashMap<String, Object>;
* map.put("channel", 1);
* map.put("goodsId", 2);
* String url = "http://localhost:8083/goods/goodsIndex?channel={channel}&goods_id={goodsId}";
* 根據實際狀況本身添加參數
* @return
*/
@Override
public ServiceResult parseGetResult(Map<String, Object> map, String url){
ServiceResult result = new ServiceResult();
try {
String sResult = restTemplate.getForObject(url, String.class, map);
JSONObject jResult = JSONObject.parseObject(sResult);
result = buildSuccessResult(jResult);
} catch (CoreServiceException e) {
result = buildErrorResult("url:"+ url +"請求失敗");
logger.info("url:{}, map:{},請求失敗", url, map);
e = new CoreServiceException(CoreServiceExcepType.REQUEST_CODE, "請求失敗");
e.printStackTrace();
}

return result;
}

/**
* 發送get請求
* @param map 參數map
* @param url 請求地址,地址中不須要拼接參數,在方法中處理
* 示例 :
* HashMap<String, Object> map = new HashMap<String, Object>;
* map.put("channel", 1);
* map.put("goodsId", 2);
* String url = "http://localhost:8083/goods/goodsIndex";
* 根據實際狀況本身添加參數
* @return
*/
@Override
public ServiceResult parseGetResult(HashMap<String, Object> map, String url) {
StringBuilder sb = new StringBuilder();
sb.append(url);
if(!CollectionUtils.isEmpty(map)){
Set keys = map.keySet();
sb.append("?");
for (String string : keys) {
sb.append(string);
sb.append("=");
sb.append(map.get(string).toString());
sb.append("&");
}
}
String finalUrl = sb.toString();
if(finalUrl.endsWith("&")){
finalUrl = finalUrl.substring(0, finalUrl.length() - 1);
}
ServiceResult result = this.parseGetResult(finalUrl);
return result;
}

/**
* 發送get請求
* @param url 請求地址
* 請求爲純字符串,能夠是無參數的get請求,也能夠是將參數的K V都拼接好傳入
* 示例
* 一、http://localhost:8083/goods/goodsIndex
* 二、http://localhost:8083/goods/goodsIndex?channel=1&goods_id=2
* 以上兩種方式都支持
* @return
*
*/
@Override
public ServiceResult parseGetResult(String url) {
ServiceResult result = new ServiceResult();
try {
String sResult = restTemplate.getForObject(url, String.class);
JSONObject jResult = JSONObject.parseObject(sResult);
result = buildSuccessResult(jResult);
} catch (CoreServiceException e) {
result = buildErrorResult("url:"+ url +"請求失敗");
logger.info("url:{}, map:{},請求失敗", url);
e = new CoreServiceException(CoreServiceExcepType.REQUEST_CODE, "請求失敗");
e.printStackTrace();
}

return result;
}

/**
* 發送post請求
* @param map 請求參數集合
* @param 請求地址
* 示例:
* MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
* map.add("channel", 1);
* map.add("goods_id", 2);
* String url = "http://localhost:8083/goods/goodsIndex";
* 根據實際狀況本身添加參數
* @return
*/
@Override
public ServiceResult parsePostResult(LinkedMultiValueMap<String, Object> map, String url) {
ServiceResult result = new ServiceResult();
try{
String sResult = restTemplate.postForObject(url, map, String.class);
JSONObject jResult = JSONObject.parseObject(sResult);
result = buildSuccessResult(jResult);
}catch (CoreServiceException e) {
result = buildErrorResult("url:"+ url +"請求失敗");
logger.info("url:{}, map:{},請求失敗", url, map);
e = new CoreServiceException(CoreServiceExcepType.REQUEST_CODE, "請求失敗");
e.printStackTrace();
}
return result;
}

/**
* 帶header的http post請求
* header中的值能夠本身設置
*/
@Override
public ServiceResult parsePostResultWithHeader(HttpHeaders httpHeader, JSONObject params, String url) {
ServiceResult result = new ServiceResult();
try{
HttpEntity<Map<String, Object>> httpEntity = new HttpEntity<Map<String,Object>>(params, httpHeader);
ResponseEntity exchange = restTemplate.exchange(url, HttpMethod.POST, httpEntity, String.class);
JSONObject jResult = JSONObject.parseObject(exchange.getBody());
result = buildSuccessResult(jResult);
}catch (Exception e) {
logger.info("url:{}, map:{},請求失敗", url, params);
result = buildErrorResult("url:" + url + "請求失敗");
}
return result;
}

}

  • AsyncServiceImpl.java
package com.shanyuan.platform.ms.base.rest.service.impl;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.StringUtils;
import org.springframework.util.concurrent.ListenableFuture;
import org.springframework.util.concurrent.ListenableFutureCallback;
import org.springframework.web.client.AsyncRestTemplate;

import com.alibaba.fastjson.JSONObject;
import com.shanyuan.platform.ms.base.common.BaseService;
import com.shanyuan.platform.ms.base.common.ServiceResult;
import com.shanyuan.platform.ms.base.exception.CoreServiceExcepType;
import com.shanyuan.platform.ms.base.exception.CoreServiceException;
import com.shanyuan.platform.ms.base.rest.service.AsyncRestService;

/**
*
* @author yangjian 2017/09/28
*
*/
@Service
public class AsyncRestServiceImpl extends BaseService implements AsyncRestService {

protected Logger logger = LoggerFactory.getLogger(getClass());

@Autowired
private AsyncRestTemplate restTemplate;

/**
* 發送get請求
* @param map 參數map
* @param url 請求地址,參數拼接在連接中,用通配符表明
* 示例 :
* Map<String, Object> map = new HashMap<String, Object>;
* map.put("channel", 1);
* map.put("goodsId", 2);
* String url = "http://localhost:8083/goods/goodsIndex?channel={channel}&goods_id={goodsId}";
* 根據實際狀況本身添加參數
* @return
*/
@Override
public ServiceResult parseGetResult(Map<String, Object> map, String url) {

ServiceResult result = new ServiceResult();
ListenableFuture<ResponseEntity> forEntity = restTemplate.getForEntity(url, String.class, map);
forEntity.addCallback(new ListenableFutureCallback<ResponseEntity>() {
public void onSuccess(ResponseEntity resp) {
String sResult = resp.getBody();
if(!StringUtils.isEmpty(sResult)){
JSONObject jResult = JSONObject.parseObject(sResult);
result.setContent(jResult);
result.setCode(CODE_SUCCESS);
result.setMessage("success");
logger.info("url:{}, map:{} 請求成功", url, map);
}else{
this.onFailure(new Throwable(new CoreServiceException(CoreServiceExcepType.REQUEST_CODE, "請求結果爲空")));
}
}
public void onFailure(Throwable t) {
result.setMessage(t.getMessage());
result.setCode(CODE_ERROR);
t.printStackTrace();
logger.info("url:{}, map:{} 請求失敗", url, map);
}
});

return result;
}

/**
* 發送get請求
* @param url 請求地址
* 請求爲純字符串,能夠是無參數的get請求,也能夠是將參數的K V都拼接好傳入
* 示例
* 一、http://localhost:8083/goods/goodsIndex
* 二、http://localhost:8083/goods/goodsIndex?channel=1&goods_id=2
* 以上兩種方式都支持
* @return
*
*/
@Override
public ServiceResult parseGetResult(String url) {
ServiceResult result = new ServiceResult();
ListenableFuture<ResponseEntity> forEntity = restTemplate.getForEntity(url, String.class);
forEntity.addCallback(new ListenableFutureCallback<ResponseEntity>() {
public void onSuccess(ResponseEntity resp) {
String sResult = resp.getBody();
if(!StringUtils.isEmpty(sResult)){
JSONObject jResult = JSONObject.parseObject(sResult);
result.setContent(jResult);
result.setCode(CODE_SUCCESS);
result.setMessage("success");
logger.info("url:{} 請求成功", url);
}else{
this.onFailure(new Throwable(new CoreServiceException(CoreServiceExcepType.REQUEST_CODE, "請求結果爲空")));
}
}
public void onFailure(Throwable t) {
result.setMessage(t.getMessage());
result.setCode(CODE_ERROR);
t.printStackTrace();
logger.info("url:{} 請求失敗", url);
}
});

return result;
}

/**
* 發送get請求
* @param map 參數map
* @param url 請求地址,地址中不須要拼接參數,在方法中處理
* 示例 :
* HashMap<String, Object> map = new HashMap<String, Object>;
* map.put("channel", 1);
* map.put("goodsId", 2);
* String url = "http://localhost:8083/goods/goodsIndex";
* 根據實際狀況本身添加參數
* @return
*/
@Override
public ServiceResult parseGetResult(HashMap<String, Object> map, String url) {
StringBuilder sb = new StringBuilder();
sb.append(url);
if(!CollectionUtils.isEmpty(map)){
Set keys = map.keySet();
sb.append("?");
for (String string : keys) {
sb.append(string);
sb.append("=");
sb.append(map.get(string).toString());
sb.append("&");
}
}
String finalUrl = sb.toString();
if(finalUrl.endsWith("&")){
finalUrl = finalUrl.substring(0, finalUrl.length() - 1);
}
ServiceResult result = this.parseGetResult(finalUrl);
return result;
}

/**
* 發送post請求
* @param map 請求參數集合
* @param 請求地址
* 示例:
* MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
* map.add("channel", 1);
* map.add("goods_id", 2);
* String url = "http://localhost:8083/goods/goodsIndex";
* 根據實際狀況本身添加參數
* @return
*/
@Override
public ServiceResult parsePostResult(LinkedMultiValueMap<String, Object> map, String url) {
ServiceResult result = new ServiceResult();
String header = "";
HttpEntity httpEntity = new HttpEntity(header);
ListenableFuture<ResponseEntity> forEntity = restTemplate.postForEntity(url, httpEntity, String.class, map);
forEntity.addCallback(new ListenableFutureCallback<ResponseEntity>() {
public void onSuccess(ResponseEntity resp) {
String sResult = resp.getBody();
if(!StringUtils.isEmpty(sResult)){
JSONObject jResult = JSONObject.parseObject(sResult);
result.setContent(jResult);
result.setCode(CODE_SUCCESS);
result.setMessage("success");
logger.info("url:{}, map:{} 請求成功", url, map);
}else{
this.onFailure(new Throwable(new CoreServiceException(CoreServiceExcepType.REQUEST_CODE, "請求結果爲空")));
}
}
public void onFailure(Throwable t) {
result.setMessage(t.getMessage());
result.setCode(CODE_ERROR);
t.printStackTrace();
logger.info("url:{}, map:{} 請求失敗", url, map);
}
});
return result;
}

@Override
public ServiceResult parsePostResultWithHeader(HttpHeaders headers, JSONObject params, String url) {
ServiceResult result = new ServiceResult();
HttpEntity httpEntity = new HttpEntity(headers);
ListenableFuture<ResponseEntity> forEntity = restTemplate.postForEntity(url, httpEntity, String.class, params);
forEntity.addCallback(new ListenableFutureCallback<ResponseEntity>() {
public void onSuccess(ResponseEntity resp) {
String sResult = resp.getBody();
if(!StringUtils.isEmpty(sResult)){
JSONObject jResult = JSONObject.parseObject(sResult);
result.setContent(jResult);
result.setCode(CODE_SUCCESS);
result.setMessage("success");
logger.info("url:{}, map:{} 請求成功", url, params);
}else{
this.onFailure(new Throwable(new CoreServiceException(CoreServiceExcepType.REQUEST_CODE, "請求結果爲空")));
}
}
public void onFailure(Throwable t) {
result.setMessage(t.getMessage());
result.setCode(CODE_ERROR);
t.printStackTrace();
logger.info("url:{}, map:{} 請求失敗", url, params);
}
});
return result;
}

}

以上是對上邊接口的實現,具體參數說明都已經寫到註釋裏邊,有不清楚的問題能夠一塊兒討論。

補充:目前已經咱們項目中已經不使用這種方式去調用接口了,直接用SpringBoot中Feign組件了。

相關文章
相關標籤/搜索