HTTP工具类
说明
每个服务发展到一定阶段,必不可少的需要调用外部服务,目前最常见,最通用的就是HTTP协议了,由此我们发展出来HTTP工具类。每个团队发展出了适合自己用的Http工具类,拿我个人举例,根据我不同阶段不同水平接触它,对它的要求也越来越不一样:
实现功能即可 ----> 要求简洁方便,一句代码解决 ----> 功能强大,支持我的各种header需求,支持Https,各种返回类型的需求(能转化成我想要的java对象最好了) ----> 还要能看到状态码,异常不要自己说吃掉就吃掉 ----> 需要支持我的请求和响应日志,同时不要把我最烦人的日志打印出来(文件流) ----> 考虑到以后业务需求,我还想在请求前和请求后做点东西,统一处理部分Http,要求动态扩展 ---->支持这么多功能,仍要有一套统一的调用方法,最终要简单易用
慢慢的将Http工具基于Http Client完善,臃肿,参考,补充,重构,最终形成了一个比较完善的Http工具类。这些都是踩过坑才会慢慢考虑到,逐渐完善的,或许还不够完善不够规范,但是突然发现Spring
已经给我们提供了这样的工具类RestTemplate
,以上说的功能一个不少,果然出于真实践。
RestTemplate
自Spring 3.0
就有了,它不是HttpClient
或HttpConnection
的替代品,而是基于这写Http
请求框架二次封装简单易用的工具类。它会替你屏蔽底层枯燥重复的Http
请求封装,向上提供一个功能齐全强大的Http工具。Spring
真正吸引人的不仅仅是一个java
框架这么简单,它会站在我们的立场考虑,充分考虑到我们的需求,最终给我们提供最简单易用的一套解决方法。
举几个简单的例子:
- 简单
Get
请求,获取状态码,获取body体
@Test
public void testGet() {
ResponseEntity<String> responseEntity = restTemplate.getForEntity("http://www.baidu.com", String.class);
System.out.println("statusCode : " + responseEntity.getStatusCodeValue());
System.out.println("body : " + responseEntity.getBody());
System.out.println("body : " + responseEntity.toString());
}
- 获取字节流
@Test
public void testGetByteBody() {
ResponseEntity<byte[]> responseEntity = restTemplate.getForEntity("http://192.168.24.119/downlaod.jpg", byte[].class);
System.out.println("statusCode : " + responseEntity.getStatusCodeValue());
System.out.println("body : " + Arrays.toString(responseEntity.getBody()));
}
- 自定义请求头,获取想要的
Java
实体
@Test
public void testPostWithJsonObject() {
// add jsonConvert
restTemplate.getMessageConverters().add(new FastJsonHttpMessageConverter());
Map<String, String> postBody = new HashMap<>();
postBody.put("username","1");
postBody.put("password","12312");
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.add(HttpHeaders.CONTENT_TYPE, "application/json");
HttpEntity<Map<String,String>> httpRequest = new HttpEntity<>(postBody, httpHeaders);
ResponseEntity<byte[]> responseEntity = restTemplate.postForEntity("http://192.168.24.119/login", httpRequest, byte[].class);
System.out.println("statusCode : " + responseEntity.getStatusCodeValue());
System.out.println("body : " + new String(responseEntity.getBody()));
}
- 自定义选择Http请求框架(默认
httpConnection
)
@Bean
public ClientHttpRequestFactory getClientHttpRequestFactory(HttpClientBuilder httpClientBuilder) {
ClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClientBuilder.build());
return requestFactory;
}
- 同Spring MVC 实体转化
MessageConvert
配置
@Bean
public RestTemplate getRestTemplate(ClientHttpRequestFactory requestFactory) {
RestTemplate restTemplate = new RestTemplate();
restTemplate.setRequestFactory(requestFactory);
restTemplate.setMessageConverters(Arrays.<HttpMessageConverter<?>>asList(
new StringHttpMessageConverter(StandardCharsets.UTF_8),
new ByteArrayHttpMessageConverter()));
return restTemplate;
}
- 面向切面请求的
filter
,你可以在请求前和请求后做些事
restTemplate.getInterceptors().add((request, bytesBody, execution)->{
return execution.execute(request, bytesBody);
});
- 自定义异常处理机制
restTemplate.setErrorHandler(new ResponseErrorHandler() {
@Override
public boolean hasError(ClientHttpResponse response) throws IOException {
return false;
}
@Override
public void handleError(ClientHttpResponse response) throws IOException {
}
});
配置
RestTemplate
实例仅需要配置ClientHttpRequestFactory
配置HttpClientBuilder
请求框架
@Bean
public HttpClientBuilder getHttpClientBuilder() throws KeyManagementException, NoSuchAlgorithmException {
HttpClientBuilder consumer = HttpClients.custom();
PoolingHttpClientConnectionManager poolingHttpClientConnectionManager = new PoolingHttpClientConnectionManager(RegistryBuilder.<ConnectionSocketFactory>create()
.register("https", new SSLConnectionSocketFactory(SSLContextBuilder.create().build()))
.register("http", new PlainConnectionSocketFactory())
.build());
consumer.setConnectionManager(poolingHttpClientConnectionManager);
return consumer;
}
配置ClientHttpRequestFactory
@Bean
public ClientHttpRequestFactory getClientHttpRequestFactory(HttpClientBuilder httpClientBuilder) {
ClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClientBuilder.build());
return requestFactory;
}
配置RestTemplate
@Bean
public RestTemplate getRestTemplate(ClientHttpRequestFactory requestFactory) {
RestTemplate restTemplate = new RestTemplate();
restTemplate.setRequestFactory(requestFactory);
restTemplate.setMessageConverters(Arrays.<HttpMessageConverter<?>>asList(
new StringHttpMessageConverter(StandardCharsets.UTF_8),
new ByteArrayHttpMessageConverter()));
return restTemplate;
}
完毕
简单用法
restTemplate
使用方法比较简单,这里举几个比较典型的例子
restTemplate.execute(Url, HttpMethod, RequestCallback, ResponseExtractor)
最基本最全的执行方法。第一个参数Url
简明旨意;第二个参数Httpmethod
请求方法;第三个参数RequestCallback
是一个请求前的拦截器,在这里可以对请求头,请求体做出自定义的操作;第四个参数ResponseExtractor
是请求执行后的拦截器,或者说是一个提取器,自定义转化并返回一个结果。
该方法的返回值就是ResponseExtractor
的返回值。
restTemplate.exchange(Url, HttpMethod, HttpEntity, Type, uriVars...)
在restTemplate.execute
上封装,第三个参数HttpEntity
可以设置headers
和body
,它实现的功能也是在RequestCallback
基础上实现的;第四个参数Type
代表你希望接收一个什么样的返回值(当然,你需要有一个自定义实现的ResponseExtractor
, 也就是MessageConvert
);第五个参数为url
上变量值的替换具体值。
该方法返回一个ResponseEntity<T>
类型的返回值,其中T
就是第三个参数对应的返回类型,可以通过getBody
获取,除此之外ResponseEntity
还能获得状态码,headers
等信息
restTemplate.postForEntity(URL,Request, Type, uriVars...)
进一步封装,将请求方法写到方法名上
restTemplate.postForObject(URL,Request, Type, uriVars...)
再封装,如果你只关心值,restTemplate.postForObject
可以让你直接获取你想要的值。它的返回值类型直接就是第三个参数Type
的值
restTemplate.postForLocation(Url,Request)
postForLocation
方法是另一种用法,它针对post
请求,返回的状态码为302
的请求,获取其header
中Location
的值
总结
总结来说,关于RestTemplate
从配置到使用来说是比较简单的,看着方法就能猜出来其使用的途径,但是又包装的恰到好处,各个设计模式用的也非常6,称之为规范一点都不过分。
网友评论