我們以自定義格式轉(zhuǎn)換器的實現(xiàn)思路,來理解新架構(gòu)的類型轉(zhuǎn)換器的使用方法,同時在實際開發(fā)中,我們可能會有自己的格式轉(zhuǎn)換需求,這個時候我們也可以通過自定義格式轉(zhuǎn)換器來完成這些個性化需求。
自定義格式轉(zhuǎn)換器
完成自定義轉(zhuǎn)換器需要實現(xiàn)以下三個中的任意一個接口:Convertor<S,T>、GenericConvertor或ConvertorFacoty。下面我們對這些接口進(jìn)行逐一分析:
1. Convertor<S,T>
這是最為簡單的一個接口,定義了從源類到目標(biāo)類的轉(zhuǎn)換方法。該接口的定義如下
1
2
3
4
|
public interface ConverterFactory<S, R> { //將S類型的對象轉(zhuǎn)換為T類型,R為目標(biāo)類型T的基類 <T extends R> Converter<S, T> getConverter(Class<T> targetType); } |
2. GenericConvertor
GenericConvertor會根據(jù)源類對象及目標(biāo)類對象所在宿主類的上下文信息進(jìn)行類型轉(zhuǎn)換工作,該接口的定義如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
public interface GenericConverter { //ConvertiblePair包含了源類型和目標(biāo)類型,它的定義在下面 Set<ConvertiblePair> getConvertibleTypes(); //TypeDescriptor包含了需轉(zhuǎn)換類型對象所在宿主類的信息,我們根據(jù)此信息,完成源到目標(biāo)類型的轉(zhuǎn)換 Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType); /** * 內(nèi)部類定義 */ public static final class ConvertiblePair { //源類型 private final Class<?> sourceType; //目標(biāo)類類型 private final Class<?> targetType; /** * 創(chuàng)建一個源-目標(biāo)對子 */ public ConvertiblePair(Class<?> sourceType, Class<?> targetType) { Assert.notNull(sourceType, "Source type must not be null" ); Assert.notNull(targetType, "Target type must not be null" ); this .sourceType = sourceType; this .targetType = targetType; } public Class<?> getSourceType() { return this .sourceType; } public Class<?> getTargetType() { return this .targetType; } //忽略hashCode\equals\toString等重寫方法 } } |
我們常使用其實現(xiàn)類接口:
1
2
|
public interface ConditionalGenericConverter extends GenericConverter, ConditionalConverter { } |
它除了實現(xiàn)GenericConverter,還實現(xiàn)了另一個“條件轉(zhuǎn)換器”:
1
2
3
4
5
6
7
|
public interface ConditionalConverter { /** * Should the conversion from {@code sourceType} to {@code targetType} currently under */ //根據(jù)源類型和目標(biāo)類型所在宿主類型的上下文信息判斷是否要進(jìn)行類型轉(zhuǎn)換 boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType); } |
在實際開發(fā)中,我們能實現(xiàn)此接口自定義轉(zhuǎn)換器,來根據(jù)具體類型上下文來靈活配置我們的類型轉(zhuǎn)換
3. ConvertorFacoty
這是一個將我們源類轉(zhuǎn)換為一個目標(biāo)類或其子類的”多轉(zhuǎn)換器共存“接口工廠。它的定義如下:
1
2
3
4
5
6
|
public interface ConverterFactory<S, R> { //獲取將源類轉(zhuǎn)換為特定R類或其子類的轉(zhuǎn)換器 <T extends R> Converter<S, T> getConverter(Class<T> targetType); } |
這個接口一個常見的實現(xiàn)類是StringToNumberConvertor,能將String類型數(shù)據(jù)轉(zhuǎn)換為Number類型或其子類:Long,Integer,Double等。
注冊自定義轉(zhuǎn)換器
ConversionService
ConversionService則是Spring類型轉(zhuǎn)換體系的核心接口,ConversionService接口的定義如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
package org.springframework.core.convert; public interface ConversionService { //判斷sourceType是否可以轉(zhuǎn)換為targetType boolean canConvert(Class<?> sourceType, Class<?> targetType); //TypeDescriptor描述了轉(zhuǎn)換類的各類上下文信息,在類型轉(zhuǎn)換實現(xiàn)方法中可以根據(jù)這些信息進(jìn)行靈活控制 //比如這里通過源類和目標(biāo)類的上下文信息判斷是否可以進(jìn)行轉(zhuǎn)換 boolean canConvert(TypeDescriptor sourceType, TypeDescriptor targetType); //將source轉(zhuǎn)換為targetType <T> T convert(Object source, Class<T> targetType); //利用源、目標(biāo)類的上下文信息,將源類型轉(zhuǎn)換為目標(biāo)類型 Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType); } |
ConversionServiceFactoryBean
實現(xiàn)以上類型完成我們的自定義轉(zhuǎn)換器定義后,我們還要在Spring容器中通過ConversionServiceFactoryBean注冊創(chuàng)建后才能使用。
ConversionServiceFactoryBean創(chuàng)建了我們的ConversionService很多內(nèi)置轉(zhuǎn)換器,利用這些轉(zhuǎn)換器,我們可以完成大部分常見的類型轉(zhuǎn)換工作
而如果我們想使用自定義的類型轉(zhuǎn)換器,可以通過ConversionServiceFactoryBean的convertor屬性來注冊。
實例分析1:測試Convertor
通過以上的分析,我們接下來嘗試自定實現(xiàn)Convert
1. 自定義屬性轉(zhuǎn)換器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
public class MyConvertor implements Converter<String, User>{ @Override public User convert(String source) { //source為要轉(zhuǎn)換的字符串 String[] values = source.split( "," ); //根據(jù)我們的需求,用逗號來區(qū)分 Integer id = Integer.valueOf(values[ 0 ]); User user = new User(id,values[ 1 ],values[ 2 ]); return user; } } /**********下面是我們的UserPOJO類**********/ public class User { public User() { super (); } private Integer id; private String userName; private String password; public Integer getId() { return id; } public void setId(Integer id) { this .id = id; } public User(Integer id, String userName, String password) { super (); this .id = id; this .userName = userName; this .password = password; } //忽略get和set方法 @Override public String toString() { return "User [id=" + id + ", userName=" + userName + ", password=" + password + "]" ; } } |
2. 注冊自定義屬性轉(zhuǎn)換器
1
2
3
4
5
6
7
8
9
10
|
<!-- 通過:annotation-driven的conversion-service屬性來裝配我們的類型轉(zhuǎn)換器 --> < mvc:annotation-driven conversion-service = "factoryBean" /> <!-- 通過ConversionServiceFactoryBean注冊我們的自定義轉(zhuǎn)換器 --> < bean class = "org.springframework.context.support.ConversionServiceFactoryBean" id = "factoryBean" > < property name = "converters" > <!-- 在屬性converters注冊 --> < list > < bean class = "com.mvc.convertor.MyConvertor" /> </ list > </ property > </ bean > |
3. 配置控制器
在控制層,我們通過以下方法測試我們的轉(zhuǎn)換器
1
2
3
4
5
|
@RequestMapping ( "convert" ) public String convert(User user){ System.out.println(user); return "model1" ; } |
4. 測試
啟動服務(wù)器,在游覽器中訪問[項目根路徑]/convert?user=11,myUserName,myPassword。
控制臺會打印信息:User [id=11, userName=myUserName, password=myPassword]。即springMVC幫我們完成了字符串到User類型的轉(zhuǎn)換。**這里需注意的是,我們的請求參數(shù)名”user”是和控制層方法入?yún)⒆兞縐ser user像對應(yīng)的,才能完成參數(shù)綁定進(jìn)而轉(zhuǎn)換類型
實例分析2:測試ConvertorFactory
1. 自定義類型轉(zhuǎn)換器
在實例1的基礎(chǔ)上,我們添加User的一個子類:SuperUser,作為”super”子類,它擁有了自己的專屬名字,我們將字符串”11,myUserName,myPassword,myName“轉(zhuǎn)換為我們的superUser對象,下面相對應(yīng)的自定義轉(zhuǎn)換器和POJO類
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
public class MySuperConvertor implements Converter<String, SuperUser>{ @Override public SuperUser convert(String source) { String[] values = source.split( "," ); Integer id = Integer.valueOf(values[ 0 ]); SuperUser superUser = new SuperUser(values[ 3 ], new User(id,values[ 1 ],values[ 2 ])); return superUser; } } /**********下面是SuperUser POJO類*********/ package com.mvc.model; public class SuperUser extends User { private String name; //忽略get和set方法 public SuperUser(String name,User user) { super (user.getId(),user.getUserName(),user.getPassword()); this .name = name; } public SuperUser() { super (); } @Override public String toString() { return "SuperUser [name=" + name + ", toString()=" + super .toString() + "]" ; } } |
除了配置上面的轉(zhuǎn)換器,還需自定義我們的轉(zhuǎn)換器工廠,在轉(zhuǎn)換器工廠中,我們根據(jù)目標(biāo)類型是User還是其子類SuperUser來調(diào)用相應(yīng)的自定義轉(zhuǎn)換器:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
public class MyConvertorFactory implements ConverterFactory<String, User>{ @Override //T類型必須是User或其子類,Stirng是我們的轉(zhuǎn)換源類 public <T extends User> Converter<String, T> getConverter( Class<T> targetType) { if (targetType == User. class ){ return (Converter<String, T>) new MyConvertor(); } else { return (Converter<String, T>) new MySuperConvertor(); } } } |
2. 注冊自定義屬性轉(zhuǎn)換器
1
2
3
4
5
6
7
8
9
10
11
|
<!-- 通過:annotation-driven的conversion-service屬性來裝配我們的類型轉(zhuǎn)換器 --> < mvc:annotation-driven conversion-service = "factoryBean" /> <!-- 通過ConversionServiceFactoryBean注冊我們的自定義轉(zhuǎn)換器 --> < bean class = "org.springframework.context.support.ConversionServiceFactoryBean" id = "factoryBean" > < property name = "converters" > <!-- 在屬性converters注冊 --> < list > <!--這里只要注冊我們自定義的轉(zhuǎn)換器工廠即可--> < bean class = "com.mvc.convertor.MyConvertorFactory" /> </ list > </ property > </ bean > |
3. 配置控制器
在實例1的基礎(chǔ)上,我們添加一個新方法
1
2
3
4
5
6
7
8
9
10
11
12
|
//這是原來的 @RequestMapping ( "convert" ) public String convert( User user){ System.out.println(user); return "model1" ; } //下面是新添加的方法 @RequestMapping ( "convertSuper" ) public String convert( SuperUser user){ System.out.println(user); return "model1" ; } |
4. 測試
運行服務(wù)器,我們在游覽器中輸入:
1. root/convert?user=10,myUserName,myPassword
控制臺輸出:User [id=10, userName=myUserName, password=myPassword]
2. root/convertSuper?superUser=11,myUserName,myPassword,myName
控制臺輸出:SuperUser [name=myName, toString()=User [id=11, userName=myUserName, password=myPassword]]
我們根據(jù)入?yún)㈩愋停⑼ㄟ^ConvertFactory,完成對同一系列(某一類及其子類)的類型轉(zhuǎn)換
源碼下載
本篇文章測試源碼可到https://github.com/jeanhao/spring的dataConvertor文件夾下下載
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持服務(wù)器之家。
原文鏈接:http://blog.csdn.net/qwe6112071/article/details/51056781