Http入站通道适配器响应太多路径

时间:2018-05-03 13:16:18

标签: java spring spring-integration spring-rest

我有一个工作的spring集成应用程序,我在/requests下添加了一个HTTP端点,以便从REST客户端(实际是Web浏览器)接收POST数据;我也通过 Spring MVC 添加了一组其他REST端点,其中一个端点处理对/api/requests的GET请求 - 这些REST端点se旨在提供一个读取只与客户互动。

弹簧集成端点在按预期调用时工作(即直接调用/requests),但我体验到它是"捕捉"甚至要求它不应该:/api/requests

我没有使用Spring Boot。我从Integration home上的示例中对我的配置进行了适配,稍后将其从应用程序移动到Web应用程序。

这是context.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:...>

    <ctx:component-scan base-package="services,api"  />

    <int-http:inbound-channel-adapter id="httpInboundAdapter"
        channel="httpRequestsChannel"
        path="/requests"
        supported-methods="POST">
        <int-http:cross-origin allow-credentials="false" allowed-headers="*" origin="*" />
    </int-http:inbound-channel-adapter>

    <!-- other channels and endpoints -->

    <!-- misc beans -->

    <!-- other beans: jdbc-datasource, etc -->

    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver" />

</beans>

web.xml的(相关部分):

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
          http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
          version="3.0">

    <!-- [a] -->
    <servlet>
        <servlet-name>httpInboundAdapter</servlet-name>
        <servlet-class>org.springframework.web.context.support.HttpRequestHandlerServlet</servlet-class>
    </servlet>

    <!-- [b] -->
    <servlet-mapping>
        <servlet-name>httpInboundAdapter</servlet-name>
        <url-pattern>/requests</url-pattern>
    </servlet-mapping>

    <servlet>
        <servlet-name>app</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value></param-value>
        </init-param>

        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>app</servlet-name>
        <url-pattern>/api/*</url-pattern>
    </servlet-mapping>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/META-INF/spring.integration/context.xml</param-value>
    </context-param>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>  
    </listener>
    <listener>
        <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
    </listener>

</web-app>

初步问题:

  1. [a]中正确配置的servlet吗?这有效,但我不清楚哪个servlet名称应该匹配哪个bean名称(如Http Inbound Components中所述),也许它的 context bean id ↔< em> web.xml servlet名称?
  2. 是否需要[b]中的映射?如果没有它,我无法使入站适配器工作,但是可能应该以另一种方式配置,因为上面提到的文档没有显示HttpRequestHandlerServlet servlet的映射
  3. 主要问题:

    1. 为什么该适配器拦截其他休息呼叫?我得到了:

      HTTP Status 405 - Request method 'GET' not supported
      

      调用/api/requests时,清楚地显示适配器插入。

    2. 我做了一些调试,行为似乎由UrlPathHelper.alwaysUseFullPath控制,改变了&#34; / api / requests&#34; to&#34; / requests&#34;。 如果此属性可以设置为true,那么整个会起作用,我该怎么做?

      更新#1

      我在this answer之后更新了我的配置,但我仍然遇到了麻烦。

      我从客户端请求获得404,并且此警告显示在应用程序日志中:

      WARNING: No mapping found for HTTP request with URI [/api/requests] in DispatcherServlet with name 'app'
      

      这是新的context.xmlid s:

      <?xml version="1.0" encoding="UTF-8"?>
      <beans xmlns="http://www.springframework.org/schema/beans"
          xmlns:...>
      
          <ctx:component-scan base-package="services,api"  />
          <ctx:annotation-config />
          <mvc:annotation-driven />
      
          <int-http:inbound-channel-adapter id="/api/requests"
              channel="httpRequestsChannel"
              path="/api/requests"
              supported-methods="POST">
              <int-http:cross-origin allow-credentials="false" allowed-headers="*" origin="*" />
          </int-http:inbound-channel-adapter>
      
          <int-http:inbound-channel-adapter id="/api/requests"
              channel="nullChannel"
              path="/api/requests"
              supported-methods="OPTIONS">
              <int-http:cross-origin allow-credentials="false" allowed-headers="*" origin="*" />
          </int-http:inbound-channel-adapter>
      
          <!-- other channels and endpoints -->
      
          <!-- misc beans -->
      
          <!-- other beans: jdbc-datasource, etc -->
      
          <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver" />
      
      </beans>
      

      我从web.xml

      中删除了servlet声明和映射
      <?xml version="1.0" encoding="UTF-8"?>
      <web-app xmlns="http://java.sun.com/xml/ns/javaee"
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
                http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
                version="3.0">
      
          <servlet>
              <servlet-name>app</servlet-name>
              <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
      
              <init-param>
                  <param-name>contextConfigLocation</param-name>
                  <param-value></param-value>
              </init-param>
      
              <load-on-startup>1</load-on-startup>
          </servlet>
      
          <servlet-mapping>
              <servlet-name>app</servlet-name>
              <url-pattern>/api/*</url-pattern>
          </servlet-mapping>
      
          <!-- ... -->
      

      更新#2

      另一篇评论,删除重复的id bean,我仍然得到相同的警告:

      WARNING: No mapping found for HTTP request with URI [/api/requests] in DispatcherServlet with name 'app'
      

      这是新的context.xmlid s:

      <?xml version="1.0" encoding="UTF-8"?>
      <beans xmlns="http://www.springframework.org/schema/beans"
          xmlns:...>
      
              <ctx:component-scan base-package="services,api"  />
              <ctx:annotation-config />
              <mvc:annotation-driven />
      
              <int-http:inbound-channel-adapter id="/api/requests"
                  channel="httpRequestsChannel"
                  path="/api/requests"
                  supported-methods="POST,OPTIONS">
                  <int-http:cross-origin allow-credentials="false" allowed-headers="*" origin="*" />
              </int-http:inbound-channel-adapter>
      
              <int:channel id="httpRequestsChannel" />
          <!-- other channels, endpoints and beans -->
      
      </beans>
      

      更新#3

      正如所指出的,我已经编辑了path属性:POST请求现在可以正常工作,但GET请求现在已经被破坏,产生:

      WARNING: Request method 'GET' not supported
      

      虽然上面没有显示,但这个应用程序与this other question中的应用程序相同,此处的控制器应响应GET上的/api/requests

      package api;
      
      // imports
      
      @CrossOrigin(origins = "*", maxAge = 3600)
      @RestController
      @RequestMapping(path="/api/requests", produces="application/json")
      public class RequestController {
          // ...
      

      已编辑context.xml

      <?xml version="1.0" encoding="UTF-8"?>
      <beans xmlns="http://www.springframework.org/schema/beans"
          xmlns:...>
      
              <ctx:component-scan base-package="services,api"  />
              <ctx:annotation-config />
              <mvc:annotation-driven />
      
              <int-http:inbound-channel-adapter id="/api/requests"
                  channel="httpRequestsChannel"
                  path="/requests"
                  supported-methods="POST,OPTIONS">
                  <int-http:cross-origin allow-credentials="false" allowed-headers="*" origin="*" />
              </int-http:inbound-channel-adapter>
      
              <int:channel id="httpRequestsChannel" />
          <!-- other channels, endpoints and beans -->
      
      </beans>
      

      更新#4

      在此更新中,我修复了从path="/api/requests"path="/requests"的REST控制器主路径映射。

      package it.cgt.api;
      
      // imports
      
      @CrossOrigin(origins = "*", maxAge = 3600)
      @RestController
      @RequestMapping(path="/requests", produces="application/json")
      public class RequestController {
      
          @Autowired
          private RequestService requestService;
      
          @Autowired
          private ProductService productService;
      
          @GetMapping(path= "")
          public ApiResponse<List<Request>> getRequests(RequestFilters filters) {
              return new ApiResponse<List<Request>>(requestService.getRequests(filters));
          }
      
          // ...
      

      此更改使GET再次起作用,但POST不再有效。

      这似乎是由DispatcherServlet#getHandler()中的代码引起的,其中RequestMappingInfoHandlerMapping成员中的handlerMappings类型的实例会识别对/api/requests的请求,但拒绝POST方法抛出使执行落在请求处理程序查找之外的异常。

1 个答案:

答案 0 :(得分:1)

在那份文件中我们有这句话:

  

如果您在Spring MVC应用程序中运行,则不需要前面提到的显式servlet定义。

由于您有DispatcherServlet,因此HttpRequestHandlerServlet不需要具体的httpInboundAdapter

因此,您还会删除<url-pattern>/requests</url-pattern>,并且所有REST API都位于/api/*下,并且不会根据提到的/requests公开UrlPathHelper.alwaysUseFullPath