首先说到这个RestTemplate ,大家都知道用来发送http请求的封装模板,首先使用场景有两个典型:
第一:和第三方交互使用http请求时,需要进行token认证
第二:springcloud架构中的Hystrix中上下游请求时token认证
开始上正菜吧……
SpringCloud RestTemplate通过拦截器统一添加token
实现拦截器
package xxxxxx;
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;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.List;
/**
* @author
* @description RestTemplate 统一添加 access_token 拦截器
* @date 2020/6/2
* @projectName share-capacity-platform
*/
@Component
public class HeaderRequestInterceptor implements ClientHttpRequestInterceptor {
@Override
public ClientHttpResponse intercept(HttpRequest httpRequest, byte[] body, ClientHttpRequestExecution clientHttpRequestExecution) throws IOException {
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
String auth = request.getHeader("Authorization");
String accessToken = request.getParameter("access_token");
List<String> authorizations = httpRequest.getHeaders().get("Authorization");
String authorization = "";
if (accessToken != null){
authorization = "bearer " + accessToken;
}else if (auth != null){
authorization = auth;
}else if (authorizations != null){
authorization = "bearer " + authorizations.get(0);
}
HttpHeaders headers = httpRequest.getHeaders();
headers.add("Authorization", authorization);
return clientHttpRequestExecution.execute(httpRequest, body);
}
}
RestTemplateConfig配置类
package xxxxxx;
/*
* Copyright (c) 2005, 2019, EVECOM Technology Co.,Ltd. All rights reserved.
* EVECOM PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.DefaultResponseErrorHandler;
import org.springframework.web.client.RestTemplate;
import java.util.Collections;
/**
* <P><B>Description: </B> 描述 </P>
* Revision Trail: (Date/Author/Description)
* 2019/7/18
* @version 1.0
*/
@Configuration
public class RestTemplateConfig {
@Autowired
HeaderRequestInterceptor headerRequestInterceptor;
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
// 长连接
PoolingHttpClientConnectionManager pollingConnectionManager = new PoolingHttpClientConnectionManager();
// 总连接数
pollingConnectionManager.setMaxTotal(1000);
// 同路由的并发数
pollingConnectionManager.setDefaultMaxPerRoute(1000);
HttpClientBuilder httpClientBuilder = HttpClients.custom();
httpClientBuilder.setConnectionManager(pollingConnectionManager);
// 重试次数,默认是3次,没有开启
// httpClientBuilder.setRetryHandler(new DefaultHttpRequestRetryHandler(3,
// true));
HttpClient httpClient = httpClientBuilder.build();
HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory(
httpClient);
// 连接超时
clientHttpRequestFactory.setConnectTimeout(60000);
// 数据读取超时时间,即SocketTimeout
clientHttpRequestFactory.setReadTimeout(60000);
// 连接不够用的等待时间,不宜过长,必须设置,比如连接不够用时,时间过长将是灾难性的
clientHttpRequestFactory.setConnectionRequestTimeout(200);
// 缓冲请求数据,默认值是true。通过POST或者PUT大量发送数据时,建议将此属性更改为false,以免耗尽内存。
RestTemplate restTemplate = new RestTemplate();
//set拦截器统一添加token
restTemplate.setInterceptors(Collections.singletonList(headerRequestInterceptor));
restTemplate.setRequestFactory(clientHttpRequestFactory);
restTemplate.setErrorHandler(new DefaultResponseErrorHandler());
return restTemplate;
}
}
总结
通过拦截器将token添加到请求头中,然后在RestTemplateConfig 配置类中添加该拦截器,即可简单实现RestTemplate统一添加token
FeignHeadConfiguration 实现token认证
import feign.RequestInterceptor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.util.Enumeration;
/**
* @author
* @date
*/
@Configuration
@Slf4j
public class FeignHeadConfiguration {
@Bean
public RequestInterceptor requestInterceptor() {
return requestTemplate -> {
ServletRequestAttributes attrs = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if (attrs != null) {
HttpServletRequest request = attrs.getRequest();
Enumeration<String> headerNames = request.getHeaderNames();
if (headerNames != null) {
while (headerNames.hasMoreElements()) {
String name = headerNames.nextElement();
String value = request.getHeader(name);
if ("Authorization".equalsIgnoreCase(name) || "token".equalsIgnoreCase(name)) {
log.info("添加自定义请求头key:[{}], value:[{}]", name, value);
requestTemplate.header(name, value);
}
}
} else {
log.info("FeignHeadConfiguration", "获取请求头失败!");
}
}
};
}
}