springboot提供了RestTemplateBuilder(),可以定义一个configuration类,在其中定义一个bean,返回resttemplate,其他类中使用这个bean直接主句
它的build方法:构建一个新的 RestTemplate 实例并使用此构建器对其进行配置。返回:一个已配置的 RestTemplate 实例。
定义如下:
@Configuration
public class RestTemplateConfiguration {
@Bean
public RestTemplate newRestTemplate() {
return new RestTemplateBuilder()
.interceptors(new RestTemplateHeaderModifierInterceptor())
.errorHandler(new CustomErrorHandler()).build();
}
@Slf4j
private static class CustomErrorHandler implements ResponseErrorHandler {
@Override
public boolean hasError(ClientHttpResponse response) throws IOException {
return response.getStatusCode().series() == HttpStatus.Series.CLIENT_ERROR
|| response.getStatusCode().series() == HttpStatus.Series.SERVER_ERROR;
}
@Override
public void handleError(ClientHttpResponse response) throws IOException {
if (response.getStatusCode().is5xxServerError()) {
throw new BusinessException(SERVER_ERROR);
}
if (response.getStatusCode().is4xxClientError()) {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(response.getBody()))) {
String httpBodyResponse = reader.lines().collect(Collectors.joining(""));
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
ExceptionBody restTemplateError = mapper.readValue(httpBodyResponse, ExceptionBody.class);
throw new BusinessException(restTemplateError.getMessage());
}
}
}
}
public static class RestTemplateHeaderModifierInterceptor implements ClientHttpRequestInterceptor {
@Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
request.getHeaders().add(X_ACCOUNT_ID, RestClientHeader.accountIdThreadLocal.get());
request.getHeaders().add(X_TENANT_ID, RestClientHeader.tenantIdThreadLocal.get());
return execution.execute(request, body);
}
}
}
ClientHttpRequestInterceptor :拦截给定的请求,并返回响应。给定的 ClientHttpRequestExecution 允许拦截器将请求和响应传递给链中的下一个实体。
本项目中需要对所有请求处理请求头中的X_ACCOUNT_ID字段和X_TENANT_ID字段,因此定义了一个拦截器,然后在构建resttemplate中设置刚刚定义的拦截器
这里的RestClientHeader:
@Data
public class RestClientHeader {
public static ThreadLocal<String> accountIdThreadLocal = new ThreadLocal<>();
public static ThreadLocal<String> tenantIdThreadLocal = new ThreadLocal<>();
}
是一个带ThreadLocal字段的类,其中放的是accountId、tenantId这个请求头字段的值
threadLocal设置值的位置:
public class AuthHeaderInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String accountId = request.getHeader(X_ACCOUNT_ID);
RestClientHeader.accountIdThreadLocal.set(accountId);
String tenantId = request.getHeader(X_TENANT_ID);
RestClientHeader.tenantIdThreadLocal.set(tenantId);
return HandlerInterceptor.super.preHandle(request, response, handler);
}
}