Http Post请求内容types表单在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方法不允许。 有趣的是在响应的允许标题中,它将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内容types非常有效。

一个更普遍的问题是如何使spring mvc请求处理程序处理不同的请求内容types。 任何build议将不胜感激。

不幸的是FormHttpMessageConverter (当内容types为application/x-www-form-urlencoded时,用于@RequestBody -annotated参数)无法绑定目标类(如@ModelAttribute所能)。

因此你需要@ModelAttribute而不是@RequestBody 。 如果您不需要将不同的内容types传递给该方法,则可以简单地replace注释:

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

否则,我想你可以创build一个单独的方法forms处理表单数据与适当的headers属性:

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

编辑:另一种可能的select是通过将FormHttpMessageConverter (将input消息转换为参数映射)和WebDataBinder (将参数映射转换为目标对象)来实现您自己的HttpMessageConverter

我有HTTP响应代码415

当我将内容types添加到请求标题时,我的问题得到了解决

例如

“Content-Type:application / json”

在问题的核心,我们希望同时接受application / json和application / x-www-form-urlencoded Content-types。

为了做到这一点,我使用@RequestBody,它已经为我的应用程序/ JSON(通常是我发现的线程中的其他人),但是有额外的工作,所以可以使用application / x-www-form-urlencoded与@RequestBody。

首先,创build一个新的HttpMessageConverter,能够将请求input更改为一个对象。 我通过重用FormHttpMessageConverter来实现这一点,它已经能够将input改变为MultiValueMap。 然后,我将MultiValueMap更改为常规Map,并使用Jackson将Map转换为所需的对象。

这里是HttpMessageConverter的代码:

 import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.http.HttpInputMessage; import org.springframework.http.HttpOutputMessage; import org.springframework.http.MediaType; import org.springframework.http.converter.FormHttpMessageConverter; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.HttpMessageNotReadableException; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import java.io.IOException; import java.util.List; import java.util.Map; /** * <p>Converts HTTP requests with bodies that are application/x-www-form-urlencoded or multipart/form-data to an Object * annotated with {@link org.springframework.web.bind.annotation.RequestBody} in the the handler method. * * @author Jesse Swidler */ public class ObjectHttpMessageConverter implements HttpMessageConverter<Object> { private final FormHttpMessageConverter formHttpMessageConverter = new FormHttpMessageConverter(); private final ObjectMapper objectMapper = new ObjectMapper(); private static final LinkedMultiValueMap<String, String> LINKED_MULTI_VALUE_MAP = new LinkedMultiValueMap<>(); private static final Class<? extends MultiValueMap<String, ?>> LINKED_MULTI_VALUE_MAP_CLASS = (Class<? extends MultiValueMap<String, ?>>) LINKED_MULTI_VALUE_MAP.getClass(); @Override public boolean canRead(Class clazz, MediaType mediaType) { return objectMapper.canSerialize(clazz) && formHttpMessageConverter.canRead(MultiValueMap.class, mediaType); } @Override public boolean canWrite(Class clazz, MediaType mediaType) { return false; } @Override public List<MediaType> getSupportedMediaTypes() { return formHttpMessageConverter.getSupportedMediaTypes(); } @Override public Object read(Class clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException { Map<String, String> input = formHttpMessageConverter.read(LINKED_MULTI_VALUE_MAP_CLASS, inputMessage).toSingleValueMap(); return objectMapper.convertValue(input, clazz); } @Override public void write(Object o, MediaType contentType, HttpOutputMessage outputMessage) throws UnsupportedOperationException { throw new UnsupportedOperationException(""); } } 

Spring应用程序有很多不同的方式可以select这个消息转换器。 对我来说,它是在一个XML文件中完成的:

 <mvc:annotation-driven> <mvc:message-converters> <bean class="com.terminal.core.services.config.ObjectHttpMessageConverter"/> </mvc:message-converters> </mvc:annotation-driven> 

使用@ModelAttribute确实是处理表单参数的首选方法。

使用JSON也适用于我,我想这使得JSON解释器从正文中获取数据。 我正在尝试使用PUT,但这有点困难。 你可以在这里阅读我的文章。

下面为我​​工作

在服务器端:

  @RequestMapping(value = "test", method = RequestMethod.POST, consumes = {"application/xml", "application/json"}) @ResponseStatus(HttpStatus.OK) public @ResponseBody String methodName(@RequestBody EntityClassName entity) { 

在客户端:

 String json = new JSONStringer().object() .key("key").value("value") .endObject() .toString(); StringEntity se = new StringEntity(json); se.setContentType(new BasicHeader(HTTP.CONTENT_TYPE, "application/json")); request.setEntity(se); HttpResponse response = client.execute(request); 

我使用这个代码转换为HTML格式的JSON。

 function ConvertFormToJSON(form) { var array = $(form).serializeArray(); var json = {}; $.each(array, function() { json[this.name] = this.value || ''; }); return json; } 

并用单引号是错误的。 我把“”改成“”,问题解决了。