<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
在WebMvcAutoConfiguration類中有一個方法configureMessageConverters(),它會設定預設的MessageConverter
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { this.messageConvertersProvider.ifAvailable((customConverters) -> { converters.addAll(customConverters.getConverters()); }); }
假設我們現在有一個新的需求
想要後端返回我們自己定義的格式的資料,就叫x-decade,格式為使用分號拼接Person物件屬性值
那麼就要新建一個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> { // 只考慮寫出,所以這裡預設寫false @Override public boolean canRead(Class<?> clazz, MediaType mediaType) { return false; } @Override public boolean canWrite(Class<?> clazz, MediaType mediaType) { return clazz.isAssignableFrom(Person.class); } /** * 統計當前converter能支援哪些型別 * @return 返回支援的媒體型別 */ @Override public List<MediaType> getSupportedMediaTypes() { return MediaType.parseMediaTypes("application/x-decade"); } // 只考慮寫出,所以這裡預設寫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 { // 自定義想要寫出的資料格式 String result = person.getName() + ";" + person.getAge() + ";" + person.getBirth(); // 寫出 final OutputStream body = outputMessage.getBody(); body.write(result.getBytes()); } }
我們發現,WebMvcConfigurer介面類下面有2個關於設定MessageConverter的方法
// 會覆蓋預設的MessageConverter default void configureMessageConverters(List<HttpMessageConverter<?>> converters) { } // 不會覆蓋,只會在預設的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()); } }; } }
我們在請求頭中設定Accept為我們自定義的格式application/x-decade
驗證結果如下
問題:我們新建的x-decade格式是否只能通過postman呼叫才會生效呢?如果我們要使用瀏覽器引數方式,怎麼才能生效呢?
因為我們之前的【Spring Boot】響應處理
它預設只能處理xml和json格式,所以為了解決這個問題,我們就要自定義內容協商管理器了
首先我們還是要在自定義設定類中重寫相關方法
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) { // 設定支援的瀏覽器引數型別 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); // 為了繼續支援請求頭引數型別,還需要往裡面塞請求頭內容協商管理器 final HeaderContentNegotiationStrategy headerContentNegotiationStrategy = new HeaderContentNegotiationStrategy(); configurer.strategies(Arrays.asList(strategy, headerContentNegotiationStrategy)); } }; } }
可以看到,系統中的內容協商管理器下面還是原來的2種:獲取請求頭中的Accept和獲取請求引數中的format
但是獲取請求引數format,除了能識別原來的json和xml,還能識別我們自定義的application/x-decade,它使用decade與之對應
可以看到,我們自定義的媒體型別成功加入伺服器能解析出來的型別
我們寫一個介面進行驗證
@GetMapping(value = "/testPerson") @ResponseBody public Person testPerson() { Person person = new Person(); person.setName("decade"); person.setAge(24); person.setBirth(new Date()); return person; }
由驗證結果可以知道,我們從postman和瀏覽器都可以獲得我們指定格式的資料
到此這篇關於SpringBoot自定義MessageConverter與內容協商管理器contentNegotiationManager詳解的文章就介紹到這了,更多相關SpringBoot MessageConverter內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45