【问题标题】:Spring Integration and Spring MVC: @Controller vs inbound-gateway with service-activatorSpring 集成和 Spring MVC:@Controller 与带有服务激活器的入站网关
【发布时间】:2016-07-28 14:30:40
【问题描述】:

我想找到使用 Spring Integration HTTPSpring MVC 管理入站请求的最佳方法。

我有一个<int-http:inbound-gateway>,配置如下:

<!-- CHANNEL -->
<int:channel id="requestChannel">
    <int:dispatcher task-executor="executor"/>
</int:channel>
<int:channel id="outputChannel" />

<!-- INBOUND GATEWAY -->
<int-http:inbound-gateway id="gateway" request-channel="requestChannel"
              path="/service/**" 
              supported-methods="POST"
              reply-channel="outputChannel"
              header-mapper="headerMapper">
</int-http:inbound-gateway>

<!-- SERVICE ACTIVATOR -->
<int:service-activator id="channelServiceActivator"
    ref="channelService"
    input-channel="requestChannel"
    output-channel="outputChannel"
    method="manage"/>

<bean id="channelService"
    class="test.spring.data.rest.xml.channel.ChannelService"/>

通过这种集成,在路径 URI:/service/** 上进行的每个 HTTP 调用都在 ChannelService 类的 "manage()" 方法中处理。

这是ChannelService 类:

public class ChannelService {

    public void manage(Message<?> message){

        // how to get the HttpServletRequest request here ???
    }

}

它有效:"manage()" 方法被正确执行并且消息包含正确的有效负载。 但是有一个小问题:我没有对在该 ServiceChannel 的输入中收到的 HttpServletRequest 的任何引用

如果我使用 Spring MVC 的 @Controller,我可以使用相对 @RequestMapping 处理每个请求。 如果我想读取请求中包含的有效载荷,我必须从 HttpServletRequest 的 inputStream 中读取它。在任何地方,我都没有机会在频道中获得消息:

@Controller
@RequestMapping(value="/service")
public class ServiceController {

    @RequestMapping(value="/**")
    public handle(HttpServletRequest request) throws Exception{

        // how to get the Message<?> message passed on the channel here ???

    }

}

如果我同时使用两者@Controllerinbound-gateway),@Controller 映射胜过入站网关:没有机会处理 servlet带有inbound-gateway 的路径 URI(如果有) 映射相同路径 URI 的 @Controller

所以,我想了解是否有某种方法可以在 @Controller 中使用 Message&lt;?&gt; message,或者在 ServiceActivator 中使用 HttpServletRequest,或者通过其他方法来管理这种情况。

提前致谢。

【问题讨论】:

    标签: spring spring-mvc spring-integration


    【解决方案1】:

    您可以通过MessageHeaders (http://docs.spring.io/spring-integration/reference/html/http.html#_uri_template_variables_and_expressions) 访问HttpServletRequest

    HttpRequestHandlingEndpointSupport 的逻辑如下:

    evaluationContext.setVariable("requestAttributes", RequestContextHolder.currentRequestAttributes());
    
    MultiValueMap<String, String> requestParams = this.convertParameterMap(servletRequest.getParameterMap());
    evaluationContext.setVariable("requestParams", requestParams);
    
    evaluationContext.setVariable("requestHeaders", new ServletServerHttpRequest(servletRequest).getHeaders());
    

    因此,您可以使用以下子元素配置 &lt;int-http:inbound-gateway&gt;

    <int-http:header name="requestAttributes" expression="#requestAttributes"/>
    <int-http:header name="requestParams" expression="#requestParams"/>
    <int-http:header name="requestHeaders" expression="#requestHeaders"/>
    <int-http:header name="matrixVariables" expression="#matrixVariables"/>
    <int-http:header name="cookies" expression="#cookies"/>
    

    requestAttributesRequestAttributes 的实现。标准的是ServletRequestAttributes,您可以在其中找到getRequest() 方法。是的,也可以在表达式中使用它:

    <int-http:header name="request" expression="#requestAttributes.request"/>
    

    另一方面,您始终可以在自己的代码中使用RequestContextHolder.currentRequestAttributes(),因为它与ThreadLocal 绑定。

    Spring MVC 对 Spring 集成一无所知,因此没有任何 Message 处理。

    不管怎样,你也可以走这条路。为此,您应该引入@MessagingGateway 并从您的@Controller 那里委派一个逻辑。

    【讨论】:

    • 非常感谢 Artem 的精彩解释。
    猜你喜欢
    • 2019-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-28
    相关资源
    最近更新 更多