SpringBoot自定義MessageConvert詳細講解

前言

對於頁面攜帶的請求頭中的AcceptSpringBoot有對應的10種MessageConvert可以支持寫出對應的媒體類型,比如application/xml、application/json……

我們還可以通過向容器放入一個WebMvcConfigurer

實現定制化SpingMVC,自定義一個MessageConvert處理特殊的協議比如application/x-person

實現多協議數據兼容。json、xml、x-person

原理

0、@ResponseBody 響應數據出去 調用 RequestResponseBodyMethodProcessor 處理

1、Processor 處理方法返回值。通過 MessageConverter 處理

2、所有 MessageConverter 合起來可以支持各種媒體類型數據的操作(讀、寫)

3、內容協商找到最終的 messageConverter;

實現

/* 條件
 *
 * 1、瀏覽器發請求直接 返回xml   [application/xml]   jacksonXmlConverter
 * 2、如果是ajax請求 返回json   [application/json]  jacksonJsonConverter
 * 3、如果是app發請求,返回自定義協議數據 [application/x-person]   xxxxConverter
 *
 * 步驟:
 *  1、添加自定義的MessageConverter進系統底層
 *  2、系統底層就會統計出所有MessageConverter能操作哪些類型
 *  3、客戶端內容協商 [person—>person]
 */

person類

@Data
public class Person {
    public String username;
    public Integer age;
    public Pet pet;
}

pet類

@Data
public class Pet {
    public String name;
    public Integer age;
}
PersonMessageConvert
/*
 * 自定義的Convert
 */
public class PersonMessageConvert implements HttpMessageConverter<Person> {
    @Override
    public boolean canRead(Class<?> clazz, MediaType mediaType) {
        return false;
    }
    @Override
    public boolean canWrite(Class<?> clazz, MediaType mediaType) {
        return clazz.isAssignableFrom(Person.class);
    }
    /*
     * @Description 服務器需要統計所有MessageConvert都能寫出哪些類型,我們這裡也要自定義
     * @Param
     **/
    @Override
    public List<MediaType> getSupportedMediaTypes() {
        return MediaType.parseMediaTypes("application/x-person");
    }
    @Override
    public Person read(Class<? extends Person> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
        return null;
    }
    @Override
    public void write(Person person, MediaType contentType, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
        //自定義協會數據的寫出
        String data = person.getUsername() + ";" + person.getAge() + ";" +person.getPet() + ";";
        //寫出去
        OutputStream body = outputMessage.getBody();
        body.write(data.getBytes());
    }
}

方法

    @ResponseBody
    @GetMapping("/test/person")
    public Person getPeroson() {
        Person person = new Person();
        person.setUsername("張三");
        person.setAge(18);
        person.setPet(new Pet());
        return person;
    }

WebMvcConfigurer

    @Bean
    public WebMvcConfigurer webMvcConfigurer() {
        return new WebMvcConfigurer() {
            @Override
            public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
                converters.add(new PersonMessageConvert());
            }
       }
    }

測試

拓展

如何實現訪問路徑攜帶format參數指明協商協議

比如:http://localhost:8080/test/person?format=x-person

記得先開啟基於參數的內容協商

spring:
  mvc:
    contentnegotiation:
      favor-parameter: true

@Bean
    public WebMvcConfigurer webMvcConfigurer() {
        return new WebMvcConfigurer() {
            /*
             * 自定義內容協商策略
             */
            @Override
            public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
                Map<String, MediaType> mediaTypeMap = new HashMap<>();
                mediaTypeMap.put("json", MediaType.APPLICATION_JSON);
                mediaTypeMap.put("xml", MediaType.APPLICATION_XML);
                mediaTypeMap.put("x-person",MediaType.parseMediaType("application/x-person"));
                //指定支持解析那些參數的媒體類型
                ParameterContentNegotiationStrategy parametertrategy = new ParameterContentNegotiationStrategy(mediaTypeMap);
                HeaderContentNegotiationStrategy headerStrategy = new HeaderContentNegotiationStrategy();
                configurer.strategies(Arrays.asList(parametertrategy, headerStrategy));
            }
            @Override
            public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
                converters.add(new PersonMessageConvert());
            }
        };
    }

測試

註意:有可能我們添加的自定義的功能會覆蓋默認很多功能,導致一些默認的功能失效。比如上面的ContentNegotiationConfigurer 就會覆蓋原來的默認ContentNegotiationConfigurer

到此這篇關於SpringBoot自定義MessageConvert詳細講解的文章就介紹到這瞭,更多相關SpringBoot MessageConvert內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: