Spring Boot中如何使用Convert接口實(shí)現(xiàn)類型轉(zhuǎn)換器
使用Convert接口實(shí)現(xiàn)類型轉(zhuǎn)換器
在Spring3中引入了一個(gè)Converter接口,它支持從一個(gè)Object轉(zhuǎn)為另一個(gè)Object。除了Converter接口之外,實(shí)現(xiàn)ConverterFactory接口和GenericConverter接口也可以實(shí)現(xiàn)我們自己的類型轉(zhuǎn)換邏輯。
Converter接口
首先看看Converter接口的定義
public interface Converter<S, T> { T convert(S source); }
可以看到這個(gè)接口是使用了泛型的,S表示原類型,T表示目標(biāo)類型,然后里面定義了一個(gè)convert方法,將原類型對(duì)象作為參數(shù)傳入進(jìn)行轉(zhuǎn)換之后返回目標(biāo)類型對(duì)象。
下面在Spring Boot中使用Converter接口來(lái)實(shí)現(xiàn)將String類型分別轉(zhuǎn)換為Data,自定義對(duì)象和List<自定義對(duì)象>。
添加依賴
添加spring-boot-starter-web依賴
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
實(shí)體類
1.User類
public class User { private long id; //用戶名 private String name; //出生日期 private Date birth; //關(guān)聯(lián)用戶 private User linkUser; //喜歡的文章 private List<Article> favArticles=new ArrayList<>(); //下面省略Getter和Setter方法
2.Article類
public class Article { //文章id private long artId; //文章名 private String artName; //下面省略Getter和Setter方法 }
配置類型轉(zhuǎn)化器
下面三個(gè)類都需要添加@Component注解,否則不能生效。并實(shí)現(xiàn)Spring提供的org.springframework.core.convert.converter.Converter接口,重寫其中的convert()方法 ,方法中寫自己的轉(zhuǎn)換邏輯。
1.定義全局日期轉(zhuǎn)換器
@Component public class DateConvert implements Converter<String,Date> { //日期格式 SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd"); @Override public Date convert(String s) { if (s!=null&&!"".equals(s)){ try { //解析參數(shù) Date date=sdf.parse(s); return date; } catch (ParseException e) { e.printStackTrace(); } } return null; } }
2.定義全局對(duì)象轉(zhuǎn)換器
這里使用Jackson的ObjectMapper類的readValue()函數(shù)實(shí)現(xiàn)將Json字符串反序列化為Java對(duì)象
@Component public class ObjectConvert implements Converter<String,User> { @Override public User convert(String s) { ObjectMapper objectMapper=new ObjectMapper(); if (s!=null&&!"".equals(s)){ try { User user=objectMapper.readValue(s,User.class); return user; } catch (JsonProcessingException e) { e.printStackTrace(); } } return null; } }
3.定義全局List類型轉(zhuǎn)換器
這里使用Jackson的ObjectMapper類的readValue()函數(shù)實(shí)現(xiàn)將Json字符串反序列化為 List
@Component public class StringToListController implements Converter<String, List<Article>> { ObjectMapper objectMapper=new ObjectMapper(); @Override public List<Article> convert(String s) { List<Article> list=null; try { list=objectMapper.readValue(s, new TypeReference<List<Article>>() { }); } catch (JsonProcessingException e) { e.printStackTrace(); } return list; } }
控制器
這里注意使用produces設(shè)置返回?cái)?shù)據(jù)的類型為json,consumes設(shè)置提交內(nèi)容的類型為:application/x-www-form-urlencoded。
application/x-www-form-urlencoded作用:將鍵值對(duì)的參數(shù)用&連接起來(lái),如果有空格,將空格轉(zhuǎn)換為+加號(hào);有特殊符號(hào),將特殊符號(hào)轉(zhuǎn)換為ASCII HEX值。
@RestController public class HelloController { @GetMapping("hello") public Date getDate(Date birth){ System.out.println(birth); return birth; } @PostMapping(value="showUser",produces="application/json", consumes = "application/x-www-form-urlencoded") public User showUser(User user){ return user; } }
測(cè)試
在Postman中進(jìn)行測(cè)試,注意以下設(shè)置:POST請(qǐng)求 -> Body -> x-www-form-urlencoded。在Body中輸入?yún)?shù)進(jìn)行測(cè)試。
因?yàn)閰?shù)中有Json類型參數(shù),如果直接使用Params下進(jìn)行發(fā)送數(shù)據(jù),會(huì)出現(xiàn)請(qǐng)求參數(shù)異常錯(cuò)誤。
測(cè)試結(jié)果:
Converter使用及其原理
在Spring MVC開發(fā)中,我們可以很方便的使用Converter來(lái)實(shí)現(xiàn)對(duì)請(qǐng)求參數(shù)的處理,比如字符串去空,日期格式化等。
配置文件中對(duì)Converter的引用
<!-- 屬性編輯器 --> <bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean"> <property name="converters"> <list> <bean class="com.xxx.common.converter.StringTrimConverter" /> <bean class="com.xxx.common.converter.DateConverter" /> <bean class="com.xxx.common.converter.DatetimeConverter" /> </list> </property> </bean> <mvc:annotation-driven conversion-service="conversionService">
如上代碼,我們配置了三種類型的Converter。
以字符串去空為例
import org.springframework.core.convert.converter.Converter; /** * 去除前后空格 * @author * */ public class StringTrimConverter implements Converter<String, String> { public String convert(String source) { //如果源字符串不為空則進(jìn)行轉(zhuǎn)換 if(source != null){ //去除源字符串前后空格 source = source.trim(); if(source.equals("")){ source = null; } } return source; } }
配置好以上內(nèi)容,即可在我們的請(qǐng)求中實(shí)現(xiàn)字符串自動(dòng)去空格。
明白使用其實(shí)很簡(jiǎn)單,我們可以看下在Spring的底層,具體是如何實(shí)現(xiàn)Converter的。我們以字符串去空的代碼為例。
以上代碼,首先實(shí)現(xiàn)了Converter接口
我們查看Converter接口的源碼
/** * A converter converts a source object of type S to a target of type T. * Implementations of this interface are thread-safe and can be shared. * * <p>Implementations may additionally implement {@link ConditionalConverter}. * * @author Keith Donald * @since 3.0 * @see ConditionalConverter * @param <S> The source type * @param <T> The target type */ public interface Converter<S, T> { /** * Convert the source of type S to target type T. * @param source the source object to convert, which must be an instance of S * @return the converted object, which must be an instance of T * @throws IllegalArgumentException if the source could not be converted to the desired target type */ T convert(S source); }
通過(guò)JavaDoc我們可以看到,實(shí)現(xiàn)該接口,可以使我們將S類型的對(duì)象轉(zhuǎn)換為T類型。那么對(duì)應(yīng)的我們對(duì)于Date類型的轉(zhuǎn)換,就可寫為如下代碼:
public class DateConverter implements Converter <bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
該類的對(duì)象,繼續(xù)查看對(duì)應(yīng)改類的源碼,以及對(duì)應(yīng)的JavaDoc。我們可以在該類的Doc中看到如下描述:
* <p>Like all {@code FactoryBean} implementations, this class is suitable for * use when configuring a Spring application context using Spring {@code <beans>} * XML. When configuring the container with * {@link org.springframework.context.annotation.Configuration @Configuration} * classes, simply instantiate, configure and return the appropriate * {@code FormattingConversionService} object from a * {@link org.springframework.context.annotation.Bean @Bean} method.
該類適用于適用XML構(gòu)建Spring應(yīng)用。
我們查看對(duì)應(yīng)的成員變量:
public class FormattingConversionServiceFactoryBean implements FactoryBean<FormattingConversionService>, EmbeddedValueResolverAware, InitializingBean { private Set<?> converters; private Set<?> formatters; private Set<FormatterRegistrar> formatterRegistrars; private boolean registerDefaultFormatters = true; private StringValueResolver embeddedValueResolver; private FormattingConversionService conversionService;
在配置XML時(shí),我們主要配置了集合類的converters,該類比較重要的方法如下:
@Override public void afterPropertiesSet() { this.conversionService = new DefaultFormattingConversionService(this.embeddedValueResolver, this.registerDefaultFormatters); ConversionServiceFactory.registerConverters(this.converters, this.conversionService); registerFormatters(); }
該方法實(shí)現(xiàn)了對(duì)conversionService中增減我們對(duì)應(yīng)的格式化器。
在Spring啟動(dòng)時(shí),注冊(cè)轉(zhuǎn)換器 時(shí)會(huì)進(jìn)入afterPropertiesSet 方法。在該方法中,我們可以看到Spring以HashSet來(lái)存儲(chǔ)對(duì)應(yīng)的converters。在ConversionServiceFactory中,判斷不同的轉(zhuǎn)換器,并進(jìn)行注冊(cè)。
public static void registerConverters(Set<?> converters, ConverterRegistry registry) { if (converters != null) { for (Object converter : converters) { if (converter instanceof GenericConverter) { registry.addConverter((GenericConverter) converter); } else if (converter instanceof Converter<?, ?>) { registry.addConverter((Converter<?, ?>) converter); } else if (converter instanceof ConverterFactory<?, ?>) { registry.addConverterFactory((ConverterFactory<?, ?>) converter); } else { throw new IllegalArgumentException("Each converter object must implement one of the " + "Converter, ConverterFactory, or GenericConverter interfaces"); } } } }
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Spring如何通過(guò)注解存儲(chǔ)和讀取對(duì)象詳解
在Spring中,要想更簡(jiǎn)單的存儲(chǔ)和讀取對(duì)象的核心是使用注解,這篇文章主要給大家介紹了關(guān)于Spring如何通過(guò)注解存儲(chǔ)和讀取對(duì)象的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-07-07springboot注冊(cè)攔截器所遇到的問(wèn)題
這篇文章主要介紹了springboot注冊(cè)攔截器的方法及所遇到的問(wèn)題,需要的朋友可以參考下2018-07-07tomcat啟動(dòng)完成執(zhí)行 某個(gè)方法 定時(shí)任務(wù)(Spring)操作
這篇文章主要介紹了tomcat啟動(dòng)完成執(zhí)行 某個(gè)方法 定時(shí)任務(wù)(Spring)操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-09-09Eclipse運(yùn)行android項(xiàng)目報(bào)錯(cuò)Unable to build: the file dx.jar was not
今天小編就為大家分享一篇關(guān)于Eclipse運(yùn)行android項(xiàng)目報(bào)錯(cuò)Unable to build: the file dx.jar was not loaded from the SDK folder的解決辦法,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2018-12-12java利用CompletionService保證任務(wù)先完成先獲取到執(zhí)行結(jié)果
這篇文章主要為大家詳細(xì)介紹了java如何利用CompletionService來(lái)保證任務(wù)先完成先獲取到執(zhí)行結(jié)果,文中的示例代碼講解詳細(xì),需要的可以參考下2023-08-08SpringBoot整合kaptcha實(shí)現(xiàn)圖片驗(yàn)證碼功能
這篇文章主要介紹了SpringBoot整合kaptcha實(shí)現(xiàn)圖片驗(yàn)證碼功能,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下2022-07-07SpringBoot集成Redis實(shí)現(xiàn)消息隊(duì)列的方法
這篇文章主要介紹了SpringBoot集成Redis實(shí)現(xiàn)消息隊(duì)列的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-02-02spring boot實(shí)戰(zhàn)之使用JSP的示例
本篇文章主要介紹了spring boot實(shí)戰(zhàn)之使用JSP的示例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-10-10java模擬TCP通信實(shí)現(xiàn)客戶端上傳文件到服務(wù)器端
這篇文章主要為大家詳細(xì)介紹了java模擬TCP通信實(shí)現(xiàn)客戶端上傳文件到服務(wù)器端,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-10-10java實(shí)現(xiàn)文件讀寫與壓縮實(shí)例
這篇文章主要介紹了java實(shí)現(xiàn)文件讀寫與壓縮實(shí)例,有助于讀者加深對(duì)文件操作的理解,需要的朋友可以參考下2014-07-07