@RequestBody注解

Spring中@RequestBody注解,用于读取Request请求的body数据,并根据内容类型(Content Type)确定使用哪个HttpMessageConverter进行解析。

@RequestBody默认提供:StringHttpMessageConverter,ByteArrayHttpMessageConverter,

SourceHttpMessageConverter,AllEncompassingFormHttpMessageConverter,其中AllEncompassingFormHttpMessageConverter继承自FormHttpMessageConverter处理表单提交相关。具体查看org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.java

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
public RequestMappingHandlerAdapter() {
		StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter();
		stringHttpMessageConverter.setWriteAcceptCharset(false);  // see SPR-7316
//默认的4种消息转换器
this.messageConverters = new ArrayList<HttpMessageConverter<?>>(4);
		this.messageConverters.add(new ByteArrayHttpMessageConverter());
		this.messageConverters.add(stringHttpMessageConverter);
		this.messageConverters.add(new SourceHttpMessageConverter<Source>());
    // 表单消息转换类
		this.messageConverters.add(new AllEncompassingFormHttpMessageConverter());
	}

AllEncompassingFormHttpMessageConverter中根据classpath中的jar提供了json及xml相关的转换类。

AllEncompassingFormHttpMessageConverter.java

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
public class AllEncompassingFormHttpMessageConverter extends FormHttpMessageConverter {

	private static final boolean jaxb2Present =
			ClassUtils.isPresent("javax.xml.bind.Binder",
					AllEncompassingFormHttpMessageConverter.class.getClassLoader());

	private static final boolean jackson2Present =
			ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper",
					AllEncompassingFormHttpMessageConverter.class.getClassLoader()) &&
			ClassUtils.isPresent("com.fasterxml.jackson.core.JsonGenerator",
					AllEncompassingFormHttpMessageConverter.class.getClassLoader());

	private static final boolean jackson2XmlPresent =
			ClassUtils.isPresent("com.fasterxml.jackson.dataformat.xml.XmlMapper",
					AllEncompassingFormHttpMessageConverter.class.getClassLoader());

	private static final boolean gsonPresent =
			ClassUtils.isPresent("com.google.gson.Gson",
					AllEncompassingFormHttpMessageConverter.class.getClassLoader());


	public AllEncompassingFormHttpMessageConverter() {
		addPartConverter(new SourceHttpMessageConverter<Source>());

		if (jaxb2Present && !jackson2XmlPresent) {
			addPartConverter(new Jaxb2RootElementHttpMessageConverter());
		}

		if (jackson2Present) {
			addPartConverter(new MappingJackson2HttpMessageConverter());
		}
		else if (gsonPresent) {
			addPartConverter(new GsonHttpMessageConverter());
		}

		if (jackson2XmlPresent) {
			addPartConverter(new MappingJackson2XmlHttpMessageConverter());
		}
	}

}

常用表提交内容类型(Content-Type)

1 application/x-www-form-urlencoded

提交的数据按照 key1=val1&key2=val2 的方式进行编码,大多数的数据提交为这种方式,包括JQuery的ajax等。在Spring中可以使用@RequestParam,@RequestBody,@ModelAttribute处理。

1
2
3
4
POST http://www.example.com HTTP/1.1
Content-Type: application/x-www-form-urlencoded;charset=utf-8

title=test&content=test
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
var data =  {
    name : 'binbean'
};

$.ajax('/test', {
    method:'POST',
    //  将数据编码为表单模式
    contentType:'application/x-www-form-urlencoded; charset=UTF-8',
    //  数据必须为JS对象,非字符串
    data : data,
    success : function(datas) {
        console.log(datas)
    }
})

spring中对应的处理方式为

  • 方法1,使用@RequestParam

    1
    2
    3
    4
    5
    6
    7
    8
    
    @RequestMapping(value = "/test", method = RequestMethod.POST)
    public ResponseEntity<String> test(
    	@RequestParam("param1") String param1,
    	@RequestParam("param2") String param2, 			     @RequestParam("param3") String param3) {
    ...
    ...
    return new ResponseEntity<String>(HttpStatus.OK);
    }
  • 方法2,使用@RequestBody,MultiValueMap接收提交数据

    1
    2
    3
    4
    5
    6
    
    @RequestMapping(value = "/test", method = RequestMethod.POST)
    public ResponseEntity<String> test(@RequestBody MultiValueMap<String, String> params) {
    ...
    ...
    return new ResponseEntity<String>(HttpStatus.OK);
    }
  • 方法3,使用@ModelAttribute,对象(User)接收提交的数据

    1
    2
    3
    4
    5
    6
    7
    8
    
    @RequestMapping(value = "/test", method = RequestMethod.POST)
    public ResponseEntity<String> test(@ModelAttribute("user") User user)
    { ...... }
    
    @ModelAttribute("user")
    public User getUser() {
    return new User();
    }

2 multipart/form-data

常见的上传文件表单提交方式。可使用@RequestParam注解处理。@RequestBody不能处理这种类型的数据。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
@RequestMapping("/fileUpload")
public String fileUpload(@RequestParam("file") MultipartFile file) {
		// 判断文件是否为空
		if (!file.isEmpty()) {
			try {
				// 文件保存路径
				String filePath = "/upload/" + file.getOriginalFilename();
				// 转存文件
				file.transferTo(new File(filePath));
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
}

3 application/json

以json格式提交数据。可以使用@RequestParam,@RequestBody处理接收数据。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
var data =  {
    name : 'binbean'
};
$.ajax('/test', {
    method:'POST',
    contentType:'application/json;charset=utf-8', charset=UTF-8',
    //  数据必须转换为字符串
    data : JSON.stringify(data),
    success : function(datas) {
        console.log(datas)
    }
})