【问题标题】:Spring boot REST controller POST request handlingSpring Boot REST 控制器 POST 请求处理
【发布时间】:2016-01-27 21:01:04
【问题描述】:

使用 Spring Boot (v1.2.6.RELEASE),我需要接受 Controller 方法的 POST 请求。

@RestController
@RequestMapping(value = "/myWebApp/signup")
public class RegController {

    @RequestMapping(value = "/registerFamily", method = { RequestMethod.POST  }, headers = {"Content-type=application/json"})
@ResponseBody
public FamilylResponse registerFamily(@RequestBody @Valid FamilyRequest familyRequest){

... }

当我从 Chrome/mozilla 的 REST 客户端发送 POST 请求时,响应如下:

{"timestamp":1446008095543,"status":405,"error":"Method Not Allowed","exception":"org.springframework.web.HttpRequestMethodNotSupportedException","message":"Request method 'POST' not supported","path":"/myWebApp/signup/registerFamily"}

...

堆栈跟踪如下:

  org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'POST' not supported
at org.springframework.web.servlet.support.WebContentGenerator.checkAndPrepare(WebContentGenerator.java:273)
at org.springframework.web.servlet.support.WebContentGenerator.checkAndPrepare(WebContentGenerator.java:251)
at org.springframework.web.servlet.resource.ResourceHttpRequestHandler.handleRequest(ResourceHttpRequestHandler.java:207)
at org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter.handle(HttpRequestHandlerAdapter.java:51)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)  

根据Spring: not accept POST request under mvc:resources? how to fix that的回复,

我认为 WebContentGenerator 的其他子类,如 WebContentInterceptorRequestMappingHandlerAdapter 应该处理对控制器的请求。

另外,在运行 Junit 测试时,我发现 RequestMappingHandlerAdapter 正在处理控制器的这些请求。

但我还没有找到如何配置它来接受 POST 请求?

任何其他更好的解决方案都应该受到欢迎。

编辑

Tomcat 使用 WebMvcAutoConfiguration.WebMvcAutoConfigurationAdapter(WebMvcConfigurerAdapter 的子类) 和

WebMvcAutoConfiguration.WebMvcAutoConfigurationAdapter.addResourceHandlers(ResourceHandlerRegistry) 执行以下操作:

o.s.w.s.handler.SimpleUrlHandlerMapping :将 URL 路径 [/webjars/**] 映射到 [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler] 类型的处理程序上

o.s.w.s.handler.SimpleUrlHandlerMapping :将 URL 路径 [/**] 映射到 [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler] 类型的处理程序上

junit 中,我添加了 WebMvcConfigurerAdapter 的一个空的具体子类。

而 WebMvcConfigurerAdapter.addResourceHandlers(ResourceHandlerRegistry) 什么都不做。

@Configuration
@EnableWebMvc
public class WebAppContext extends WebMvcConfigurerAdapter {}

@Configuration
@Import({ WebAppContext.class })
@PropertySource("classpath:application.properties")
public class ExampleApplicationContext { }


@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {ExampleApplicationContext.class})
@WebAppConfiguration
public class RegControllerTest {  ... }   

【问题讨论】:

  • 您是否发送Content-Type 标头?
  • @zeroflagL,对不起,我发送到错误的 URL。所以,默认的 /** 被采用了

标签: spring-mvc spring-boot


【解决方案1】:

很难说哪里出了问题,因为您的代码看起来不错。 但我会尝试提出一些小的更改,这可能有助于澄清情况。

首先,您在使用@RestController 时不需要额外的@ResponseBody 注释。来自spring site

Spring 4 的新 @RestController 注解,将类标记为 控制器,其中每个方法都返回一个域对象而不是 看法。它是 @Controller 和 @ResponseBody 滚动的简写 在一起。

此外,问题可能隐藏在您的headers 要求下。如果不具体,可以改成consumes选项。试试下面的 sn-p。

@RequestMapping(value = "/api", method = RequestMethod.POST, 
                    consumes = "application/json", produces = "application/json")

【讨论】:

  • 更新了问题。
  • @labbhattacharjee 我看到了你的编辑,但现在不明白你想达到什么目的。你是想只在Controller中处理POST请求,还是通过它来管理资源文件?我对headersconsumes 的建议对您有帮助吗?
  • @Vadyml,感谢您的回复。我不想通过控制器处理资源文件。不,我仍然收到 HTTP 405
  • @labbhattacharjee 我可以建议尝试将您的代码从 method = { RequestMethod.POST } 更改为 method = RequestMethod.POST。如果您没有删除headers = {"Content-type=application/json"},请同时删除。如果这没有帮助,则问题不在控制器中。
  • @labbhattacharjee 您也可以尝试添加到您的控制器this working sample method 并检查它是如何工作的。
【解决方案2】:

基于spring docheaders 属性:

映射请求的标头,缩小主映射。相同的 任何环境的格式:“My-Header=myValue”样式的序列 表达式,只有在找到每个这样的标头时才映射请求 具有给定的值。可以使用“!=”来否定表达式 运算符,如“My-Header!=myValue”。 “我的标题”样式表达式 也支持,这样的标头必须出现在 请求(允许有任何值)。最后,“!My-Header”样式 表达式表明指定的标头不应该是 出现在请求中。

因此,当且仅当具有 application/json 值的 Content-type 标头存在时,您的 POST 请求才会正确映射。限制Content-Type 的更好方法是consumes 属性。如果您使用consumes 属性,则在Content-Type 标头无效或丢失的情况下,将返回415 Unsupported Media Type,这更可取。

【讨论】:

  • 更新了问题。
【解决方案3】:
  1. 确保检查,您有 @CompnentScan({ your controller base package } of Controller 类。

  2. 确保检查应用程序启动日志 swsmmaRequestMappingHandlerMapping : 映射“{[/v1/accounts],methods=[POST],params=[],headers=[],consumes=[application/json],produces=[application/json],custom=[]} " 到公共默认 T[] com.bank.dev.controller.ICrudController.create(T...) swsmmaRequestMappingHandlerMapping : 映射“{[/v1/accounts/{uuid}],methods=[GET],params=[],headers=[],consumes=[],produces=[application/json],custom=[] }" 到公共默认 T com.bank.dev.controller.ICrudController.get(java.lang.String,java.lang.String)

【讨论】:

  • 欢迎来到 Stack Overflow!这不是问题的答案,而是评论/新问题。一旦您有足够的声誉 (50),您就可以对任何帖子发表评论。与此同时,您可以通过提出自己的问题或就您知道的主题提供答案来赢得声誉。
猜你喜欢
  • 1970-01-01
  • 2019-10-17
  • 2017-12-29
  • 1970-01-01
  • 2015-06-08
  • 1970-01-01
  • 2016-07-19
  • 1970-01-01
  • 2022-11-29
相关资源
最近更新 更多