2016-07-28 6 views
1

ich den besten Weg finden, will eine eingehende Anfrage mit Frühling Integration HTTP und Spring MVC zu verwalten.Frühling Integration und Spring MVC: @Controller vs Inbound-Gateway mit Service-Aktivator

Ich habe ein <int-http:inbound-gateway> wie folgt konfiguriert:

<!-- 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"/> 

Mit dieser Integration gemacht jeder HTTP-Aufruf auf dem Pfad URI: /service/** ist im manage() Methode der Klasse ChannelService behandelt.

Dies ist die ChannelService Klasse:

public class ChannelService { 

    public void manage(Message<?> message){ 

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

} 

Es funktioniert: die „verwalten()“ Verfahren korrekt ausgeführt wird und die Nachricht enthält die richtige Nutzlast. Aber es gibt ein kleines Problem: Ich habe keine Referenz auf die HttpServletRequest erhalten in Eingabe in diesem ServiceChannel.

Wenn ich eine @Controller von Spring MVC verwende, kann ich jede Anfrage mit der relativen @RequestMapping behandeln. Wenn ich die Nutzlast in der Anfrage lesen will, muss ich es aus dem InputStream der HttpServletRequest lesen. Überall habe ich keine Chance haben, die Nachricht in den Kanal geleitet zu bekommen:

@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 ??? 

    } 

} 

Wenn ich beide (@Controller und inbound-gateway), die @Controller Mapping gewinnt über das Inbound-Gateway: gibt es keine Chance, einen Servlet-Pfad-URI mit einer inbound-gateway zu behandeln, wenn es eine @Controller gibt, die den gleichen Pfad URI abbildet.

Also, ich möchte verstehen, ob es eine Möglichkeit gibt, eine Message<?> message in der @Controller, oder die HttpServletRequest im ServiceActivator, oder eine andere Möglichkeit, dieses Szenario zu verwalten.

Vielen Dank im Voraus.

Antwort

3

Sie können über MessageHeaders (http://docs.spring.io/spring-integration/reference/html/http.html#_uri_template_variables_and_expressions) auf die zugreifen.

Die HttpRequestHandlingEndpointSupport hat eine Logik wie:

evaluationContext.setVariable("requestAttributes", RequestContextHolder.currentRequestAttributes()); 

MultiValueMap<String, String> requestParams = this.convertParameterMap(servletRequest.getParameterMap()); 
evaluationContext.setVariable("requestParams", requestParams); 

evaluationContext.setVariable("requestHeaders", new ServletServerHttpRequest(servletRequest).getHeaders()); 

So können Sie Ihr <int-http:inbound-gateway> mit Unterelementen wie konfigurieren:

<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"/> 

Die requestAttributes ist eine Implementierung von RequestAttributes. Der Standard ist ServletRequestAttributes, wo Sie getRequest() Methode finden können. Und ja, es verwendet, als auch in dem Ausdruck:

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

Auf der anderen Seite immer Sie RequestContextHolder.currentRequestAttributes() in Ihrem eigenen Code verwenden können, weil sie mit ThreadLocal gebunden ist.

Der Spring MVC weiß nichts über Spring Integration, daher gibt es keinen Message Deal mit.

Wie auch immer Sie können auch so gehen. Zu diesem Zweck sollten Sie @MessagingGateway vorstellen und dort eine Logik von Ihrem @Controller delegieren.

+0

Vielen Dank Artem für Ihre brillante Erklärung. –