Spring Formatter<T> 对Spring MVC接受的参数格式化
在使用时,必须编写一个实现org.springframework.format.Formatter接口的java类。这个接口的声明如下
注意点就是:此Formatter的应用场景多在Spring MVC中接受String的值将其转化为相应的Java对象
public interface Formatter<T> extends Printer<T>, Parser<T> {
}
public interface Printer<T> {
String print(T var1, Locale var2);
}
public interface Parser<T> {
T parse(String var1, Locale var2) throws ParseException;
}
例子:
将DateFormatter作为Formatter的例子: (DateFormatter Spring自带支持,当然也可以自定义)
1.编写处理类
public class DateFormatter implements Formatter<Date> {
private String pattern;
public DateFormatter(String pattern) {
this.pattern = pattern;
}
@Override
public Date parse(String formatted, Locale locale) throws ParseException {
if (StringUtils.isEmpty(formatted)) {
return null;
}
return getDateFormatter(locale).parse(formatted);
}
@Override
public String print(Date object, Locale locale) {
return Objects.isNull(object) ? "" :
getDateFormatter(locale).format(object);
}
protected DateFormat getDateFormatter(Locale local) {
DateFormat dateFormat = new SimpleDateFormat(this.pattern, local);
dateFormat.setLenient(false);
return dateFormat;
}
}
2.将处理类注册到容器 容器会默认的奖器注册到解析器中
@Bean
public DateFormatter dateFormatterDate() {
return new DateFormatter("yyyy-MM/dd");
}
3.由于容器会默认的注册到解析器中,因而该步骤也可以不要 注册到解析器
@Bean
public FormatterRegistrar formatterRegistrarDate() {
return registry -> registry.addFormatter(dateFormatterDate());
}
FormatterRegistrar用于注册多个相关的转换器或格式化器(根据给定的格式化目录注册,例如Date格式化)在直接注册不能实现时FormatterRegistrar就派上用场了,例如,当格式化程序需要在不同于自身<T>的特定字段类型下进行索引时,或者在注册Printer/Parser对时。
4.测试:
编写测试类
@Data
public class MyModel {
private Date decimal;
}
/**
* 127.0.0.1:8886/get3?decimal=2017-01/01
*
* @return
*/
@GetMapping(value = "/get3")
public Object get(MyModel myModel) throws IOException {
System.out.println(myModel);
return myModel;
}
同时Spring也提供了基于注解的格式化
例如 :如果使用下列注解,默认默认的解析器就会加载
@DateTimeFormat(pattern="yyyy-MM/dd")
@NumberFormat(style = NumberFormat.Style.CURRENCY)
使用注解的例子:
1.编写测试类
@Data
public class MyModel {
@DateTimeFormat(pattern="yyyy-MM/dd")
private Date decimal;
}
/**
* 127.0.0.1:8886/get3?decimal=2017-01/01
*
* @return
*/
@GetMapping(value = "/get3")
public Object get(MyModel myModel) throws IOException {
System.out.println(myModel);
return myModel;
}
可以达到和上面同样的效果。
同时也可以自定义注解,需要实现AnnotationFormatterFactory<T> 例如下面的Spring中用于将String转化为Number的实现
public class NumberFormatAnnotationFormatterFactory implements
AnnotationFormatterFactory<NumberFormat> { //NumberFormat为注解类型
@Override
public Set<Class<?>> getFieldTypes() {
/**
* 返回支持的转换类型
*/
return new HashSet<Class<?>>(Arrays.asList(new Class<?>[]{Short.class, Integer.class, Long.class,
Float.class, Double.class, BigDecimal.class, BigInteger.class}));
}
@Override
public Printer<Number> getPrinter(NumberFormat annotation, Class<?> fieldType) {
return configureFormatterForm(annotation, fieldType);
}
@Override
public Parser<Number> getParser(NumberFormat annotation, Class<?> fieldType) {
return configureFormatterForm(annotation, fieldType);
}
private Formatter<Number> configureFormatterForm(NumberFormat annotation, Class<?> fieldType) {
if (!annotation.pattern().isEmpty()) {
return new NumberFormatter(annotation.pattern());
} else {
NumberFormat.Style style = annotation.style();
if (style == NumberFormat.Style.PERCENT) {
return new PercentFormatter();
} else if (style == NumberFormat.Style.CURRENCY) {
return new CurrencyFormatter();
} else {
return new NumberFormatter();
}
}
}
}
这是想要触发格式化,只需要在字段上添加上@NumberFormat注解即可,如下
@Data
public class MyModel {
@NumberFormat(style = NumberFormat.Style.CURRENCY)
private Date decimal;
}
配置全局的日期和时间格式
默认情况下,不带@DateTimeFormat注解的日期和时间字段适用DateFormat.SHORT(短日期)的格式转化字符串,开发者也可以使用自定义的全局格式覆盖默认的格式。
此时需要确保Spring不注册默认的格式化器。而应该手动注册所有的格式化器,如下
@Bean
public FormattingConversionService conversionService() {
DefaultFormattingConversionService conversionService = new DefaultFormattingConversionService(false);
//保证仍旧支持@NumberFormat
conversionService.addFormatterForFieldAnnotation(new NumberFormatAnnotationFormatterFactory());
//修改默认的时间格式
DateFormatterRegistrar registrar = new DateFormatterRegistrar();
registrar.setFormatter(new DateFormatter("yyyyMMdd"));
registrar.registerFormatters(conversionService);
return conversionService;
}
上一篇: 游记四首
下一篇: Java核心技术-集合-映射