Spring启动REST控制器POST请求处理

时间:2015-10-28 07:20:46

标签: spring-mvc spring-boot

使用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 的其他子类,如 WebContentInterceptor RequestMappingHandlerAdapter 应该处理对控制器的请求。

在运行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 {  ... }   

3 个答案:

答案 0 :(得分:6)

很难说出错是什么,因为你的代码似乎很好。 但我会尝试提出一些小改动,这可能有助于澄清情况。

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

  

Spring 4的新@RestController注释,它将类标记为   控制器,其中每个方法返回一个域对象而不是一个   视图。它是@Controller和@ResponseBody的缩写   在一起。

此外,问题可能隐藏在您的headers要求之下。如果不具体,可以将其更改为consumes选项。试试下面的代码段。

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

答案 1 :(得分:2)

基于spring docapplication/json属性:

  

映射请求的标头,缩小主映射。相同   任何环境的格式:" My-Header = myValue"样式   表达式,仅在找到每个此类标头时才映射请求   具有给定值。使用"!="可以取消表达式。   运算符,如" My-Header!= myValue"。 "我的报头"风格表达   也支持,这些标题必须存在于   请求(允许有任何价值)。最后,"!My-Header"样式   表达式表明指定的标头不应该是   在请求中出现。

因此,当且仅当存在具有Content-Type值的consumes标头时,才会正确映射您的consumes请求。限制Content-Type的更好方法是415 Unsupported Media Type属性。如果您使用{{1}}属性,如果{{1}}标头无效或丢失,则会返回{{1}},这更为理想。

答案 2 :(得分:0)

  1. 请务必检查,您有@CompnentScan(控制器类的{控制器基础包}。

  2. 确保检查应用程序启动日志 swsmmaRequestMappingHandlerMapping:映射“{[/ v1 / accounts],methods = [POST],params = [],headers = [],consume = [application / json],produce = [application / json],custom = []} “on public default T [] com.bank.dev.controller.ICrudController.create(T ...) swsmmaRequestMappingHandlerMapping:映射“{[/ v1 / accounts / {uuid}],methods = [GET],params = [],headers = [],consume = [],produce = [application / json],custom = [] “on public default T com.bank.dev.controller.ICrudController.get(java.lang.String,java.lang.String)