使用request-factory的http:outbound-gateway能否集成ClientHttpRequestInterceptor做日志?
解决方案
你不需要子类化HttpComponentsClientHttpRequestFactory,ClientHttpRequestInterceptor方案依然可行,只需要调整配置方式,把请求工厂和拦截器整合到RestTemplate中,再将该RestTemplate配置到http:outbound-gateway即可。
方案一:通过RestTemplate整合Spring拦截器
这种方式保留Spring生态的拦截器模型,同时复用Apache HttpClient的配置:
- 定义
HttpComponentsClientHttpRequestFactoryBean:
<bean id="httpRequestFactory" class="org.springframework.http.client.HttpComponentsClientHttpRequestFactory"> <!-- 配置Apache HttpClient参数,比如连接池、超时时间等 --> </bean>
- 实现自定义的
ClientHttpRequestInterceptor日志拦截器:
public class LoggingClientHttpRequestInterceptor implements ClientHttpRequestInterceptor { private static final Logger logger = LoggerFactory.getLogger(LoggingClientHttpRequestInterceptor.class); @Override public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException { // 记录请求信息:URL、方法、请求体、头信息等 logger.info("Outbound HTTP Request: {} {} | Headers: {} | Body: {}", request.getMethod(), request.getURI(), request.getHeaders(), new String(body, StandardCharsets.UTF_8)); ClientHttpResponse response = execution.execute(request, body); // 记录响应信息:状态码、响应体、头信息等 String responseBody = StreamUtils.copyToString(response.getBody(), StandardCharsets.UTF_8); logger.info("Inbound HTTP Response: {} | Headers: {} | Body: {}", response.getStatusCode(), response.getHeaders(), responseBody); return response; } }
- 定义带有拦截器的
RestTemplate,注入请求工厂:
<bean id="loggingRestTemplate" class="org.springframework.web.client.RestTemplate"> <constructor-arg ref="httpRequestFactory"/> <property name="interceptors"> <list> <bean class="com.yourpackage.LoggingClientHttpRequestInterceptor"/> </list> </property> </bean>
- 在
http:outbound-gateway中配置该RestTemplate:
<int-http:outbound-gateway id="outboundGateway" request-channel="requestChannel" url="http://your-target-api-url" rest-template="loggingRestTemplate" <!-- 其他网关配置属性 -->/>
方案二:使用Apache HttpClient原生拦截器
如果更倾向于直接操作Apache HttpClient的底层流程,可以给HttpClient实例添加原生的HttpRequestInterceptor:
- 实现Apache HttpClient的
HttpRequestInterceptor:
public class ApacheHttpRequestLoggingInterceptor implements HttpRequestInterceptor { private static final Logger logger = LoggerFactory.getLogger(ApacheHttpRequestLoggingInterceptor.class); @Override public void process(HttpRequest request, HttpContext context) throws HttpException, IOException { // 记录请求信息 if (request instanceof HttpEntityEnclosingRequest) { HttpEntityEnclosingRequest entityRequest = (HttpEntityEnclosingRequest) request; String body = EntityUtils.toString(entityRequest.getEntity(), StandardCharsets.UTF_8); logger.info("Outbound Apache HTTP Request: {} {} | Headers: {} | Body: {}", request.getRequestLine().getMethod(), request.getRequestLine().getUri(), request.getAllHeaders(), body); } else { logger.info("Outbound Apache HTTP Request: {} {} | Headers: {}", request.getRequestLine().getMethod(), request.getRequestLine().getUri(), request.getAllHeaders()); } } }
- 配置带有拦截器的HttpClient实例,注入到请求工厂:
<bean id="apacheLoggingInterceptor" class="com.yourpackage.ApacheHttpRequestLoggingInterceptor"/> <bean id="customHttpClient" class="org.apache.http.impl.client.HttpClients" factory-method="custom"> <constructor-arg> <bean class="org.apache.http.impl.client.HttpClientBuilder"> <method name="addInterceptorFirst"> <ref bean="apacheLoggingInterceptor"/> </method> <!-- 配置HttpClient参数,比如连接池、超时等 --> </bean> </constructor-arg> </bean> <bean id="httpRequestFactory" class="org.springframework.http.client.HttpComponentsClientHttpRequestFactory"> <property name="httpClient" ref="customHttpClient"/> </bean>
- 在
http:outbound-gateway中使用该请求工厂:
<int-http:outbound-gateway id="outboundGateway" request-channel="requestChannel" url="http://your-target-api-url" request-factory="httpRequestFactory" <!-- 其他网关配置属性 -->/>
两种方案都能实现HTTP请求/响应的日志记录,你可以根据自己的技术习惯选择。
内容的提问来源于stack exchange,提问作者al.truisme
相关产品推荐
相关产品推荐

