【发布时间】:2019-12-09 07:46:23
【问题描述】:
当我配置 RestTemplate 使用 HttpClient 时,我的拦截器只执行第一次,第二次执行时它会挂起,在下面的这个块中。也不例外,不知道为什么! 如果我删除 httpClient 那就没问题了。 (我的拦截器意图是捕获 401 未授权状态以刷新访问令牌)
if (url.contains("/auth") || url.contains("/custcare-common")) {
return execution.execute(request, body);
}
完整代码如下:
public class RestTemplateHeaderInterceptor implements ClientHttpRequestInterceptor {
@Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution)
throws IOException {
String url = request.getURI().getPath();
if (url.contains("/auth") || url.contains("/custcare-common")) {
return execution.execute(request, body);
}
HttpSession session = SessionBean.getSession();
if (session != null) {
// check header does not has token then add to header
if (request.getHeaders().isEmpty() || !request.getHeaders().containsKey(HttpHeaders.AUTHORIZATION)) {
// add jwt token to header
Object accessToken = session.getAttribute(AppConstants.Token.ACCESS_TOKEN);
if (accessToken != null) {
request.getHeaders().add(HttpHeaders.AUTHORIZATION, SecurityConstants.TOKEN_PREFIX + accessToken);
}
}
// refresh token when expire
ClientHttpResponse response = execution.execute(request, body);
if (response.getStatusCode() == HttpStatus.UNAUTHORIZED) {
Object refreshToken = session.getAttribute(AppConstants.Token.REFRESH_TOKEN);
if (refreshToken != null) {
TokenData newTokenData = getNewToken(refreshToken.toString());
if (newTokenData != null) {
session.setAttribute(AppConstants.Token.ACCESS_TOKEN, newTokenData.getAccessToken());
session.setAttribute(AppConstants.Token.REFRESH_TOKEN, newTokenData.getRefreshToken());
request.getHeaders().set(HttpHeaders.AUTHORIZATION, SecurityConstants.TOKEN_PREFIX + newTokenData.getAccessToken());
return execution.execute(request, body);
}
}
}
}
return execution.execute(request, body);
}
private TokenData getNewToken(String refreshToken) {
TokenData tokenData = null;
RefreshTokenRequest request = new RefreshTokenRequest();
request.setRefreshToken(refreshToken);
MessagesResponse<TokenData> response = RestUtil.post(RestUtil.getCcApiUrl("cc-api.authen.refresh-token"), request, new ParameterizedTypeReference<MessagesResponse<TokenData>>() {});
if (response != null) {
tokenData = response.getData();
}
return tokenData;
}
}
我的 RestTemplate 配置:
@Configuration
public class RestTemplateConfig {
@Bean
public PoolingHttpClientConnectionManager poolingHttpClientConnectionManager() {
PoolingHttpClientConnectionManager result = new PoolingHttpClientConnectionManager();
result.setMaxTotal(20);
return result;
}
@Bean
public RequestConfig requestConfig() {
RequestConfig requestConfig = RequestConfig.custom().setConnectionRequestTimeout(60000).setConnectTimeout(60000)
.setSocketTimeout(60000).build();
return requestConfig;
}
@Bean
public CloseableHttpClient httpClient() throws KeyManagementException, NoSuchAlgorithmException, KeyStoreException {
TrustStrategy trustStrategy = new TrustStrategy() {
@Override
public boolean isTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
return true;
}
};
SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(null, trustStrategy).build();
SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(sslContext, new NoopHostnameVerifier());
CloseableHttpClient result = HttpClientBuilder.create()
.setConnectionManager(poolingHttpClientConnectionManager())
.setDefaultRequestConfig(requestConfig())
.setSSLSocketFactory(csf)
.build();
return result;
}
@Bean
@Primary
public RestTemplate restTemplate() throws KeyManagementException, NoSuchAlgorithmException, KeyStoreException {
HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClient());
RestTemplate restTemplate = new RestTemplate(requestFactory);
restTemplate.setErrorHandler(new RestResponseErrorHandler());
List<ClientHttpRequestInterceptor> interceptors = restTemplate.getInterceptors();
if (interceptors.isEmpty()) {
interceptors = new ArrayList<>();
}
interceptors.add(new RestTemplateHeaderInterceptor());
restTemplate.setInterceptors(interceptors);
return restTemplate;
}
}
最后,我通过设置 DefaultMaxPerRoute 解决了这个问题,但我仍然对此感到困惑。 :D
@Bean
public PoolingHttpClientConnectionManager poolingHttpClientConnectionManager() {
PoolingHttpClientConnectionManager result = new PoolingHttpClientConnectionManager();
result.setMaxTotal(100);
result.setDefaultMaxPerRoute(100);
return result;
}
【问题讨论】:
标签: java spring resttemplate interceptor