Spring RestTemplate配置拦截器打印请求URL和响应结果
- 一、前言
- 二、RestTemplateConfig配置类
- 三、ClientHttpRequestInterceptor拦截器
- 四、效果展示
一、前言
最近项目中频繁调用第三方接口获取响应结果,请求方式post()和get(),调用过程中总是报400错误,就想到可能是提交的请求参数不对,但却没法看到RestTemplate的完整请求URL,所以想到配置拦截器,在发起Request请求时进行拦截打印,这样就方便查看发送的Request请求是否正确。
二、RestTemplateConfig配置类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | @Slf4j @Configuration public class RestTemplateConfig { private static final int HTTP_CLIENT_RETRY_COUNT = 3; private static final int MAXIMUM_TOTAL_CONNECTION = 10; private static final int MAXIMUM_CONNECTION_PER_ROUTE = 5; private static final int CONNECTION_VALIDATE_AFTER_INACTIVITY_MS = 10 * 1000; /** * @param connectionTimeoutMs milliseconds/毫秒 * @param readTimeoutMs milliseconds/毫秒 * @return */ public static RestTemplate createRestTemplate(int connectionTimeoutMs, int readTimeoutMs/*,ObjectMapper objectMapper*/) { HttpClientBuilder clientBuilder = HttpClients.custom(); PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(); // 整个连接池最大连接数 connectionManager.setMaxTotal(MAXIMUM_TOTAL_CONNECTION); // 设置每个路由的最大并发连接数,默认为2. connectionManager.setDefaultMaxPerRoute(MAXIMUM_CONNECTION_PER_ROUTE); // 官方推荐使用检查永久链接的可用性,而不推荐每次请求的时候才去检查 (milliseconds 毫秒) connectionManager.setValidateAfterInactivity(CONNECTION_VALIDATE_AFTER_INACTIVITY_MS); clientBuilder.setConnectionManager(connectionManager); //设置重连操作次数,这里设置了3次 clientBuilder.setRetryHandler(new DefaultHttpRequestRetryHandler(HTTP_CLIENT_RETRY_COUNT, true, new ArrayList<>()) { @Override public boolean retryRequest(IOException exception, int executionCount, HttpContext context) { log.info("Retry request, execution count: {}, exception: {}", executionCount, exception); return super.retryRequest(exception, executionCount, context); } }); // 把配置好的HttpClient放入构造器 HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory(clientBuilder.build()); httpRequestFactory.setConnectTimeout(connectionTimeoutMs); httpRequestFactory.setConnectionRequestTimeout(readTimeoutMs); httpRequestFactory.setReadTimeout(readTimeoutMs); RestTemplate restTemplate = new RestTemplate(httpRequestFactory); // 添加自定义拦截器 List<ClientHttpRequestInterceptor> interceptors = new ArrayList<ClientHttpRequestInterceptor>(); interceptors.add(new LoggingClientHttpRequestInterceptor()); restTemplate.setInterceptors(interceptors); //提供对传出/传入流的缓冲,可以让响应body多次读取(如果不配置,拦截器读取了Response流,再响应数据时会返回body=null) restTemplate.setRequestFactory(new BufferingClientHttpRequestFactory(httpRequestFactory)); /* MappingJackson2HttpMessageConverter messageConverter = restTemplate.getMessageConverters().stream().filter(MappingJackson2HttpMessageConverter.class::isInstance) .map(MappingJackson2HttpMessageConverter.class::cast).findFirst().orElseThrow(() -> new RuntimeException("MappingJackson2HttpMessageConverter not found")); messageConverter.setObjectMapper(objectMapper);*/ //防止响应中文乱码 restTemplate.getMessageConverters().stream().filter(StringHttpMessageConverter.class::isInstance).map(StringHttpMessageConverter.class::cast).forEach(a -> { a.setWriteAcceptCharset(false); a.setDefaultCharset(StandardCharsets.UTF_8); }); return restTemplate; } @Bean public RestTemplate restTemplate(){ RestTemplate restTemplate = RestTemplateConfig.createRestTemplate(5000, 5000); //配置自定义的interceptor拦截器 //使用restTemplate远程调用防止400和401导致报错而获取不到正确反馈信息 restTemplate.setErrorHandler(new DefaultResponseErrorHandler(){ @Override public void handleError(ClientHttpResponse response) throws IOException { if (response.getRawStatusCode() != 400 && response.getRawStatusCode() != 401){ super.handleError(response); } } }); return restTemplate; } } |
- 这里restTemplateConfig主要配置请求的超时时间、最大连接数、出现异常后重连次数、自定义拦截器添加等;
三、ClientHttpRequestInterceptor拦截器
- 需要去实现ClientHttpRequestInterceptor类中的intercept()方法才能实现Request拦截;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | @Slf4j public class LoggingClientHttpRequestInterceptor implements ClientHttpRequestInterceptor { @Override public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException { tranceRequest(request, body); ClientHttpResponse response = execution.execute(request, body); traceResponse(response); return response; } private void tranceRequest(HttpRequest request, byte[] body) throws UnsupportedEncodingException { log.debug("=========================== 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.debug("============================ request end ============================"); } private void traceResponse(ClientHttpResponse httpResponse) throws IOException { StringBuilder inputStringBuilder = new StringBuilder(); BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(httpResponse.getBody(), "UTF-8")); String line = bufferedReader.readLine(); while (line != null) { inputStringBuilder.append(line); inputStringBuilder.append('\n'); line = bufferedReader.readLine(); } log.debug("============================ response begin ============================"); log.debug("Status code : {}", httpResponse.getStatusCode()); log.debug("Status text : {}", httpResponse.getStatusText()); log.debug("Headers : {}", httpResponse.getHeaders()); log.debug("Response body: {}", inputStringBuilder.toString()); log.debug("============================= response end ============================="); } } |
四、效果展示
- GET请求:
- POST请求:
–欢迎评论区留言讨论,转载请注明出处。