HttpMessageConver 的原理

HttpMessageConverter 原理

HttpMessageConverter 是 Spring 3.0 提供的一个新接口。负责将请求消息转为一个对象。也负责把一个对象转为响应消息。

你可以通过源码查看:

ublic interface HttpMessageConverter<T> {

	boolean canRead(Class<?> clazz, @Nullable MediaType mediaType);

	boolean canWrite(Class<?> clazz, @Nullable MediaType mediaType);

	List<MediaType> getSupportedMediaTypes();

	T read(Class<? extends T> clazz, HttpInputMessage inputMessage)
			throws IOException, HttpMessageNotReadableException;

	void write(T t, @Nullable MediaType contentType, HttpOutputMessage outputMessage)
			throws IOException, HttpMessageNotWritableException;

}

Spring MVC 定义了该转换器的接口来表示转换消息的过程。通过下面例子观察

例子:

@ResponseBody
@RequestMapping(value="/string", method=RequestMethod.POST)
public String test(@RequestBody String string) {
    return "result:" + string;
}

首先,在进入 test 方法之前,会先根据 @RequestBody 注解注解的参数,选择合适的 HttpMessageConverter 的消息转换器,来把消息体写入到 string 变量中,而这里的消息转换器也就是 StringHttpMessageConverter,它的 canRead 返回 true,后面执行 read 方法,把 HttpInputMessage 中的消息体读出来。

当执行完 test 方法,因为有 @ResponseBody 注解,则会调用 write() 方法,通过把 t(也就是返回值)通过 HttpOutMessage 来写出到响应体中。并且 canWrite() 返回 true。其中 MediaType 指的是对请求的Media Type属性的封装。

流程:

  1. 客户端发送请求报文
  2. 请求报文在通过前端控制器,交给 HttpInputMessage
  3. HttpInputMessage 可以把请求报文交给 HttpMessageConverter 转换器,变成 Java 对象。
  4. 最后把 Java 对象交给 Spring MVC 请求处理器
  5. 然后请求处理器把 Java 对象交给 HttpMessageConverter 转换器
  6. 转换器负责调用 HttpOutputMessage,输出到响应报文发送给客户端

那么 HttpMessageConverter 在 SpringMVC 如何使用体现?

HttpMessageConverter 使用

HttpMessageConverter 将请求的信息绑定到处理器目标方法的入参,或者将响应结果转为对应的类型消息。在 Spring 中提供了两种途径

  • 使用 @RequestBody 和 @ResponseBody 对请求处理器的入参、目标方法进行注解。
  • 使用 HttpEntity 和 ResponseEntity 作为请求处理器目标方法的入参和返回值。(HttpEntity 对应 @RequestBody, ResponseEntity 对应 @ResponseBody)

当请求处理器使用到上述的几种方式的时候,SpringMVC 首先根据请求头或下响应头的 Accept 属性匹配 HttpMesssageConverter ,进而根据参数类型或者泛型的类型的过滤得到匹配的HttpMessageConverter,如果找不到,则报错。

细节:

  • 使用 @RequestBody 和 HttpEntity 的效果一样
  • 使用 @ResponseBody 和 ResponseEntity 的效果是一样的
  • @ResponseBody 使用在方法上,@RequestBody 使用在参数上

范例:

  1. 使用 @ResponseBody 返回一个字符串

    	@ResponseBody
    	@RequestMapping("testResponseBody")
    	public String testJson() {
    		return "success;"
    	}
    
  2. 使用 ResponseEntity 返回字符串

    	@RequestMapping("testResponseEntity")
    	public ResponseEntity testDownload1(HttpServletRequest request) throws Exception{
    		ResponseEntity responseEntity = new ResponseEntity<String>("success", HttpStatus.OK);
    		return responseEntity;
    	}
    
  3. 使用 @RequestBody 来获取表单的所有请求参数

    	@RequestMapping("testRequestBody")
    	public void testUpload1(@RequestBody String body) {
    		System.out.println(body);
    	}
    

    表单

     <form action="${pageContext.request.contextPath}/testRequestBody" method="post"  >
     	<input type="text" name="name" value="aaa" ><br>
     	<input type="text" name="age" value="18" ><br>
     	<input type="submit" value="提交">
     </form>
    

    结果

    name=aaa&age=18
    
  4. 使用 HttpEntity 来获取表单的所有请求参数

    	@RequestMapping("testRequestEntity")
    	public void testRequestEntity(HttpEntity<String> entity) {
    		System.out.println(entity.getBody());
    	}
    

    表单和上面一样,只需要修改提交的 URL 即可,结果也和上面一样。

注意:

  • 对于注解和实体类(HttpEntity 和 ResponseEntity )的写法是不相同的。其中两个实体类需要指定泛型,该泛型也就表示调用哪个对应的消息转换器。
  • 消息转换器有很多,包括 StringHttpMessageConverter,ObjectToStringHttpMessageConverter,GsonHttpMessageConverter(需要导入 Json 的 jar 包)等等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值