Spring mvc 请求内容类型为表单的Http Post在Spring MVC 3中不起作用
代码段:Spring mvc 请求内容类型为表单的Http Post在Spring MVC 3中不起作用,spring-mvc,content-type,Spring Mvc,Content Type,代码段: @RequestMapping(method = RequestMethod.POST)//, headers = "content-type=application/x-www-form-urlencoded") public ModelAndView create(@RequestBody UserAccountBean account) { try{ accounts.put(account.assignId(), account); }catc
@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");
}
@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");
}
@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;
}
}
@组件
公共类JacksonConversionServiceConfigure实现BeanPostProcessor{
私有最终转换服务转换服务;
@自动连线
公共JacksonConversionService配置器(转换服务转换服务){
this.conversionService=conversionService;
}
公共对象后处理BeforeInitialization(对象bean、字符串beanName)抛出BeanException{
返回豆;
}
公共对象后处理初始化后(对象bean、字符串beanName)抛出BeansException{
if(AnnotationMethodHandlerAdapter的bean实例){
AnnotationMethodHandlerAdapter=(AnnotationMethodHandlerAdapter)bean;
HttpMessageConverter[]converters=adapter.getMessageConverters();
用于(HttpMessageConverter转换器:转换器){
if(映射JacksonHttpMessageConverter的转换器实例){
MappingJacksonHttpMessageConverter jsonConverter=(MappingJacksonHttpMessageConverter)转换器;
jsonConverter.setObjectMapper(新的ConversionServiceWareObjectMapper(this.conversionService));
}
}
}
返回豆;
}
}
复制自Spring示例。非常适合JSON内容类型
一个更普遍的问题是如何使SpringMVC请求处理程序处理不同的请求内容类型。
如有任何建议,将不胜感激 不幸的是
FormHttpMessageConverter
(当内容类型为应用程序/x-www-form-urlencoded
时用于@RequestBody
-带注释的参数)无法绑定目标类(正如@modeldattribute
可以绑定的那样)
因此,您需要@modeldattribute
而不是@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) { ... }
编辑:另一种可能的选择是通过组合
FormHttpMessageConverter
(将输入消息转换为参数映射)和WebDataBinder
(将参数映射转换为目标对象)来实现您自己的HttpMessageConverter
.使用@modeldattribute确实是处理表单参数的首选方法。我的HTTP响应代码是415
当我将内容类型添加到请求头时,我的问题得到了解决
e、 g
“Content-Type:application/json”使用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);
问题的核心是,我们希望使用相同的请求处理程序接受application/json和application/x-www-form-urlencoded内容类型 为此,我使用@RequestBody,它已经在为我的application/json工作(通常还有我找到的线程中的其他线程),但是还有额外的工作,因此application/x-www-form-urlencoded可以与@RequestBody一起使用 首先,创建一个能够将请求输入更改为对象的新HttpMessageConverter。我通过重用FormHttpMessageConverter来实现这一点,FormHttpMessageConverter已经能够将输入更改为多值映射。然后,我将多值映射更改为常规映射,并使用Jackson将映射转换为所需的对象 以下是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("");
}
}
import com.fasterxml.jackson.databind.ObjectMapper;
导入org.springframework.http.HttpInputMessage;
导入org.springframework.http.HttpOutputMessage;
导入org.springframework.http.MediaType;
导入org.springframework.http.converter.FormHttpMessageConverter;
导入org.springframework.http.converter.HttpMessageConverter;
导入org.springframework.http.converter.httpmessagenoteradableexception;
导入org.springframework.util.LinkedMultiValueMap;
导入org.springframework.util.MultiValueMap;
导入java.io.IOException;
导入java.util.List;
导入java.util.Map;
/**
*将具有应用程序/x-www-form-urlencoded或多部分/form数据体的HTTP请求转换为对象
*在处理程序方法中使用{@link org.springframework.web.bind.annotation.RequestBody}进行注释。
*
*@作者杰西·斯威德勒
*/
公共类ObjectHttpMessageConverter实现HttpMessageConverter{
私有最终FormHttpMessageConverter FormHttpMessageConverter=新FormHttpMessageConverter();
私有最终ObjectMapper ObjectMapper=新ObjectMapper();
私有静态最终LinkedMultiValueMap LINKED_MULTI_VALUE_MAP=新LinkedMultiValueMap();
私有静态最终类>链接的多值映射类
=(类>)链接的多值映射。getClass();
@凌驾
公共布尔canRead(类clazz,MediaType-MediaType){
返回objectMapper.canSerialize(clazz)和&formHttpMessageConverter.canRead(MultiValueMap.class,mediaType);
}
@凌驾
公共布尔canWrite(类clazz,MediaType-MediaType){
返回false;
}
@凌驾
公共列表getSupportedMediaTypes(){
返回formHttpMessageConverter.getSupportedMediaTypes();
}
@凌驾
公共对象读取(类clazz,HttpInputMessage-inputMessage)引发IOException,HttpMessageGenetradableExc