重点: 格式化转换器
类型转换及格式化的意义
在如WEB /客户端项目中,通常需要将数据转换为符合需求的类型进行处理,展示时也需要将数据转化为具有某种格式的字符串进行展示
业务场景:
日期属性,都会用到数据转换和格式化。存的时候为了保证性能采用int 或 long,而展示的时候为了用户体验会展示成日期格式。
固定电话号码,存储的时候将区号和座机号码分开存储,展示时区号和座机号码组合展示。
》实现类型转换及格式化
- PropertyEditor (属性编辑器)
- Converter (转换器)
- Formatter (格式化器)
>使用属性编辑器实现类型转换
- 实现自定义属性编辑器
·继承PropertyEditorSupport
·重写setAsText()方法,表示将String -> Object
·并且在setAsText()方法内通过setValue()方法,设置属性的值
·重写getAsText: 表示将Object -> String
/**
* 自定义属性编辑器
* @author Administrator
*
*/
public class MyPropertyEditor extends PropertyEditorSupport {
@Override
public String getAsText() {
Carmodel car = (Carmodel)getValue();
return car==null ? "" : car.toString();
}
@Override
public void setAsText(String text) throws IllegalArgumentException {
// 汽车的参数传递: 品牌,价格,颜色 例:car=benchi,40,red
// 前台传递参数时需要严格按照约定好的方式传参
if(null==text || "".equals(text.trim())){
return;
}else{
// 获取参数
String[] strArr = text.split(",");
Carmodel car = new Carmodel();
// 品牌
car.setBrand(strArr[0]);
// 价格
car.setPrice(Double.parseDouble(strArr[1]));
// 颜色
car.setColor(strArr[2]);
setValue(car);
}
}
}
- 注册自定义属性编辑器
·通过@InitBinder 注解实现属性编辑器的注册
·可以注册自定义的,也可以注册框架内建的
/**
* 验证属性编辑器的控制器
* @author Administrator
*
*/
@Controller
@RequestMapping("/prop")
public class PropController {
// 跳转页面
@RequestMapping("/toUserInfo.do")
public String toUserInfo(UserModel user,Model model){
model.addAttribute("user",user);
System.out.println("用户信息:"+user.toString());
return "userInfo";
}
// 绑定属性编辑器
@InitBinder
public void initData(WebDataBinder binder){
// 用来注册属性编辑器
// 注册自定义的属性编辑器
binder.registerCustomEditor(Carmodel.class,new MyPropertyEditor());
// 注册框架内建的日期属性编辑器
// 前台传递参数时需要严格按照约定好的方式传参 否则会报错 :400
binder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"), true));
}
}
- 最大的缺点
·只能实现String转换Object,不能实现任意类型对象之间的转换
>使用转换器实现类型转换
- 实现自定义转换器
·实现Converter 接口,并指定源类型及目标类型 core包下面的
·实现convert(Object args) 方法,参数为源类型
/**
* 自定义转换器
* @author Administrator
*
*/
public class MyConverter implements Converter<String, TelPhone> {
/**
* 数据转换方法
* source : 源数据
*/
public TelPhone convert(String source) {
TelPhone telPhone = new TelPhone();
// 使用正则表达式限制传递进来的参数
String regex = "^(\\d{3,4})-(\\d{7,8}$)";
Pattern p = Pattern.compile(regex);
Matcher matcher = p.matcher(source);
if(matcher.matches()){
// 如果匹配正则表达式进行解析
String[] strArr = source.split("-");
String areaCode = strArr[0];
String phoneNum = strArr[1];
// 座机号码数据模型组装
telPhone.setAreaCode(areaCode);
telPhone.setPhoneName(Integer.parseInt(phoneNum));
}else{
// 不匹配正则表达式规则
System.out.println("用户输入的参数:"+source+"不符合正则表达式");
}
return telPhone;
}
}
- 注册转换器
·通过ConversionServiceFactoryBean 注册自定义转换器
·<mvc:annotation-driven conversion-service=”conversionService”>
<!-- 自定义转换器注册 -->
<mvc:annotation-driven conversion-service="conversionService"/>
<!-- 自定义转换器 -->
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<list>
<bean class="com.kgc.converters.MyConverter"></bean>
</list>
</property>
</bean>
- 特点
·ConversionService 会根据S 源类型/T目标类型自动适配
·支持任意类型数据之间进行转换
>使用格式化转换器进行数据格式化/解析(适合WEB层使用) 重点
- 自定义格式化转换器实现
·试下Formatter接口,并指定需要格式化的数据类型
·实现print() 方法:进行格式化显示
·实现parse() 方法:进行解析
/**
* 自定义格式化转换器
* 通过接口的泛型指定要得到的目标数据类型
* @author Administrator
*
*/
public class MyFormatter implements Formatter<MobileModel> {
// 进行格式化展示
public String print(MobileModel arg0, Locale arg1) {
return arg0.toString();
}
// 通过格式化解析
public MobileModel parse(String source, Locale local) throws ParseException {
MobileModel mobile = new MobileModel();
// 使用正则表达式规范输入的参数
String regex = "1[3|5|7|8][0-9]{9}";
Pattern p = Pattern.compile(regex);
Matcher matcher = p.matcher(source);
if(matcher.matches()){
// 通过本地化信息将数据格式化成不同的格式
if(local.equals(Locale.CHINA)){
//150-1234-5678
String headStr = source.substring(0,3);
String midStr = source.substring(3,7);
String lastStr =source.substring(7,11);
String cnNum = headStr+"-"+midStr+"-"+lastStr;
mobile.setMobileNum(cnNum);
}else if(local.equals(Locale.US)){
//1-5012-345678
String headStr = source.substring(0,1);
String midStr = source.substring(1,5);
String lastStr =source.substring(5,11);
String usNum = headStr+"-"+midStr+"-"+lastStr;
mobile.setMobileNum(usNum);
}
}else{
throw new IllegalArgumentException("输入的参数不是手机号码");
}
return mobile;
}
}
- 注册自定义格式化转换器
·通过FormattingConversionServiceFactoryBean 注册自定义转换器
<!-- 自定义转换器注册 -->
<mvc:annotation-driven conversion-service="formattingConversionServiceFactoryBean"/>
- 特点
·Formatter的源类型必须是一个String
·可以设置本地化信息Locale
》常用的内置格式化转换器
·CurrencyFormatter :货币格式化转换器
// 验证货币类型格式化转换器的测试方法
@Test
public void testFmt(){
CurrencyFormatter currencyFormatter = new CurrencyFormatter();
// currencyFormatter.print(123, Locale.CHINA);
System.out.println("这是中文货币:"+currencyFormatter.print(123, Locale.CHINA));
System.out.println("这是美国货币:"+currencyFormatter.print(123, Locale.US));
}
·DateFormatter : 时间格式化转换器
// 验证日期格式化转换器
@Test
public void testDateFmt(){
DateFormatter dateFormatter = new DateFormatter("yyyy-MM-dd HH-mm-SSS");
Calendar cal = Calendar.getInstance();
cal.set(2013, 11, 12);
String date = dateFormatter.print(cal.getTime(), Locale.CHINA);
System.out.println("格式化后得到的日期:"+date);
}
·PercentFormatter : 百分数格式化转换器
// 验证百分比格式化转化器
@Test
public void testPcFmt(){
PercentFormatter percentFormatter = new PercentFormatter();
String pfm = percentFormatter.print(0.1, Locale.CHINA);
System.out.println("这是格式化得到的百分比:"+pfm);
}
注意事项
·若属性编辑器和转换器同时存在,框架优先选择属性编辑器。
·Converter 是一般工具,可以将一种类型转换为另一种类型
·将String 转换为Date ,或将Long 转换成Date
·Converter 既可以用在web 层,也可以用在其它层中
·Formatter 只能将String 转换为另一种java 类型
·将String 转换为Date,但不能将Long转化为Date
·Formatter 适用于web层
·在Spring MVC应用程序中,选择Formatter比选择Converter更合适