Spring:深入分析SpringMVC之HttpMessageConverter<T>类

HttpMessageConverter是Spring的一个重要接口,它负责将请求信息转换为一个对象,将对象输出为响应信息。

DispatcherServlet默认已经安装了RequestMappingHandlerAdapter作为HandlerAdapter的组件实现类,HttpMessageConverter即由RequestMappingHandlerAdapter使用,将请求信息转换为对象,或将对象转换为响应信息。

HttpMessageConverter接口定义了以下几个方法。

Boolean canRead(Class<?> clazz,MediaType mediaType):

指定转换器可以读取的媒体类型(如text/html、application/json等),MIME媒体类型在RFC2616中定义,详细可以参考:http://www.w3school.com.cn/media/media_mimeref.asp 。

Boolean canWrite(Class<?> clazz,MediaType mediaType):

指定转换器可以将clazz类型的对象写道响应流中,响应流支持的媒体类型在mediaType中定义。

List<MediaType> getSupportedMediaTypes():

该转换器支持的媒体类型。

T read(Class<? extends T> clazz,HttpInputMessage inputMessage):

将请求信息流转换为T类型的对象。

void write(T t,MediaType contentType,HttpOutputMessage outputMessage):

将T类型的对象写到响应流中,同时指定响应的媒体类型为contentType。

1 HttpMessageConverter<T>的实现类

Spring为HttpMessageConverter提供了众多的实现类,他们组成了一个功能强大用途广泛的HttpMessageConverter家族:

RequestMappingHandlerAdapter默认已经装配了一下HttpMessageConverter:

[1] StringHttpMessageConverter。

[2] ByteArrayHttpMessageConverter。

[3] SourceHttpMessageConverter。

[4] AllEncompassingFormHttpMessageConverter。

如果需要装配其他类型的HttpMessageConverter,则可以在Spring的web容器上下文中自定义一个RequestMappingHandlerAdapter:

<!-- 定义一个RequestMappingHandlerAdapter -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter" p:messageConverters-ref="messageConverters"/>
<!-- HttpMessageConverter列表 -->
<util:list id="messageConverters">
    <bean class="org.springframework.http.converter.BufferedImageHttpMessageConverter"/>
    <bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter"/>
    <bean class="org.springframework.http.converter.StringHttpMessageConverter"/>
    <bean class="org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter"/>
</util:list>

如果在SpringWeb容器中显示定义了一个RequestMappingHandlerAdapter,则SpringMVC将使用它覆盖默认的RequestMappingHandlerAdapter。

2 使用HttpMessageConverter

如何使用HttpMessageConverter将请求信息转换并绑定到处理方法的参数中呢?SpringMVC提供了两种途径

[1] 使用@RequestBody/@ResponseBody对方法进行标注。

[2] 使用HttpEntity作为处理方法的参数或返回值。

@Controller
@RequestMapping("/user")
public class UserController{
    @RequestMapping(value = "/getUser")
    public void getUser(@RequestBody String requestBody){
        System.out.println(requestBody);
    }

    @ResponseBody
    @RequestMapping(value = "/getUserList")
    public List<Object> getUserList(){
        return Lists.newArrayList();
    }
}

RestTemplate是Spring的模板类,在哭护短程序中可使用该类调用Web服务器端的服务,它支持REST风格的URL。此外,它像RequestMappingHandlerAdapter一样拥有一张HttpMessageConverter的注册表,RestTemplate默认已经注册了一下HttpMessageConverter:

[1] ByteArrayHttpMessageConverter。

[2] StringHttpMessageConverter。

[3] ResourceHttpMessageConverter。

[4] SourceHttpMessageConverter。

[5] AllEncompassingFormHttpMessageConverter。

所以,在默认情况下,RestTemplate就可以利用这些HttpMessageConverter对响应数据进行相应的转换处理。可通过RestTemplate的setMessageConverters(List<HttpMessage-Converter<?>> messageConverters)方法手工注册HttpMessageConverter。

