背景
学习记录一种请求方式
分析
逻辑
简单
代码量
少
维护
中等
更新
Spring5 推荐是WebClient 用于替换RestTemplate
提供了很多工厂配置类,根据具体需求进行对请求或响应做出处理,且提供了许多的API供使用
RestTemplateClient
RestTemplateClient() //构造方法用于初始化配置
BufferingClientHttpRequestFactory(ClientHttpRequestFactory factory) //缓存工厂,用来获取多次Body内容,RestTemplate如果不配置该工厂则只能获取一次Body内容
new RestTemplateClientConfig() //自定义的工厂配置类
继承SimpleClientHttpRequestFactory类,重写prepareConnection方法获取底层链接,将链接封装一层SSLSocket工厂,用来支持HTTPS协议,也可以做其他处理
实现ClientHttpRequestInterceptor接口 intercept方法 用于拦截请求 (打印日志或者夹带私货)
rest(请求路径,请求方式,请求头,返回类型,请求体) //调用者调用 可以根据业务逻辑增加参数
代码
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.RequestEntity;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.BufferingClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
import java.net.URI;
import java.util.Collections;
public class RestTemplateClient {
@Resource
private RestTemplate restTemplate;
public RestTemplateClient() {
BufferingClientHttpRequestFactory bufferFactory = new BufferingClientHttpRequestFactory(new RestTemplateClientConfig());
restTemplate = new RestTemplate(bufferFactory);
restTemplate.setInterceptors(Collections.singletonList(new RestTemplateClientConfig()));
}
public <T> ResponseEntity<T> rest(String path, HttpMethod method, HttpHeaders headers, Class<T> tClass, Object o) {
if (headers == null) {
headers = new HttpHeaders();
headers.put("Accept", Collections.singletonList("*/*"));
headers.put("Content-Type", Collections.singletonList("application/json;charset=utf-8"));
}
RequestEntity<Object> request = new RequestEntity<>(o, headers, method, URI.create(path));
return rest(path, method, request, tClass);
}
public <T> ResponseEntity<T> rest(String uri, HttpMethod method, RequestEntity<?> request, Class<T> c) {
return restTemplate.exchange(URI.create(uri), method, request, c);
}
}
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import javax.net.ssl.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
@Slf4j
public class RestTemplateClientConfig extends SimpleClientHttpRequestFactory implements ClientHttpRequestInterceptor {
@Override
protected void prepareConnection(HttpURLConnection connection, String httpMethod) throws IOException {
if (connection instanceof HttpsURLConnection) {
HttpsURLConnection https = (HttpsURLConnection) connection;
https.setHostnameVerifier((String var1, SSLSession var2)->true);
try {
https.setSSLSocketFactory(creatSSLsocketFactory());
}catch (Exception e){
e.printStackTrace();
}
}
super.prepareConnection(connection,httpMethod);
}
private SSLSocketFactory creatSSLsocketFactory() throws NoSuchAlgorithmException, KeyManagementException {
SSLContext tls = SSLContext.getInstance("TLS");
tls.init(null,new TrustManager[]{new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
}
@Override
public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
}},new SecureRandom());
return tls.getSocketFactory();
}
@Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
ClientHttpResponse response = null;
traceRequest(request, body);
try {
response = execution.execute(request, body);
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(String.format("RestRemote is Error 产品端拒绝链接,请检查通信是否正常 Uri:[%s]", request.getURI()));
}
if (response.getRawStatusCode() != 200) {
throw new RuntimeException(String.format("RestRemote is Error 请检查路径或根据Code判断错误 Uri:[%s] Code:[%s]", request.getURI(), response.getStatusCode()));
}
traceResponse(response);
return response;
}
private void traceRequest(HttpRequest request, byte[] body) throws IOException {
log.info("===========================request begin=============================================");
log.debug("URI : {}", request.getURI());
log.debug("Method : {}", request.getMethod());
log.debug("Headers : {}", request.getHeaders());
log.debug("Request body: {}", new String(body, "UTF-8"));
log.info("==========================request end================================================");
}
private void traceResponse(ClientHttpResponse response) throws IOException {
StringBuilder inputStringBuilder = new StringBuilder();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(response.getBody(), "UTF-8"));
String line = bufferedReader.readLine();
while (line != null) {
inputStringBuilder.append(line);
inputStringBuilder.append('\n');
line = bufferedReader.readLine();
}
log.info("============================response begin==========================================");
log.debug("Status code : {}", response.getStatusCode());
log.debug("Headers : {}", response.getHeaders());
log.debug("Response body: {}", inputStringBuilder.toString());
log.info("============================response end============================================");
}
}
API
简单请求
特殊场景的请求