带有请求内容类型表单的Http Post在Spring MVC 3中不起作用


问题内容

代码段:

@RequestMapping(method = RequestMethod.POST)//,  headers = "content-type=application/x-www-form-urlencoded")
public ModelAndView create(@RequestBody UserAccountBean account) {
    try{
        accounts.put(account.assignId(), account);
    }catch(RuntimeException ex)
    {
        return new ModelAndView("account/registerError");
    }
    return new ModelAndView("account/userVerification");
}

收到请求后,我得到的是Http状态代码415:服务器拒绝了此请求,因为请求实体的格式不受请求的方法所请求的资源的支持。

如果我将代码更改为此:

代码段:

@RequestMapping(method = RequestMethod.POST,headers = "content-type=application/x-www-form-urlencoded")
public ModelAndView create(@RequestBody UserAccountBean account) {
    try{
        accounts.put(account.assignId(), account);
    }catch(RuntimeException ex)
    {
        return new ModelAndView("account/registerError");
    }
    return new ModelAndView("account/userVerification");
}

我将获得405方法不允许。有趣的是,在响应的allow标头中,它列出了GET和POST作为允许的方法。

我有一个做JOSN映射的类:

@Component
public class JacksonConversionServiceConfigurer implements BeanPostProcessor {

private final ConversionService conversionService;

@Autowired
public JacksonConversionServiceConfigurer(ConversionService conversionService) {
    this.conversionService = conversionService;
}

public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    return bean;
}

public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    if (bean instanceof AnnotationMethodHandlerAdapter) {
        AnnotationMethodHandlerAdapter adapter = (AnnotationMethodHandlerAdapter) bean;
        HttpMessageConverter<?>[] converters = adapter.getMessageConverters();
        for (HttpMessageConverter<?> converter : converters) {
            if (converter instanceof MappingJacksonHttpMessageConverter) {
                MappingJacksonHttpMessageConverter jsonConverter = (MappingJacksonHttpMessageConverter) converter;
                jsonConverter.setObjectMapper(new ConversionServiceAwareObjectMapper(this.conversionService));
            }               
        }
    }
    return bean;
}

}

从Spring示例复制。与JSON内容类型配合使用时效果很好。

一个更普遍的问题是如何使spring mvc请求处理程序与不同的请求内容类型一起工作。任何建议将不胜感激。


问题答案:

不幸的是FormHttpMessageConverter@RequestBody当内容类型为时,用于带注释的参数application/x-www- form-urlencoded)无法绑定目标类@ModelAttribute

因此,您需要@ModelAttribute而不是@RequestBody。如果您不需要将不同的内容类型传递给该方法,则只需替换注释即可:

@RequestMapping(method = RequestMethod.POST)
public ModelAndView create(@ModelAttribute UserAccountBean account) { ... }

否则,我想您可以创建一个单独的方法表单来处理具有适当headers属性的表单数据:

@RequestMapping(method = RequestMethod.POST, 
    headers = "content-type=application/x-www-form-urlencoded") 
public ModelAndView createFromForm(@ModelAttribute UserAccountBean account) { ... }

编辑:
另一个可能的选择是HttpMessageConverter通过组合FormHttpMessageConverter(将输入消息转换为参数映射)和WebDataBinder(将参数映射转换为目标对象)来实现自己的选择。