• HttpMessageConverter


    HttpMessageConverter<T>是Spring3的一个重要接口,它负责将请求信息转换为一个对象(类型为T),将对象(类型为T)输出为响应信息。

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

    HttpMessageConverter<T>接口定义以下几个方法:

    /**
     * Strategy interface that specifies a converter that can convert from and to HTTP requests and responses.
     */
    public interface HttpMessageConverter<T> {
    
        /**
         * Indicates whether the given class can be read by this converter.
         */
        boolean canRead(Class<?> clazz, MediaType mediaType);
    
        /**
         * Indicates whether the given class can be written by this converter.
         */
        boolean canWrite(Class<?> clazz, MediaType mediaType);
    
        /**
         * Return the list of {@link MediaType} objects supported by this converter.
         */
        List<MediaType> getSupportedMediaTypes();
    
        /**
         * Read an object of the given type form the given input message, and returns it.
         */
        T read(Class<? extends T> clazz, HttpInputMessage inputMessage)
                throws IOException, HttpMessageNotReadableException;
    
        /**
         * Write an given object to the given output message.
         */
        void write(T t, MediaType contentType, HttpOutputMessage outputMessage)
                throws IOException, HttpMessageNotWritableException;
    
    }

    Spring为HttpMessageConverter提供了众多的实现类

    RequestMappingHandlerAdapter默认已经注册了以下HttpMessageConverter:

    private List<HttpMessageConverter<?>> messageConverters;
    public RequestMappingHandlerAdapter() {
        StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter();
        stringHttpMessageConverter.setWriteAcceptCharset(false);  // see SPR-7316
        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());
    }

     如果需要装配其他类型的HttpMessageConverter,可以在Spring的web容器(Spring子容器)上下文中自行定义一个RequestMappingHandlerAdapter,注册若干HttpMessageConverter。dispatcher-servlet.xml

    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
        <property name="messageConverters" ref="messageConverters"/>
    </bean>
    <!--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"/>
        <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>
    </util:list>

     如果在Spring web容器中显式定义了一个RequestMappingHandlerAdapter,则Spring MVC将使用它覆盖默认的AnnotationMethodHandlerAdapter(默认配置就没有了)。

    如何使用 HttpMessageConverter<T> 将请求信息转换并绑定到处理方法的入参中或将响应结果转为对应类型的响应信息,Spring MVC提供了两种途径:

    1. 使用@RequestBody/@ResponseBody 对处理方法进行标注

    2. 使用HttpEntity<T>/ResponseEntity<T> 作为处理方法的入参或返回值

    示例1:

    @RequestMapping(value = "/handle41")
    public String handle41(@RequestBody String requestBody){
        //将请求-报文体-转换为字符串绑定到requestBody入参中
    }
    @ResponseBody
    @RequestMapping("/handle42")
    public byte[] handle42(){
        //
    }

     handle41()处Spring MVC将根据requestBody的类型(String)查找匹配的HttpMessageConverter由于StringHttpMessageConverter的泛型类型对应String,所以StringHttpMessageConverter将会被Spring MVC选中,用它将请求体(POST)信息进行转换并且将结果绑定到requestBody入参上!

    handle42()处,由于方法的返回值类型为byte[],所以Spring MVC根据类型匹配的查找规则将使用ByteArrayHttpMessageConverter对返回值进行处理。

    和@RequestBody/@ResponseBody类似,HttpEntity<?>不但可以访问请求和响应报文头的数据,还可以访问请求和响应报文体的数据(也就是HttpEntity中不但有头数据还有体数据),Spring MVC根据HttpEntity的泛型类型查找对应的HttpMessageConverter

    在接收到一个http请求的时候,处理方法如何知道请求消息的格式,在处理完成之后又根据什么确定响应消息的格式?答案很简单,根据请求消息头的"Content-Type"及Accept属性确定。

    Content-Type表示本次请求的报文内容格式。

    Accept表示接受的MIME类型。

    例如:
    @ResponseBody
    @RequestMapping( "/getEmployeesForJson")
    public Collection<Employee> getEmployees() {
        return employeeDao .getAll();
    }
     请求时的目标类型:
    方法的实际返回值为:Employee 的集合
    SpringMVC 发现需要返回的是JSON类型,但实际返回的是Employee的集合。此时@ResponseBody查找有没有把结果转为JSON的HttpMessageConverter,如果有,则调用其对应的方法,把结果转为JSON类型。
    结论:
    1.只有当处理器方法使用到@RequestBody/@ResponseBody 或HttpEntity<T>/ResponseEntity<T> 时,SpringMVC才使用注册的HttpMessageConverter 对请求响应消息进行处理。
    2.当控制器处理方法使用到 @RequestBody/@ResponseBody 或HttpEntity<T>/ResponseEntity<T> 时,Spring 首先根据请求头或响应头的 Accept 属性选择匹配的 HttpMessageConverter, 然后根据参数类型或泛型类型的过滤得到匹配的 HttpMessageConverter, 若找不到可用的HttpMessageConverter 将报错
    3.@RequestBody 和 @ResponseBody 不需要成对出现。如果方法入参使用到了@RequestBody,SpringMVC将会选择匹配的HttpMessageConverter 将请求信息转换并绑定到该入参中。如果处理方法标注了@ResponseBody,SpringMVC选择匹配的HttpMessageConverter 将方法返回值转换并输出响应消息。
  • 相关阅读:
    js上传Excel文件
    在typescript中import第三方类库clipboard报错
    webpack学习(一)安装和命令行、一次js/css的打包体验及不同版本错误
    querySelector和getElementById之间的区别
    关于js延迟加载(异步操作)的方式
    addEventListener与attachEvent
    ES6 的Object.assign(target, source_1, ..., source_n)方法与对象的扩展运算符
    JS实现生成一个周对应日期数组
    微信小程序之媒体查询@media
    微信小程序之页面引用utils中的js文件
  • 原文地址:https://www.cnblogs.com/winner-0715/p/7437868.html
Copyright © 2020-2023  润新知