【发布时间】:2018-05-03 13:16:17
【问题描述】:
我有一个工作的 spring 集成应用程序,我在/requests 下添加了一个 HTTP 端点,以从 REST 客户端(实际上是一个 Web 浏览器)接收 POST 数据;我也通过 Spring MVC 添加了一组其他 REST 端点,其中一个处理对/api/requests 的 GET 请求——这些 REST 端点旨在为客户。
spring 集成端点在按预期调用时工作(即直接调用/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>
初步问题:
-
[a]中的 servlet 是否配置正确?这可行,但我不清楚哪个 servlet 名称应该匹配哪个 bean 名称(如 Http Inbound Components 中所说),也许它是 context bean id ↔ web.xml servlet 名称? -
[b]中的映射是否必要?没有它我无法让入站适配器工作,但也许它应该以另一种方式配置,因为上述文档显示没有HttpRequestHandlerServletservlet 的映射
还有主要问题:
-
为什么那个适配器会拦截其他的休息调用?我得到:
HTTP Status 405 - Request method 'GET' not supported当调用
/api/requests时,它清楚地显示适配器正在介入。
我做了一些调试,行为似乎由 UrlPathHelper.alwaysUseFullPath 控制,将“/api/requests”更改为“/requests”。
如果这个属性可以设置为true 整个就可以了,我该怎么做呢?
更新 #1
我在this answer之后更新了配置,但还是有问题。
我从客户端请求中收到 404,并且此警告出现在应用程序日志中:
WARNING: No mapping found for HTTP request with URI [/api/requests] in DispatcherServlet with name 'app'
这是新的context.xml 和新的ids:
<?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.xml 和新的ids:
<?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 中的应用程序相同,这是应该响应GETs 而不是/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
在此更新中,我修复了 REST 控制器主路径映射从 path="/api/requests" 到 path="/requests"。
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));
}
// ...
此更改使GETs 再次工作,但随后POSTs 不再工作。
这似乎是由于 DispatcherServlet#getHandler() 中的代码,其中来自 handlerMappings 成员的 RequestMappingInfoHandlerMapping 类型的实例识别到对 /api/requests 的请求,但拒绝 POST 方法抛出异常,使执行落在请求处理程序查找。
【问题讨论】:
标签: java spring spring-integration spring-rest