RestTemplate详解
程序员文章站
2022-04-28 17:29:33
...
概述
当我们在开发项目的过程中,一个系统中要请求另外一个服务中的接口,那么通常是用过http请求,需要有个httpClient类:类似代码如下:
import com.alibaba.fastjson.JSONObject;
/**
* HttpClient4.3工具类
* @author tech
* @date 2016-03-29
*
*/
public class HttpClientUtils {
private static Logger logger = LoggerFactory.getLogger(HttpClientUtils.class); //日志记录
/**
* httpPost
* @param url 路径
* @param jsonParam 参数
* @return
*/
public static JSONObject httpPost(String url,JSONObject jsonParam){
return httpPost(url, jsonParam, false);
}
/**
* post请求
* @param url url地址
* @param jsonParam 参数
* @param noNeedResponse 不需要返回结果
* @return
*/
public static JSONObject httpPost(String url,JSONObject jsonParam, boolean noNeedResponse){
//post请求返回结果
CloseableHttpClient httpClient = HttpClients.createDefault();
JSONObject jsonResult = null;
HttpPost httpPost = new HttpPost(url);
//设置请求和传输超时时间
RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(2000).setConnectTimeout(2000).build();
httpPost.setConfig(requestConfig);
try {
if (null != jsonParam) {
//解决中文乱码问题
StringEntity entity = new StringEntity(jsonParam.toString(), "utf-8");
entity.setContentEncoding("UTF-8");
entity.setContentType("application/json");
httpPost.setEntity(entity);
}
CloseableHttpResponse result = httpClient.execute(httpPost);
/**请求发送成功,并得到响应**/
if (result.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
String str = "";
try {
/**读取服务器返回过来的json字符串数据**/
str = EntityUtils.toString(result.getEntity(), "utf-8");
if (noNeedResponse) {
return null;
}
/**把json字符串转换成json对象**/
jsonResult = JSONObject.parseObject(str);
} catch (Exception e) {
logger.error("post请求提交失败:" + url, e);
}
}
} catch (IOException e) {
logger.error("post请求提交失败:" + url, e);
} finally{
httpPost.releaseConnection();
}
return jsonResult;
}
/**
* 发送get请求
* @param url 路径
* @return
*/
public static JSONObject httpGet(String url){
//get请求返回结果
JSONObject jsonResult = null;
CloseableHttpClient client = HttpClients.createDefault();
//发送get请求
HttpGet request = new HttpGet(url);
//设置请求和传输超时时间
RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(2000).setConnectTimeout(2000).build();
request.setConfig(requestConfig);
try {
CloseableHttpResponse response = client.execute(request);
/**请求发送成功,并得到响应**/
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
/**读取服务器返回过来的json字符串数据**/
HttpEntity entity = response.getEntity();
String strResult = EntityUtils.toString(entity, "utf-8");
/**把json字符串转换成json对象**/
jsonResult = JSONObject.parseObject(strResult);
} else {
logger.error("get请求提交失败:" + url);
}
} catch (IOException e) {
logger.error("get请求提交失败:" + url, e);
} finally{
request.releaseConnection();
}
return jsonResult;
}
}
今天讲一下spring中另外一种请求方式,通过RestTemplate 这个模板类:
RestTemplate与httpClient类似,都是java中可以模拟http请求的封装。但是RestTemplate比httpClient更优雅,它是spring中的一个封装功能。
RestTemplate也是java中的模板类。采用的设计模式中的模板模式。
源码解析
RestTemplate继承InterceptingHttpAccessor抽象类,实现RestOperation接口。
public class RestTemplate extends InterceptingHttpAccessor implements RestOperations
在RestOperations定义了基本的Rest操作集合。RestTemplate实现了这个接口。
public interface RestOperations {
// GET
<T> T getForObject(String url, Class<T> responseType, Object... uriVariables) throws RestClientException;
<T> T getForObject(String url, Class<T> responseType, Map<String, ?> uriVariables) throws RestClientException;
<T> T getForObject(URI url, Class<T> responseType) throws RestClientException;
<T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Object... uriVariables) throws RestClientException;
<T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Map<String, ?> uriVariables) throws RestClientException;
<T> ResponseEntity<T> getForEntity(URI url, Class<T> responseType) throws RestClientException;
// HEAD
HttpHeaders headForHeaders(String url, Object... uriVariables) throws RestClientException;
HttpHeaders headForHeaders(String url, Map<String, ?> uriVariables) throws RestClientException;
HttpHeaders headForHeaders(URI url) throws RestClientException;
// POST
URI postForLocation(String url, Object request, Object... uriVariables) throws RestClientException;
URI postForLocation(String url, Object request, Map<String, ?> uriVariables) throws RestClientException;
URI postForLocation(URI url, Object request) throws RestClientException;
<T> T postForObject(String url, Object request, Class<T> responseType, Object... uriVariables)
throws RestClientException;
<T> T postForObject(String url, Object request, Class<T> responseType, Map<String, ?> uriVariables)
throws RestClientException;
<T> T postForObject(URI url, Object request, Class<T> responseType) throws RestClientException;
<T> ResponseEntity<T> postForEntity(String url, Object request, Class<T> responseType, Object... uriVariables)
throws RestClientException;
<T> ResponseEntity<T> postForEntity(String url, Object request, Class<T> responseType, Map<String, ?> uriVariables)
throws RestClientException;
<T> ResponseEntity<T> postForEntity(URI url, Object request, Class<T> responseType) throws RestClientException;
// PUT
void put(String url, Object request, Object... uriVariables) throws RestClientException;
void put(String url, Object request, Map<String, ?> uriVariables) throws RestClientException;
void put(URI url, Object request) throws RestClientException;
// PATCH
<T> T patchForObject(String url, Object request, Class<T> responseType, Object... uriVariables)
throws RestClientException;
<T> T patchForObject(String url, Object request, Class<T> responseType, Map<String, ?> uriVariables)
throws RestClientException;
<T> T patchForObject(URI url, Object request, Class<T> responseType) throws RestClientException;
// DELETE
void delete(String url, Object... uriVariables) throws RestClientException;
void delete(String url, Map<String, ?> uriVariables) throws RestClientException;
void delete(URI url) throws RestClientException;
// OPTIONS
Set<HttpMethod> optionsForAllow(String url, Object... uriVariables) throws RestClientException;
Set<HttpMethod> optionsForAllow(String url, Map<String, ?> uriVariables) throws RestClientException;
Set<HttpMethod> optionsForAllow(URI url) throws RestClientException;
// exchange
<T> ResponseEntity<T> exchange(String url, HttpMethod method, HttpEntity<?> requestEntity,
Class<T> responseType, Object... uriVariables) throws RestClientException;
<T> ResponseEntity<T> exchange(String url, HttpMethod method, HttpEntity<?> requestEntity,
Class<T> responseType, Map<String, ?> uriVariables) throws RestClientException;
<T> ResponseEntity<T> exchange(URI url, HttpMethod method, HttpEntity<?> requestEntity,
Class<T> responseType) throws RestClientException;
<T> ResponseEntity<T> exchange(String url,HttpMethod method, HttpEntity<?> requestEntity,
ParameterizedTypeReference<T> responseType, Object... uriVariables) throws RestClientException;
<T> ResponseEntity<T> exchange(String url, HttpMethod method, HttpEntity<?> requestEntity,
ParameterizedTypeReference<T> responseType, Map<String, ?> uriVariables) throws RestClientException;
<T> ResponseEntity<T> exchange(URI url, HttpMethod method, HttpEntity<?> requestEntity,
ParameterizedTypeReference<T> responseType) throws RestClientException;
<T> ResponseEntity<T> exchange(RequestEntity<?> requestEntity, Class<T> responseType) throws RestClientException;
<T> ResponseEntity<T> exchange(RequestEntity<?> requestEntity, ParameterizedTypeReference<T> responseType)
throws RestClientException;
// general execution
<T> T execute(String url, HttpMethod method, RequestCallback requestCallback,
ResponseExtractor<T> responseExtractor, Object... uriVariables) throws RestClientException;
<T> T execute(String url, HttpMethod method, RequestCallback requestCallback,
ResponseExtractor<T> responseExtractor, Map<String, ?> uriVariables) throws RestClientException;
<T> T execute(URI url, HttpMethod method, RequestCallback requestCallback,
ResponseExtractor<T> responseExtractor) throws RestClientException;
}
PostForObject与PostForEntity的区别在于前者请求返回就是响应体,后者返回的是响应行,响应头,响应体。
这里也有一个基础的http访问类HttpAccessor,里面主要是一个工厂方法,用来构造HttpRequestFactory。
public abstract class HttpAccessor {
protected final Log logger = LogFactory.getLog(getClass());
private ClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
public void setRequestFactory(ClientHttpRequestFactory requestFactory) {
Assert.notNull(requestFactory, "ClientHttpRequestFactory must not be null");
this.requestFactory = requestFactory;
}
public ClientHttpRequestFactory getRequestFactory() {
return this.requestFactory;
}
protected ClientHttpRequest createRequest(URI url, HttpMethod method) throws IOException {
ClientHttpRequest request = getRequestFactory().createRequest(url, method);
if (logger.isDebugEnabled()) {
logger.debug("Created " + method.name() + " request for \"" + url + "\"");
}
return request;
}
}
springboot对RestTemplate的集成
1.首先添加配置
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate(){
RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
return restTemplate;
}
}
不然在service中的autowired会注入不进去
2.再设置请求头
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
3.请求行,请求头,请求体分装成 一个Entity
HttpEntity<String> entity = new HttpEntity<>(JSONObject.toJSONString(dto),headers );
4.接下来就调用
ResponseEntity r = restTemplate.exchange(ADD_URL, HttpMethod.POST, entity, String.class);
那就可以请求到结果了。