commons.tools.utils.HttpContextUtils Http工具类
HTTP工具类
背景
每个服务发展到一定阶段,必不可少的需要调用外部服务,目前最常见,最通用的就是HTTP协议了,由此我们发展出来HTTP工具类。每个团队发展出了适合自己用的Http工具类,拿我个人举例,根据我不同阶段不同水平接触它,对它的要求也越来越不一样:
step 1:
实现功能即可。step 2:
要求简洁方便,一句代码解决。step 3:
功能强大,支持我的各种header
需求,支持Https
,各种返回类型的需求(能转化成我想要的java
对象最好了)。step 4:
还要能看到状态码,异常不要自己说吃掉就吃掉 。需要支持我的请求和响应日志,同时不要把我最烦人的日志打印出来(文件流) 。step 5:
考虑到以后业务需求,我还想在请求前和请求后做点东西,统一处理部分Http
,要求动态扩展 。step 6:
支持这么多功能,仍要有一套统一的调用方法,最终要简单易用。
经历完这些阶段,之前自己设计的HttpUtil.java
也经历了:简单封装,完善,解耦,参考,补充,重构等这些阶段。
回头想想,其实这些不仅仅是个人或者某个公司才有的需求或问题,是Java web
一个组件问题,其他人有没有什么更完善的解决方法呢。最终发现Spring
已经给我们提供了这样的工具类RestTemplate
,以上说的功能一个不少,果然出于真实践。
RestTemplate组件
RestTemplate
自Spring 3.0
就有了,它不是HttpClient
或HttpConnection
的替代品,而是基于这写Http
请求框架二次封装简单易用的工具类。它会替你屏蔽底层枯燥重复的Http
请求封装,向上提供一个功能齐全强大的Http工具。Spring
真正吸引人的不仅仅是一个java
框架这么简单,它会站在我们的立场考虑,充分考虑到我们的需求,最终给我们提供最简单易用的一套解决方法。
配置
RestTemplate
实例仅需要配置ClientHttpRequestFactory
配置RestTemplate
//http builder
@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;
}
// clientHttpFactory
@Bean
public ClientHttpRequestFactory getClientHttpRequestFactory(HttpClientBuilder httpClientBuilder) {
ClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClientBuilder.build());
return requestFactory;
}
// restTempalteBean
@Bean
public RestTemplate getRestTemplate(ClientHttpRequestFactory requestFactory) {
RestTemplate restTemplate = new RestTemplate();
restTemplate.setRequestFactory(requestFactory);
//类Spring MVC中的自定义消息转化
restTemplate.setMessageConverters(Arrays.<HttpMessageConverter<?>>asList(
new StringHttpMessageConverter(StandardCharsets.UTF_8),
new ByteArrayHttpMessageConverter()));
//自定义异常处理
restTemplate.setErrorHandler(new ResponseErrorHandler() {
@Override
public boolean hasError(ClientHttpResponse response) throws IOException {
return false;
}
@Override
public void handleError(ClientHttpResponse response) throws IOException {
}
});
//面向切面请求的filter,你可以在请求前和请求后做些事
restTemplate.getInterceptors().add((request, bytesBody, execution)->{
return execution.execute(request, bytesBody);
});
return restTemplate;
}
使用
举几个简单的例子:
- 简单
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()));
}
完毕
其他用法
restTemplate
整体使用方法是比较简单的,这里讲解几个比较核心的方法
/**
* 最基本最全的执行方法
* @param url 请求地址
* @param HttpMethod 请求方法
* @param RequestCallback 是一个请求前的拦截器,在这里可以对请求头,请求体做出自定义的操作
* @param ResponseExtractor 是请求执行后的拦截器,或者说是一个提取器,自定义转化并返回一个结果。
* @return ResponseExtractor 非常有意思的返回结果
**/
ResponseExtractor restTemplate.execute(Url, HttpMethod, RequestCallback, ResponseExtractor)
/**
* 在restTemplate.execute上封装,可以将返回结果转化成基本的bean并返回
* @param url 请求地址
* @param HttpMethod 请求方法
* @param HttpEntity 参数HttpEntity可以设置headers和body,它实现的功能也是在RequestCallback基础上实现的
* @param Type 代表你希望接收一个什么样的返回值(当然,你需要有一个自定义实现的ResponseExtractor, 也就是MessageConvert)
* @param UriVars url上的变量值的替换具体值
* @return ResponseEntity<T> 其中T就是第三个参数对应的返回类型,可以通过getBody获取,除此之外ResponseEntity还能获得状态码,headers等信息
**/
ResponseEntity<T> restTemplate.exchange(Url, HttpMethod, HttpEntity, Type, UriVars...)
/**
* 进一步封装,将请求方法写到方法名上
**/
ResponseEntity<T> restTemplate.postForEntity(URL,Request, Type, uriVars...)
/**
* 再进一步封装,如果你只关心值,该方法可以让你直接获取你想要的值。它的返回值类型直接就是第三个参数`Type`的值
**/
<T> restTemplate.postForObject(URL,Request, Type, uriVars...)
/**
* 它针对`post`请求,返回的状态码为`302`的请求,获取其header中Location(重定向后的URL)的值
**/
URI restTemplate.postForLocation(Url,Request)
总结
总结来说,关于RestTemplate
从配置到使用来说是比较简单的,看着方法就能猜出来其使用的途径,但是又包装的恰到好处,各个设计模式用的也非常6,称之为规范一点都不过分
来源:{
作者:新签名
链接:https://www.jianshu.com/p/df7cbf2d07eb
链接:https://www.jianshu.com/p/df7cbf2d07eb
}