目录
一、类型转换的三种方法
1、自定义转换器Convert,ConvertFactory
2、 @Controller类中添加@InitBinder方法-注册属性编辑器
3、 POJO字段添加注解:
二、自定义转换器Convert,ConvertFactory
1、 Convert,ConvertFactory两个功能接口
2、 实现WebMvcConfigurer接口,实现addFormatters方法:注册转换器。
3、Convert接口
4、ConverterFactory接口
三、@Controller类中添加@InitBinder方法-注册属性编辑器
1、介绍
2、PropertyEditor属性编辑器与WebDataBinder
3、 @InitBinder注解介绍
4、 @InitBinder注解解决Date类型转换
5、@InitBinder也可以用于参数绑定
如Date字段添加@DateTimeFormat(pattern = “yyyy-MM-dd”)
当确定是某一具体类型转换时,只需要实现Convert即可;
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Autowired
private BaseEnumConvertFactory enumConvertFactory;
@Autowired
private DateConvert myDateConvert;
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverter(myDateConvert);//String-Date转换器
registry.addConverterFactory(enumConvertFactory);//自定义工厂转换器
}
}
只有一个convert(S source)方法,实现该接口并实现convert方法即可;只能实现特定的两个类之间的转换。如String和Date之间的转换可以。
@FunctionalInterface
public interface Converter {
@Nullable
T convert(S source);
}
public class DateConverter implements Converter{
@Override
public Date convert(String source) {
if(source != null) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
sdf.setLenient(false);
try {
return sdf.parse(source); //将字符串解析成日期类型
} catch (ParseException e) {
e.printStackTrace();
}
}
return null;
}
public interface ConverterFactory {
Converter getConverter(Class targetType);
}
Convert与ConverterFactory差别:
T与R:T表示具体某一个类型;而R表示一个基类。
转换器工厂定义一个getConverter(Class
@Component
public class BaseEnumConvertFactory implements ConverterFactory {
@Override
public Converter getConverter(Class targetType) {
return new StringToIEum<>(targetType);
}
private static class StringToIEum implements Converter {
private Class targerType;
public StringToIEum(Class targerType) {
this.targerType = targerType;
}
@Override
public T convert(String source) {
if (StringUtils.isEmpty(source)) {
return null;
}
return (T) BaseEnumConvertFactory.getBaseEnum(this.targerType, source);
}
}
public static Object getBaseEnum(Class targerType, String source) {
T[] enumConstants = targerType.getEnumConstants();
for (T enumObj : enumConstants) {
if (source.equals(String.valueOf(enumObj.getCode()))) {
return enumObj;
}
}
return null;
}
}
@InitBinder 、WebDataBinder、PropertyEditor
概括:@InitBinder注解标注在@Controller类的方法上,该方法为当前控制器注册一个属性编辑器(CustomEditor),对整个@ontroller类及其子类有效。
SpringMVC可以使用@InitBinder注解和WebDataBinder解决类型转换问题。
使用地点:@InitBinder标注于@Controller类中的方法;
功能:@InitBinder标注的方法为当前控制器注册一个属性编辑器。
作用范围:@InitBinder方法对整个@Controller类及其子类有效。
通俗说:每一次请求,都会先执行@InitBinder方法,然后再执行对应的Handler方法。
PropertyEditor接口中定义了setAsText、setValue和getAsText、getValue方法,也就是属性编辑器的一些统一标准方法。Spring提供了大量的属性编辑器PropertyEditor,如CustomDateEditor、CustomBooleanEditor、CustomNumberEditor等,基本满足常用需求。
WebDataBinder类可以将前端请求参数绑定到对应类的属性编辑器PropertyEditor上,如果Java对应的该属性是个对象,就会找到该对象的属性编辑器进行转换,即调用setAsText方法转成对象后调用setValue方法。
因此,只需要将对应类的属性编辑器注册到WebDataBinder上即可。
例如:CustomDateEditor类中的setAsText方法:由String==>Date
获取的时候调用getAsText方法:由Date==>String
/**
* Format the Date as String, using the specified DateFormat.
*/
@Override
public String getAsText() {
Date value = (Date) getValue();
return (value != null ? this.dateFormat.format(value) : "");
}
由 @InitBinder 标识的方法,可以对 WebDataBinder 对象进行初始化。WebDataBinder 是 DataBinder 的子类,用于完成由表单字段到 JavaBean 属性的绑定。
WebDataBinder继承自DataBinder,而DataBinder又实现了PropertyEditorRegistry, TypeConverter接口。
因此WebDataBinder可以用于注册属性编辑器PropertyEditor,也可以类型转换,也可以设置不接收某些字段或设置前缀等等方法。
如:binder.setDisallowedFields("age");//不接收age参数
/**
* Parse the Date from the given text, using the specified DateFormat.
*/
@Override
public void setAsText(@Nullable String text) throws IllegalArgumentException {
if (this.allowEmpty && !StringUtils.hasText(text)) {
// Treat empty String as null value.
setValue(null);
}
else if (text != null && this.exactDateLength >= 0 && text.length() != this.exactDateLength) {
throw new IllegalArgumentException(
"Could not parse date: it is not exactly" + this.exactDateLength + "characters long");
}
else {
try {
setValue(this.dateFormat.parse(text));
}
catch (ParseException ex) {
throw new IllegalArgumentException("Could not parse date: " + ex.getMessage(), ex);
}
}
}
两种方法:
传统解决方法:在POJO类的属性上添加:@DateTimeFormat(pattern = “yyyy-MM-dd”)可以实现String转成Date类型。
新的解决办法:将Data类型的属性编辑器注册到WebDataBinder上即可;在Controller类中添加一个@InitBinder方法即可。
一般将@Controller方法写在BaseController类中,需要进行这类转换的控制器只需继承BaseController即可。
Spring已经提供了CustomDateEditor,只需要自定义日期格式创建CustomDateEditor对象,并注册到WebDataBinder上即可。
在使用SpringMVC的时候,经常会遇到日期时间字符串和Date类型的转换,而SpringMVC默认不支持这个格式的转换,所以需要手动配置,自定义数据的绑定才能解决这个问题。需要日期转换的@Controller可以使用SpringMVC的@InitBinder注解和Spring的WebDataBinder来实现。
WebDataBinder是用来绑定请求参数到指定的属性编辑器。
使用示例:
@InitBinder//注册Date属性编辑器
public void initBinder(WebDataBinder binder) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
CustomDateEditor customDateEditor = new CustomDateEditor(dateFormat, true);
binder.registerCustomEditor(Date.class, customDateEditor);
}
https://blog.csdn.net/zengxianxue/article/details/78567544