Spring Integration出站网关:动态配置及POST请求体传递问询
你已经在Spring Integration的HTTP出站网关动态配置上取得了不错的进展,从固定API调用到通过payload表达式实现动态URL、请求方法和响应类型,现在遇到的POST请求体传递问题确实很典型——毕竟payload已经被用来承载元数据了,没法直接放请求体。下面给你两个实用的解决思路:
方案1:自定义请求封装类(推荐)
创建一个专门的封装类,把元数据(URL、HTTP方法、响应类型)和请求体都包含进去,这样payload就是这个类的实例,既统一管理了配置信息,又能传递请求体。
步骤1:创建请求封装类
import org.springframework.http.HttpMethod; public class DynamicRestRequest<T> { // 元数据部分 private String url; private HttpMethod httpMethod; private Class<?> responseType; // 请求体部分 private T requestBody; // Getters and Setters public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public HttpMethod getHttpMethod() { return httpMethod; } public void setHttpMethod(HttpMethod httpMethod) { this.httpMethod = httpMethod; } public Class<?> getResponseType() { return responseType; } public void setResponseType(Class<?> responseType) { this.responseType = responseType; } public T getRequestBody() { return requestBody; } public void setRequestBody(T requestBody) { this.requestBody = requestBody; } }
步骤2:修改HTTP出站网关配置
添加request-body-expression属性,指定从封装类的requestBody字段获取请求体:
<int-http:outbound-gateway id="outbound.gateway" request-channel="get.request.channel" url="{fhirurl}" http-method-expression="payload.getHttpMethod()" expected-response-type-expression="payload.getResponseType()" request-body-expression="payload.getRequestBody()" <!-- 新增:指定请求体来源 --> charset="UTF-8" reply-timeout="5000" reply-channel="reply.channel"> <int-http:uri-variable name="fhirurl" expression="payload.getUrl()"/> </int-http:outbound-gateway>
步骤3:发送请求示例
public void dynamicRestTest() throws Exception { // 构造POST请求体 PostRequest postRequest = new PostRequest(); postRequest.setTitle("foo"); postRequest.setBody("bar"); postRequest.setUserId(1); // 构造动态请求元数据+请求体 DynamicRestRequest<PostRequest> dynamicRequest = new DynamicRestRequest<>(); dynamicRequest.setUrl("https://jsonplaceholder.typicode.com/posts"); dynamicRequest.setHttpMethod(HttpMethod.POST); dynamicRequest.setResponseType(Post.class); dynamicRequest.setRequestBody(postRequest); // 发送消息 Message<?> message = MessageBuilder.withPayload(dynamicRequest).build(); getRequestChannel.send(message); // 处理响应 Message<?> receivedMsg = receivedChannel.receive(); Post post = (Post) receivedMsg.getPayload(); System.out.println("############## ServerMsg ##############"); System.out.println(post.toString()); System.out.println("############## Done! ##############"); }
这个方案的优点是结构清晰,所有相关数据封装在一起,便于维护和扩展;缺点是需要额外创建一个类,增加少量代码量。
方案2:用消息头传递元数据
如果不想创建额外的类,可以把URL、HTTP方法、响应类型放在消息头中,让payload专门承载请求体,这样各司其职,符合消息传递的常规习惯。
步骤1:修改HTTP出站网关配置
把表达式从payload改为从headers获取元数据,同时指定request-body-expression为payload:
<int-http:outbound-gateway id="outbound.gateway" request-channel="get.request.channel" url="{fhirurl}" http-method-expression="headers['rest_http_method']" expected-response-type-expression="headers['rest_response_type']" request-body-expression="payload" <!-- payload直接作为请求体 --> charset="UTF-8" reply-timeout="5000" reply-channel="reply.channel"> <int-http:uri-variable name="fhirurl" expression="headers['rest_url']"/> </int-http:outbound-gateway>
步骤2:发送请求示例
public void headerBasedRestTest() throws Exception { // 构造POST请求体 PostRequest postRequest = new PostRequest(); postRequest.setTitle("foo"); postRequest.setBody("bar"); postRequest.setUserId(1); // 构造消息,元数据放在headers里,payload是请求体 Message<?> message = MessageBuilder.withPayload(postRequest) .setHeader("rest_url", "https://jsonplaceholder.typicode.com/posts") .setHeader("rest_http_method", HttpMethod.POST) .setHeader("rest_response_type", Post.class) .build(); getRequestChannel.send(message); // 处理响应 Message<?> receivedMsg = receivedChannel.receive(); Post post = (Post) receivedMsg.getPayload(); System.out.println("############## ServerMsg ##############"); System.out.println(post.toString()); System.out.println("############## Done! ##############"); }
这个方案的优点是不用额外创建类,代码更简洁;缺点是元数据分散在消息头中,需要确保团队成员统一使用约定的header名称,避免拼写错误。
额外提示
如果你的场景需要处理泛型响应(比如List<Post>),可以把responseType字段改为ParameterizedTypeReference,然后在expected-response-type-expression中返回这个对象,Spring Integration会正确解析泛型类型。
内容的提问来源于stack exchange,提问作者keth

