环境:Springboot2.7.18
1. 简介
Spring core.convert包是一个通用类型转换系统。它提供了统一的ConversionService API和强类型Converter SPI,用于实现从一种类型到另一种类型的转换逻辑。关于Spring类型转换的强大功能,查看下面这篇文章:
但是当你需要格式化展示一些信息时,如本地化展示String,Converter并不提供这功能,而为了解决此类问题Spring从3.0开始引入了Formatter,当你需要解析和打印本地化字段值(个性化输出)时,使用Formatter将非常方便的实现数据的处理。
Formatter
Formatter 实现字段格式化逻辑非常简单,而且是强类型的。接口定义:
public interface Formatter<T> extends Printer<T>, Parser<T> {}
Formatter 从Printer和Parser构建块接口扩展而来。以下列表显示了这两个接口的定义:
// 从目标类型到字符串的转换public interface Printer<T> {String print(T fieldValue, Locale locale);}// Parser,从字符串到目标类型的解析public interface Parser<T> {T parse(String clientValue, Locale locale) throws ParseException;}
要创建自己的Formatter格式化程序,只需要实现上面的Formatter接口。将泛型T替换为需要格式化的对象类型 — 例如,java.util.Date。实现print()操作以打印T的实例以在客户端区域中显示。实现parse()操作,从字符串类型到目标类型T的转换。
2. 实战案例
2.1 自定义Formatter程序
根据用户输入的信息,每个字段信息通过逗号分割,通过Formatter程序将其转换为Users对象。如输入:张三,30;将信息解析为Users对象。
public class Users {private String name ;private Integer age ;// getters, setters}
自定义格式化类
public class UsersFormatter implements Formatter<Users> {@Overridepublic String print(Users object, Locale locale) {if (Objects.isNull(object)) {return "" ;}return "【name = " + object.getName() + ", age = " + object.getAge() + "】" ;}@Overridepublic Users parse(String text, Locale locale) throws ParseException {if (text == null || text.trim().length() == 0) {return null ;}Users user = new Users() ;// 下面做简单处理,不做校验String[] values = text.split(",") ;user.setName(values[0]) ;user.setAge(Integer.parseInt(values[1]));return user ;}}
接下来是需要将上面的处理程序注册到系统中。
@Configurationpublic class WebConfig implements WebMvcConfigurer {@Overridepublic void addFormatters(FormatterRegistry registry) {registry.addFormatter(new UsersFormatter()) ;}}
测试接口
@GetMapping("/save")public Object save(Users users) {return users ;}
输出结果
2.2 基于注解的Formatter
可以按字段类型或注解配置字段格式。要将注解绑定到格式化程序,需要实现
AnnotationFormatterFactory。接口的定义
public interface AnnotationFormatterFactory<A extends Annotation> {Set<Class<?>> getFieldTypes();Printer<?> getPrinter(A annotation, Class<?> fieldType);Parser<?> getParser(A annotation, Class<?> fieldType);}
getFieldTypes:返回可以使用注释的字段类型,那些类型的字段上可以添加自定义的注解。
getPrinter:返回Printer以打印带注释字段的值。
getParser:返回一个Parser来解析带注释字段的值。
自定义注解
自定义注解类,使用到该注解的字段都会被处理。
@Documented@Retention(RetentionPolicy.RUNTIME)@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE})public @interface AgeFormat {}
自定义注解处理程序
public final class AgeFormatAnnotationFormatterFactory implements AnnotationFormatterFactory<AgeFormat> {public Set<Class<?>> getFieldTypes() {Set<Class<?>> types = new HashSet<Class<?>>() ;types.add(Integer.class) ;return types;}public Printer<Integer> getPrinter(AgeFormat annotation, Class<?> fieldType) {return new AgeFormatter() ;}public Parser<Integer> getParser(AgeFormat annotation, Class<?> fieldType) {return new AgeFormatter() ;}private class AgeFormatter implements Formatter<Integer> {public String print(Integer object, Locale locale) {if (object == null) {return "" ;}return object.toString() ;}public Integer parse(String text, Locale locale) throws ParseException {if (text == null || text.trim().length() == 0) {return -1 ;}return Integer.parseInt(text.substring(1)) ;}}}
注册格式化程序
@Configurationpublic class WebConfig implements WebMvcConfigurer {@Overridepublic void addFormatters(FormatterRegistry registry) {registry.addFormatterForFieldAnnotation(new AgeFormatAnnotationFormatterFactory()) ;}}
字段添加注解
public class Users {private String name ;@AgeFormatprivate Integer age ;}
测试接口
@GetMapping("/save2")public Object save2(Users users) {return users ;}
注解添加到参数上
定义方式与上面基本一致
public final class UsersFormatAnnotationFormatterFactory implements AnnotationFormatterFactory<UsersFormat> {public Set<Class<?>> getFieldTypes() {Set<Class<?>> types = new HashSet<Class<?>>() ;types.add(Users.class) ;return types;}public Printer<?> getPrinter(UsersFormat annotation, Class<?> fieldType) {return new UsersFormatter();}public Parser<?> getParser(UsersFormat annotation, Class<?> fieldType) {return new UsersFormatter() ;}}
测试接口
@GetMapping("/save")public Object save(@UsersFormat Users users) {return users ;}

以上是本篇文章的全部内容,如对你有帮助帮忙点赞+转发+收藏。
推荐文章
玩转Redis!非常强大的Redisson分布式集合,少写60%代码
这才是Spring为什么不支持static字段注入的原因【源码分析】
Spring Boot 3太强:全新Controller接口定义方式




