最近在项目中用到了腾讯里约统一认证(主要用于应用准入网关、服务治理网关、安全边界网关、应用接入网关、统一身份认证、数字资产管理平台),后端所有编写的接口API都得注册到网关上去,然后通过网关发布到公有云上,最后用户所有的请求都是通过访问网关进行统一授权请求服务器,这里我们可以简单的把理解成一个大的nginx 具体原理还在学习之中,后续会继续更新学习博客,而在实际使用中,Spring RestTemplate经常被用作客户端向Restful API发送各种请求,很多请求都需要用到相似或者相同的Http Header。如果在每次请求之前都把Header填入如果在每次请求之前都把Header填入HttpEntity/RequestEntity,这样的代码会显得十分冗余 然后Spring提供了ClientHttpRequestInterceptor接口,可以对请求进行拦截,并在其被发送至服务端之前修改请求或是增强相应的信息,下面是我写的一个简单的demo:
1.实现ClientHttpRequestInterceptor接口,代码如下:
package com.longjin.comm.handle;
import java.io.IOException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.stereotype.Component;
/**
* @Description:实现ClientHttpRequestInterceptor接口
* @Author 何志鹏
* @Date 2020/06/04 10:18
* @Version 1.0
*/
@Component
public class HttpDhInterceptor implements ClientHttpRequestInterceptor {
private static final Logger log = LoggerFactory.getLogger(HttpDhInterceptor.class);
public HttpDhInterceptor() {
}
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
return execution.execute(request, body);
}
}
2.实现HandlerInterceptor接口 代码如下:
package com.longjin.comm.handle;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.lang.Nullable;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
/**
* @Description:实现HandlerInterceptor接口
* @Author 何志鹏
* @Date 2020/06/04 10:18
* @Version 1.0
*/
public class BjtInterceptor implements HandlerInterceptor {
private static final Logger log = LoggerFactory.getLogger(BjtInterceptor.class);
public BjtInterceptor() {
}
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
return true;
}
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
}
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
log.info("-------------------------请求处理完成-------------------------");
}
}
3.实现ClientHttpRequestInterceptor接口 截取url地址添加header 代码如下:
package com.longjin.comm.handle;
import java.io.IOException;
import java.util.Date;
import com.longjin.comm.utils.ShaUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
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.stereotype.Component;
/**
* @Description:实现ClientHttpRequestInterceptor接口 截取url地址添加header
* @Author 何志鹏
* @Date 2020/06/04 10:18
* @Version 1.0
*/
@Component
@Slf4j
public class HttpWgInterceptor implements ClientHttpRequestInterceptor {
@Value("${dsf.dsfpassid}")
private String dsfpassid;
@Value("${dsf.dsftoken}")
private String dsftoken;
@Value("${tifapi.tifpassid}")
private String tifpassid;
@Value("${tifapi.tiftoken}")
private String tiftoken;
@Value("${Xuhui.xhpassid}")
private String xhpassid;
@Value("${Xuhui.xhtoken}")
private String xhtoken;
public HttpWgInterceptor() {
}
/**
* 根据请求地址配置header
*
* @param request
* @param body
* @param execution
* @return
* @throws IOException
*/
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
HttpHeaders headers = request.getHeaders();
String timestamp = String.valueOf(System.currentTimeMillis() / 1000L);
String contentType = "application/json";
String path = request.getURI().toString();
headers.add("x-tif-timestamp", timestamp);
if (path.contains("tifapi")) {
log.info("1111111111111111111111111111111");
headers .add("Content-Type", contentType);
String nonce = Long.toHexString(new Date().getTime()) + "-" + Long.toHexString((long) Math.floor(Math.random() * 0xFFFFFF));
headers .add("Content-Type", contentType);
headers.add("x-tif-signature", DigestUtils.sha256Hex(timestamp + this.tiftoken + nonce + timestamp));
headers.add("x-tif-nonce", nonce);
headers.add("x-tif-paasid", this.tifpassid);
} else if (path.contains("hzldsf")) {
String nonce = Long.toHexString(new Date().getTime()) + "-" + Long.toHexString((long) Math.floor(Math.random() * 0xFFFFFF));
log.info("请求码:{}",nonce);
headers .add("Content-Type", contentType);
headers.add("x-tif-signature", ShaUtils.getSHA256(String.format("%s%s%s%s", timestamp, dsftoken, nonce, timestamp)).toUpperCase());
headers.add("x-tif-nonce", nonce);
headers.add("x-tif-paasid", this.dsfpassid);
} else {
String nonce = Long.toHexString(new Date().getTime()) + "-" + Long.toHexString((long) Math.floor(Math.random() * 0xFFFFFF));
headers .add("Content-Type", contentType);
headers.add("x-tif-signature", DigestUtils.sha256Hex(timestamp + this.xhtoken + nonce + timestamp));
headers.add("x-tif-nonce", nonce);
headers.add("x-tif-paasid", this.xhpassid);
}
return execution.execute(request, body);
}
}
4.自定义拦截器添加到RestTemplate实例 代码如下:
package com.longjin.comm.handle;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.OkHttp3ClientHttpRequestFactory;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.client.RestTemplate;
/**
* @Description:自定义拦截器添加到RestTemplate实例
* @Author 何志鹏
* @Date 2020/06/04 10:18
* @Version 1.0
*/
@Configuration
public class HttpConfig {
private int connectionTime = 30000;
private int readTimeout = 30000;
private int writeTimeout = 30000;
@Autowired
private HttpWgInterceptor httpWgInterceptor;
@Autowired
private HttpDhInterceptor httpDhInterceptor;
public HttpConfig() {
}
@Bean({"dhRestTemplate"})
public RestTemplate dhRestTemplate() {
OkHttp3ClientHttpRequestFactory factory = new OkHttp3ClientHttpRequestFactory();
factory.setConnectTimeout(this.connectionTime);
factory.setReadTimeout(this.readTimeout);
factory.setWriteTimeout(this.writeTimeout);
RestTemplate restTemplate = new RestTemplate(factory);
List<ClientHttpRequestInterceptor> interceptorList = new ArrayList();
interceptorList.add(this.httpWgInterceptor);
interceptorList.add(this.httpDhInterceptor);
restTemplate.setInterceptors(interceptorList);
((StringHttpMessageConverter)restTemplate.getMessageConverters().get(1)).setDefaultCharset(StandardCharsets.UTF_8);
return restTemplate;
}
@Bean({"restTemplate"})
public RestTemplate restTemplate() {
OkHttp3ClientHttpRequestFactory factory = new OkHttp3ClientHttpRequestFactory();
factory.setConnectTimeout(this.connectionTime);
factory.setReadTimeout(this.readTimeout);
factory.setWriteTimeout(this.writeTimeout);
RestTemplate restTemplate = new RestTemplate(factory);
((StringHttpMessageConverter)restTemplate.getMessageConverters().get(1)).setDefaultCharset(StandardCharsets.UTF_8);
return restTemplate;
}
@Bean({"wgRestTemplate"})
public RestTemplate wgRestTemplate() {
OkHttp3ClientHttpRequestFactory factory = new OkHttp3ClientHttpRequestFactory();
factory.setConnectTimeout(this.connectionTime);
factory.setReadTimeout(this.readTimeout);
factory.setWriteTimeout(this.writeTimeout);
List<ClientHttpRequestInterceptor> interceptorList = new ArrayList();
interceptorList.add(this.httpWgInterceptor);
RestTemplate restTemplate = new RestTemplate(factory);
restTemplate.setInterceptors(interceptorList);
((StringHttpMessageConverter)restTemplate.getMessageConverters().get(1)).setDefaultCharset(StandardCharsets.UTF_8);
return restTemplate;
}
}
5.RestTemplate请求的工具类 代码如下:
package com.longjin.comm.utils;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import net.minidev.json.JSONUtil;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Map;
/**
* Http请求的工具类<br>
* 利用RestTemplate工具类实现
*/
@Slf4j
@Component
public class RestTemplateUtils {
private final int defaultTimeout = 10000;
@Autowired
private RestTemplate wgRestTemplate;
@Resource
public void setWgRestTemplate(RestTemplate restTemplate){
this.wgRestTemplate = restTemplate;
}
/**
* post请求
*
* @param url 请求URL
* @param params 请求参数
* @param clazz 返回类型
* @return 响应
* @throws RestClientException
*/
public <T> T post(String url, Map<String, Object> params, Class<T> clazz) throws RestClientException {
return post(url, params, null, clazz, defaultTimeout, defaultTimeout);
}
/**
* post请求
*
* @param url 请求URL
* @param params 请求参数
* @param headers 请求头
* @param clazz 返回类型
* @return 响应
* @throws RestClientException
*/
public <T> T post(String url, Map<String, Object> params, HttpHeaders headers, Class<T> clazz) throws RestClientException {
return post(url, params, headers, clazz, defaultTimeout, defaultTimeout);
}
/**
* post请求
*
* @param url 请求URL
* @param params 请求参数
* @param headers 请求头
* @param clazz 返回类型
* @param readTimeout 读超时时间
* @param connectTimeout 连接超时时间
* @return 响应
* @throws RestClientException
*/
private <T> T post(String url, Map<String, Object> params, HttpHeaders headers, Class<T> clazz,
int readTimeout, int connectTimeout) throws RestClientException {
if (params == null || params.isEmpty()) {
log.error("request error. param is empty.");
return null;
}
log.info("\nPOST请求参数:{}", params);
log.info("\nPOST请求头参数:{}", headers);
// 设置连接参数
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
requestFactory.setReadTimeout(readTimeout);
requestFactory.setConnectTimeout(connectTimeout);
wgRestTemplate.setRequestFactory(requestFactory);
// 请求参数
MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
params.forEach((k, v) -> map.add(k, v));
// 请求头
if (headers == null) {
headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
}
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(map, headers);
ResponseEntity<T> responseEntity = wgRestTemplate.postForEntity(url, requestEntity, clazz);
return responseEntity.getBody();
}
/**
* @param url
* @param params
* @param headers
* @param clazz
* @param <T>
* @return
* @throws RestClientException
*/
public <T> T postRequest(String url, Map<String, Object> params, HttpHeaders headers, Class<T> clazz) throws RestClientException {
HttpEntity<Map<String, Object>> requestEntity = new HttpEntity<>(params, headers);
ResponseEntity<T> responseEntity = wgRestTemplate.postForEntity(url, requestEntity, clazz);
return responseEntity.getBody();
}
/**
* @param url 请求URL
* @param clazz 返回类型
* @Description: GET请求
* @Author: yongjian_wu
* @Date: 2019/9/5
* @return:
*/
public <T> T get(String url, Class<T> clazz, Map<String, Object> params) {
// 发起请求
try {
ResponseEntity<T> responseEntity = wgRestTemplate.getForEntity(url, clazz, params);
return responseEntity.getBody();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public <T> T get(String url, Class<T> clazz, String params) {
// 发起请求
try {
ResponseEntity<T> responseEntity = wgRestTemplate.getForEntity(url, clazz, params);
return responseEntity.getBody();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* @param requestName 请求接口名
* @param url
* @param header
* @param clazz
* @param <T>
* @return
* @throws RestClientException
* @Author:sunyh
*/
public <T> T get(String url, HttpHeaders header, String requestName, Class<T> clazz) {
HttpEntity<String> requestEntity = new HttpEntity<>(header);
try {
log.info(requestName + "get请求start");
ResponseEntity<T> response = wgRestTemplate.exchange(url, HttpMethod.GET, requestEntity, clazz);
return response.getBody();
} catch (Exception e) {
log.info(requestName + "get请求失败" + e.getMessage());
return null;
}
}
/**
* @param url
* @param clazz
* @param params
* @param requestName 请求接口名
* @param <T>
* @return
*/
public <T> T get(String url, Class<T> clazz, String params, String requestName) {
try {
ResponseEntity<T> responseEntity = wgRestTemplate.getForEntity(url, clazz, params);
return responseEntity.getBody();
} catch (Exception e) {
log.info(requestName + "get请求失败" + e.getMessage());
return null;
}
}
public Map post(String url, Object param) {
return post(url,param,Map.class);
}
public <T> T post(String url, Object param, Class<T> clazz) {
String value = "";
if (param instanceof String) {
value = (String) param;
} else {
value = JSONObject.toJSONString(param);
}
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
HttpEntity<String> requestEntity = new HttpEntity<String>(value,
headers);
ResponseEntity<T> tResponseEntity = wgRestTemplate.postForEntity(
url,
requestEntity, clazz);
return tResponseEntity.getBody();
}
public Map post(String url, Object param, HttpHeaders headers) {
String value = "";
if (param instanceof String) {
value = (String) param;
} else {
value = JSONObject.toJSONString(param);
}
headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
HttpEntity<String> requestEntity = new HttpEntity<String>(value,
headers);
ResponseEntity<Map> res = wgRestTemplate.postForEntity(
url,
requestEntity, Map.class);
return res.getBody();
}
public <T> T post(String url, MultiValueMap<String, String> map, Class<T> clazz) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<MultiValueMap<String, String>>(map, headers);
ResponseEntity<T> res = wgRestTemplate.postForEntity(
url,
requestEntity, clazz);
return res.getBody();
}
public static String put(String url, String body) throws IOException {
return put(url, body, null);
}
public static String put(String url, String body, Map<String, String> headers) throws IOException {
return fetch("PUT", url, body, headers);
}
public static String fetch(String method, String url, String body, Map<String, String> headers) throws IOException {
// connection
URL u = new URL(url);
HttpURLConnection conn = (HttpURLConnection) u.openConnection();
conn.setConnectTimeout(100000);
conn.setReadTimeout(300000);
// method
if (method != null) {
conn.setRequestMethod(method);
}
// headers
if (headers != null) {
for (String key : headers.keySet()) {
conn.addRequestProperty(key, headers.get(key));
}
}
conn.addRequestProperty("Content-Type", "application/json;charset=UTF-8");
// body
conn.setDoOutput(true);
OutputStream os = conn.getOutputStream();
os.write(body.getBytes());
os.flush();
// response
InputStream is = conn.getInputStream();
String response = streamToString(is);
is.close();
os.close();
// handle redirects
if (conn.getResponseCode() == 301) {
String location = conn.getHeaderField("Location");
return fetch(method, location, body, headers);
}
return response;
}
public static String streamToString(InputStream in) throws IOException {
StringBuffer out = new StringBuffer();
BufferedReader br = new BufferedReader(new InputStreamReader(in, "UTF-8"));
String line;
while ((line = br.readLine()) != null) {
out.append(line);
}
return out.toString();
}
public String sendPut(String url, String data) {
String response = null;
try {
CloseableHttpClient httpclient = null;
CloseableHttpResponse httpresponse = null;
try {
httpclient = HttpClients.createDefault();
HttpPut httpPut = new HttpPut(url);
httpPut.setHeader("Content-Type", "application/json");
StringEntity stringentity = new StringEntity(data,
ContentType.create("text/json", "UTF-8"));
httpPut.setEntity(stringentity);
httpresponse = httpclient.execute(httpPut);
response = EntityUtils
.toString(httpresponse.getEntity());
} finally {
if (httpclient != null) {
httpclient.close();
}
if (httpresponse != null) {
httpresponse.close();
}
}
} catch (Exception e) {
e.printStackTrace();
}
return response;
}
}
6.写一个测试接口 代码如下(post请求):
7.Get请求方式 代码如下: