网站首页 > 精选教程 正文
环境:Springboot2.4.11
通常,当需要实现通用类型转换逻辑时,可以使用转换器SPI?例如,用于在java.util.Date和Long之间转换。当你在客户端环境(如web应用程序)中工作并且需要解析和打印本地化字段值时,可以使用格式化程序SPI。ConversionService为两个SPI提供统一的类型转换API。
在Springboot环境下如何自定义数据类型的转换?
Formatter SPI
Formatter SPI 实现字段格式化逻辑非常简单,而且是强类型的。以下列表显示格式化程序接口定义:
package org.springframework.format;
public interface Formatter<T> extends Printer<T>, Parser<T> {
}
Formatter 从Printer和Parser构建块接口扩展而来。以下列表显示了这两个接口的定义:
public interface Printer<T> {
String print(T fieldValue, Locale locale);
}
import java.text.ParseException;
public interface Parser<T> {
T parse(String clientValue, Locale locale) throws ParseException;
}
要创建自己的Formatter格式化程序,只需要实现上面的Formatter接口。将泛型T替换为需要格式化的对象类型?—?例如,java.util.Date。实现print()操作以打印T的实例以在客户端区域中显示。实现parse()操作,从客户端语言环境返回的格式化表示中解析T的实例。如果解析尝试失败,格式化程序应该抛出ParseException或IllegalArgumentException。注意确保格式化程序实现是线程安全的。
自定义Formatter程序
根据用户输入的信息,每个字段信息通过逗号分割,通过Formatter程序将其转换为Users对象。如输入:张三,30;将信息解析为Users对象姓名为张三,年龄为30
public class Users {
private String name ;
private Integer age ;
}
格式化程序
public class UsersFormatter implements Formatter<Users> {
@Override
public String print(Users object, Locale locale) {
if (Objects.isNull(object)) {
return "" ;
}
return "【name = " + object.getName() + ", age = " + object.getAge() + "】" ;
}
@Override
public 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 ;
}
}
格式化程序定义完后,需要注册到系统中让系统能够知道如何进行转换。
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addFormatter(new UsersFormatter()) ;
}
}
测试接口
@GetMapping("/save")
public Object save(Users users) {
return users ;
}
输出:
基于注解的Formatter
可以按字段类型或注解配置字段格式。要将注解绑定到格式化程序,需要实现AnnotationFormatterFactory。以下显示了AnnotationFormatterFactory接口的定义:
package org.springframework.format;
public interface AnnotationFormatterFactory<A extends Annotation> {
Set<Class<?>> getFieldTypes();
Printer<?> getPrinter(A annotation, Class<?> fieldType);
Parser<?> getParser(A annotation, Class<?> fieldType);
}
要创建实现,请执行以下操作:
- 参数化要与格式逻辑关联的字段annotationType?—?例如org.springframework.format.annoation.DateTimeFormat。
- 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;
}
@Override
public Printer<Integer> getPrinter(AgeFormat annotation, Class<?> fieldType) {
return new AgeFormatter() ;
}
@Override
public Parser<Integer> getParser(AgeFormat annotation, Class<?> fieldType) {
return new AgeFormatter() ;
}
private class AgeFormatter implements Formatter<Integer> {
@Override
public String print(Integer object, Locale locale) {
if (object == null) {
return "" ;
}
return object.toString() ;
}
@Override
public Integer parse(String text, Locale locale) throws ParseException {
if (text == null || text.trim().length() == 0) {
return -1 ;
}
return Integer.parseInt(text.substring(1)) ;
}
}
}
注册格式化程序
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addFormatterForFieldAnnotation(new AgeFormatAnnotationFormatterFactory()) ;
}
}
Users.age字段添加注解
public class Users {
private String name ;
@AgeFormat
private Integer age ;
}
测试接口
@GetMapping("/save2")
public Object save2(Users users) {
return users ;
}
注意这里的年龄前面加了一个‘s’字符。
注解添加到参数上
格式化程序
public final class UsersFormatAnnotationFormatterFactory
implements AnnotationFormatterFactory<UsersFormat> {
public Set<Class<?>> getFieldTypes() {
Set<Class<?>> types = new HashSet<Class<?>>() ;
types.add(Users.class) ;
return types;
}
@Override
public Printer<?> getPrinter(UsersFormat annotation, Class<?> fieldType) {
return new UsersFormatter();
}
@Override
public Parser<?> getParser(UsersFormat annotation, Class<?> fieldType) {
return new UsersFormatter() ;
}
}
接口
@GetMapping("/save3")
public Object save3(@UsersFormat Users users) {
return users ;
}
完毕!!!
给个关注+转发呗谢谢
公众号:Springboot实战案例锦集
猜你喜欢
- 2024-10-28 Java 8 中处理日期和时间示例 java 日期时间格式
- 2024-10-28 Java 实现日期的格式化,月份和天不足两位时补上0
- 2024-10-28 Java中日期格式化YYYY-DD的坑 java 日期格式化为yyyy-mm-dd mmss
- 2024-10-28 Java 的流程控制是什么样子的 java流程控制有哪些
- 2024-10-28 Java优雅的保留两位小数 java保留两位数字
- 2024-10-28 阿里面试官:聊聊如何格式化 Instant
- 2024-10-28 圆你的大厂梦!今日头条Java高频面试题真题:一/二/三面+常见问题
- 2024-10-28 “全栈2019”Java第十四章:二进制、八进制、十六进制
- 2024-10-28 Java,FreeMarker,模板引擎,通过案例代码,学懂模板引擎
- 2024-10-28 Java春招必知必会八股文210题,看完offer拿到手软
你 发表评论:
欢迎- 04-11Java面试“字符串三兄弟”String、StringBuilder、StringBuffer
- 04-11Java中你知道几种从字符串中找指定的字符的数量
- 04-11探秘Java面试中问的最多的String、StringBuffer、StringBuilder
- 04-11Python字符串详解与示例(python字符串的常见操作)
- 04-11java正则-取出指定字符串之间的内容
- 04-11String s1 = new String("abc");这句话创建了几个字符串对象?
- 04-11java判断字符串中是否包含某个字符
- 04-11关于java开发中正确的发牌逻辑编写规范
- 最近发表
-
- Java面试“字符串三兄弟”String、StringBuilder、StringBuffer
- Java中你知道几种从字符串中找指定的字符的数量
- 探秘Java面试中问的最多的String、StringBuffer、StringBuilder
- Python字符串详解与示例(python字符串的常见操作)
- java正则-取出指定字符串之间的内容
- String s1 = new String("abc");这句话创建了几个字符串对象?
- java判断字符串中是否包含某个字符
- 关于java开发中正确的发牌逻辑编写规范
- windows、linux如何后台运行jar(并且显示进程名)
- 腾讯大佬私人收藏,GitHub上最受欢迎的100个JAVA库,值得学习
- 标签列表
-
- nginx反向代理 (57)
- nginx日志 (56)
- nginx限制ip访问 (62)
- mac安装nginx (55)
- java和mysql (59)
- java中final (62)
- win10安装java (72)
- java启动参数 (64)
- java链表反转 (64)
- 字符串反转java (72)
- java逻辑运算符 (59)
- java 请求url (65)
- java信号量 (57)
- java定义枚举 (59)
- java字符串压缩 (56)
- java中的反射 (59)
- java 三维数组 (55)
- java插入排序 (68)
- java线程的状态 (62)
- java异步调用 (55)
- java中的异常处理 (62)
- java锁机制 (54)
- java静态内部类 (55)
- java怎么添加图片 (60)
- java 权限框架 (55)
本文暂时没有评论,来添加一个吧(●'◡'●)