SpringBoot自定義MessageConverter與內(nèi)容協(xié)商管理器contentNegotiationManager詳解
1、自定義消息轉(zhuǎn)換器MessageConverter
在WebMvcAutoConfiguration類中有一個(gè)方法configureMessageConverters(),它會配置默認(rèn)的MessageConverter
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { this.messageConvertersProvider.ifAvailable((customConverters) -> { converters.addAll(customConverters.getConverters()); }); }
假設(shè)我們現(xiàn)在有一個(gè)新的需求
想要后端返回我們自己定義的格式的數(shù)據(jù),就叫x-decade,格式為使用分號拼接Person對象屬性值
那么就要新建一個(gè)MessageConverter了
package com.decade.converters; import com.decade.pojo.Person; import org.springframework.http.HttpInputMessage; import org.springframework.http.HttpOutputMessage; import org.springframework.http.MediaType; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.HttpMessageNotReadableException; import org.springframework.http.converter.HttpMessageNotWritableException; import java.io.IOException; import java.io.OutputStream; import java.util.List; public class DecadeConverter implements HttpMessageConverter<Person> { // 只考慮寫出,所以這里默認(rèn)寫false @Override public boolean canRead(Class<?> clazz, MediaType mediaType) { return false; } @Override public boolean canWrite(Class<?> clazz, MediaType mediaType) { return clazz.isAssignableFrom(Person.class); } /** * 統(tǒng)計(jì)當(dāng)前converter能支持哪些類型 * @return 返回支持的媒體類型 */ @Override public List<MediaType> getSupportedMediaTypes() { return MediaType.parseMediaTypes("application/x-decade"); } // 只考慮寫出,所以這里默認(rèn)寫null @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 { // 自定義想要寫出的數(shù)據(jù)格式 String result = person.getName() + ";" + person.getAge() + ";" + person.getBirth(); // 寫出 final OutputStream body = outputMessage.getBody(); body.write(result.getBytes()); } }
我們發(fā)現(xiàn),WebMvcConfigurer接口類下面有2個(gè)關(guān)于配置MessageConverter的方法
// 會覆蓋默認(rèn)的MessageConverter default void configureMessageConverters(List<HttpMessageConverter<?>> converters) { } // 不會覆蓋,只會在默認(rèn)的MessageConverter后面追加我們自定義的 default void extendMessageConverters(List<HttpMessageConverter<?>> converters) { }
所以,我們選擇在自定義配置類中重寫extendMessageConverters()方法
package com.decade.config; import com.decade.converters.DecadeConverter; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import java.util.List; @Configuration(proxyBeanMethods = false) public class MyMvcConfig implements WebMvcConfigurer { @Bean public WebMvcConfigurer createConvert() { return new WebMvcConfigurer() { @Override public void extendMessageConverters(List<HttpMessageConverter<?>> converters) { converters.add(new DecadeConverter()); } }; } }
我們在請求頭中設(shè)置Accept為我們自定義的格式application/x-decade
驗(yàn)證結(jié)果如下
2、自定義內(nèi)容協(xié)商管理器contentNegotiationManager
問題:我們新建的x-decade格式是否只能通過postman調(diào)用才會生效呢?如果我們要使用瀏覽器參數(shù)方式,怎么才能生效呢?
因?yàn)槲覀冎暗?a href="http://www.dbjr.com.cn/article/264444.htm" target="_blank">【Spring Boot】響應(yīng)處理
它默認(rèn)只能處理xml和json格式,所以為了解決這個(gè)問題,我們就要自定義內(nèi)容協(xié)商管理器了
首先我們還是要在自定義配置類中重寫相關(guān)方法
package com.decade.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.MediaType; import org.springframework.web.accept.HeaderContentNegotiationStrategy; import org.springframework.web.accept.ParameterContentNegotiationStrategy; import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import java.util.Arrays; import java.util.HashMap; import java.util.Map; @Configuration(proxyBeanMethods = false) public class MyMvcConfig implements WebMvcConfigurer { @Bean public WebMvcConfigurer createConvert() { return new WebMvcConfigurer() { @Override public void configureContentNegotiation(ContentNegotiationConfigurer configurer) { // 設(shè)置支持的瀏覽器參數(shù)類型 Map<String, MediaType> mediaTypes = new HashMap<>(); mediaTypes.put("json", MediaType.APPLICATION_JSON); mediaTypes.put("xml", MediaType.APPLICATION_XML); mediaTypes.put("decade", MediaType.parseMediaType("application/x-decade")); final ParameterContentNegotiationStrategy strategy = new ParameterContentNegotiationStrategy(mediaTypes); // 為了繼續(xù)支持請求頭參數(shù)類型,還需要往里面塞請求頭內(nèi)容協(xié)商管理器 final HeaderContentNegotiationStrategy headerContentNegotiationStrategy = new HeaderContentNegotiationStrategy(); configurer.strategies(Arrays.asList(strategy, headerContentNegotiationStrategy)); } }; } }
可以看到,系統(tǒng)中的內(nèi)容協(xié)商管理器下面還是原來的2種:獲取請求頭中的Accept和獲取請求參數(shù)中的format
但是獲取請求參數(shù)format,除了能識別原來的json和xml,還能識別我們自定義的application/x-decade,它使用decade與之對應(yīng)
可以看到,我們自定義的媒體類型成功加入服務(wù)器能解析出來的類型
我們寫一個(gè)接口進(jìn)行驗(yàn)證
@GetMapping(value = "/testPerson") @ResponseBody public Person testPerson() { Person person = new Person(); person.setName("decade"); person.setAge(24); person.setBirth(new Date()); return person; }
由驗(yàn)證結(jié)果可以知道,我們從postman和瀏覽器都可以獲得我們指定格式的數(shù)據(jù)
到此這篇關(guān)于SpringBoot自定義MessageConverter與內(nèi)容協(xié)商管理器contentNegotiationManager詳解的文章就介紹到這了,更多相關(guān)SpringBoot MessageConverter內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JSR303校驗(yàn)注解和自定義校驗(yàn)注解的使用
這篇文章主要介紹了JSR303校驗(yàn)注解和自定義校驗(yàn)注解的使用,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09解決Springboot項(xiàng)目報(bào)錯(cuò):java:錯(cuò)誤:不支持發(fā)行版本?17
這篇文章主要給大家介紹了關(guān)于解決Springboot項(xiàng)目報(bào)錯(cuò):java:錯(cuò)誤:不支持發(fā)行版本17的相關(guān)資料,這個(gè)錯(cuò)誤意味著你的Spring Boot項(xiàng)目正在使用Java 17這個(gè)版本,但是你的項(xiàng)目中未配置正確的Java版本,需要的朋友可以參考下2023-08-08詳解Java中AC自動機(jī)的原理與實(shí)現(xiàn)
AC自動機(jī)是一個(gè)多模式匹配算法,在模式匹配領(lǐng)域被廣泛應(yīng)用。本文將詳細(xì)為大家介紹AC自動機(jī)的原理與實(shí)現(xiàn)方法,感興趣的可以了解一下2022-05-05springboot實(shí)現(xiàn)小程序支付的項(xiàng)目實(shí)踐
本文主要介紹了springboot實(shí)現(xiàn)小程序支付的項(xiàng)目實(shí)踐,?可以通過調(diào)用微信支付?API?實(shí)現(xiàn)支付功能,具有一定的參考價(jià)值,感興趣的可以了解一下2023-09-09