和@RequestBody/@ResponseBody类似,HttpEntity不但可以访问请求和响应报文体的数据,还可以访问请求和响应报文头的数据。SpringMVC根据HttpEntity的泛型类型查找对应的HttpMessageConverter。

    @RequestMapping(value = "/query")
    public void query(HttpEntity<String> httpEntity){
        System.out.println(httpEntity);
    }

    @RequestMapping(value = "/image")
    public ResponseEntity<byte[]> image() throws IOException {
        Resource resource = new ClassPathResource("/image.jpg");
        byte[] file = FileCopyUtils.copyToByteArray(resource.getInputStream());
        return  new ResponseEntity<byte[]>(file, HttpStatus.OK);
    }

通过上面两个方法可以得出以下几条结论:

① 当控制器处理方法使用@RequestBody/@ResponseBody或HttpEntity/ResponseEntity时,Spring首先根据请求头或响应头的Accept属性选择匹配的HttpMessageConverter,然后根据参数类型或反省类型的过滤得到匹配的HttpMessageConverter,如果找不到可用的HttpMessageConverter则报错。

② 当控制器处理方法使用@RequestBody/@ResponseBody或HttpEntity/ResponseEntity时,Spring首先根据请求头或响应头的Accept属性选择匹配的HttpMessageConverter,然后根据参数类型或反省类型的过滤得到匹配的HttpMessageConverter,如果找不到可用的HttpMessageConverter则报错。

③ @RequestBody和@ResponseBody不需要成对出现。如果方法参数使用了@RequestBody,则SpringMVC选择匹配的HttpMessageConverter将请求消息转换并绑定到该参数中。如果处理方法标注了@ResponseBody,则SpringMVC选择匹配的HttpMessageConverter将方法返回值转换并输出响应消息。

④ HttpEntity/ResponseEntity的功能和@RequestBody/@ResponseBody相似。

3 处理XML和JSON

SpringMVC提供了几个处理XML和JSON格式的请求/响应消息的HttpMessageConverter。

[1] MarshallingHttpMessageConverter:处理XML格式的请求或响应消息。

[2]Jaxb2RootElementHttpMessageConverter:同上,底层使用JAXB。

[3] MappingJackson2HttpMessageConverter:处理JSON格式的请求或响应消息。

因此,只要在Spring Web容器中为RequestMappingHandlerAdapter装配好响应的处理XML和JSON格式的请求/响应消息的HttpMessageConverter,并在交互中通过请求的Accept指定MIME类型,SpringMVC就可使服务器端的处理方法和客户端透明的通过XML或JSON格式的消息进行通信,开发者几乎无需关心通信层数据格式的问题,可以将精力集中到业务层的处理上。单就这一点而言,其他MVC框架就无法和SpringMVC相比。

感觉这个特性虽然很强大,但是还没遇到过类似需要的应用场景,所以demo就不写啦。

Spring MVC中的XML文件通常用于配置Spring框架的各种组件,包括控制器、服务、数据访问对象(DAO)、以及依赖注入等。`<property>`标签是Spring XML配置文件中用于注入依赖的一个元素。它主要用于注入属性值,可以是基本数据型、引用型或者是集合型。 一个简单的例子是,在Spring的bean配置文件中,我们可以使用`<property>`标签来为某个对象的属性赋值。例如,如果你有一个User,其中包含name和age属性,你可以这样使用`<property>`标签来注入这些属性: ```xml <bean id="user" class="com.example.User"> <property name="name" value="张三"/> <property name="age" value="25"/> </bean> ``` 在这个例子中,`<property>`标签有两个属性:`name`和`value`。`name`属性指定了要注入的属性的名称,而`value`属性指定了要注入的具体值。 另外,`<property>`标签还可以引用其他bean或者集合型的值: ```xml <bean id="databaseProperties" class="com.example.DatabaseProperties"> <property name="url" value="jdbc:mysql://localhost:3306/db"/> <property name="username" value="dbuser"/> <property name="password" value="dbpassword"/> </bean> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="com.mysql.jdbc.Driver"/> <property name="jdbcUrl" ref="databaseProperties.url"/> <property name="user" ref="databaseProperties.username"/> <property name="password" ref="databaseProperties.password"/> </bean> ``` 在这个例子中,`dataSource` bean的某些属性通过`<property>`标签的`ref`属性被引用自`databaseProperties` bean的相应属性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值