spring 自定义类型转换-ConverterRegistry

这篇具有很好参考价值的文章主要介绍了spring 自定义类型转换-ConverterRegistry。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1背景介绍

一个应用工程里面,一遍会涉及到很多的模型转换,如DTO模型转DO模型,DO模型转DTO, 或者Request转DTO模型,总的来说,维护起来还是相对比较复杂。每涉及一个转换都需要重新写对应类的get或者set方法,并且这些方法散落在不同的模块里面,非常不方便管理。 下面介绍 转换器设计模式来解决上面这个问题。

在这篇文章中,会介绍 Converter Design Pattern。由于Java8 功能不仅提供了相应类型之间的通用双向转换方式,而且还提供了转换相同类型对象集合的常用方法,从而将样板代码减少到绝对最小值。

2Converter接口


/**
 * A converter converts a source object of type {@code S} to a target of type {@code T}.
 *
 * <p>Implementations of this interface are thread-safe and can be shared.
 *
 * <p>Implementations may additionally implement {@link ConditionalConverter}.
 *
 * @author Keith Donald
 * @since 3.0
 * @param <S> the source type
 * @param <T> the target type
 */
public interface Converter<S, T> {

	/**
	 * Convert the source object of type {@code S} to target type {@code T}.
	 * @param source the source object to convert, which must be an instance of {@code S} (never {@code null})
	 * @return the converted object, which must be an instance of {@code T} (potentially {@code null})
	 * @throws IllegalArgumentException if the source cannot be converted to the desired target type
	 */
	T convert(S source);

}

该接口为函数式接口,因此可以用lamda方式实现转换。这种简单方式本篇不再介绍。可以参考这篇文章(https://wenku.baidu.com/view/d64211654731b90d6c85ec3a87c24028915f859c.html?wkts=1693142368160&bdQuery=Converter+java),本篇这样介绍设计模式相关内容。

3MyConverter接口

public interface MyConverter<S, T> extends Converter<S, T> {

    /**
     * 将DTO对象转换为领域对象
     * @param dtoData 原模型
     * @return  目标模型
     */
    T convert(S dtoData);

    /**
     * 转换领域模型列表
     * @param dtoDatas   原模型列表
     * @return 目标模型列表
     */
    List<T> convert(List<S> dtoDatas);
}

在使用上,一般先基于开始接口定位自己业务接口,这里满足了,单数据,或者列表数据。

4TemplateConverter

然后写自己模版类,后面的具体模型转换器基于这个模版实现

public abstract class TemplateConverter<S, T> implements MyConverter<S, T> {

    /** 实体sourceClass */
    protected final Class<S> sourceClass;

    /** targetClass */
    protected final Class<T> targetClass;

    /** 构造方法,约束泛型类型 */
    public TemplateConverter() {
        try {
            ParameterizedType parameterizedType = ((ParameterizedType) getClass()
                .getGenericSuperclass());
            sourceClass = (Class<S>) parameterizedType.getActualTypeArguments()[0];
            targetClass = (Class<T>) parameterizedType.getActualTypeArguments()[1];

        } catch (Exception e) {
            throw new RuntimeException("no  definition");
        }
    }

    /**
     * 源模型 转 目标模型
     * @param sourceModel 源模型
     * @return 目标模
     */
    public T convert(S sourceModel) {

        // 空请求默认返回空
        if (sourceModel == null) {
            return null;
        }

        T domainModel;
        try {
            domainModel = targetClass.newInstance();
            // 执行转换
            excuteConvert(sourceModel, domainModel);
        } catch (Exception e) {
            StringBuilder bf = new StringBuilder("conversion error,source:");
            bf.append(sourceClass.getSimpleName()).append(",target:")
                .append(targetClass.getSimpleName());
            throw new RuntimeException("convert  RuntimeException");
        }
        return domainModel;
    }

    /**
     * 源模型(List)转换为目标模型(List)
     *
     * @param sourceModels 源模型列表
     * @return 目标模型列表
     */
    public List<T> convert(List<S> sourceModels) {

        // 空请求,默认返回空
        if (CollectionUtils.isEmpty(sourceModels)) {
            return null;
        }

        List<T> result = new ArrayList<>();
        for (S dtoData : sourceModels) {
            T resData = convert(dtoData);
            if (resData != null) {
                result.add(resData);
            }
        }
        return result;
    }

    /**
     * 执行具体的模型转换
     * @param sourceModel 源模型
     * @param targetModel 目标模型
     */
    public abstract void excuteConvert(S sourceModel, T targetModel);

}

5 具体模型转换-StudentModeConverter

具体到模型转换器,这里还可以有很多个,这里以StudentModeConverter为例,只涉及到DTO模型转 DO模型

public class StudentModeConverter extends
                                                    TemplateConverter<StudentModeDTO, StudentModeDO> {

    @Override
    public void doConvert(StudentModeDTO sourceModel,
                          StudentModeDO targetModel) {

        targetModel.setName(sourceModel.getName());
      // 下面省略很多get/set
        targetModel.setAge(sourceModel.getAge());

    }
}

后面还可以写具体的转换器。基于之前模版。

6 通用转换服务-CommonConversionServiceImpl

public class CommonConversionServiceImpl extends GenericConversionService
                                              {

    /** constructor */
    public CommonConversionServiceImpl() {
        // 添加转换器
        addDefaultConverters(this);
    }

    /**
     * 添加转换器
     * @param converterRegistry
     */
    public void addDefaultConverters(ConverterRegistry converterRegistry) {

        // 添加通用集合转换器
        converterRegistry.addConverter(new StudentModeConverter1());
        converterRegistry.addConverter(new StudentModeConverter2());
        // ....
        converterRegistry.addConverter(new StudentModeConverter3());
    }

7 封装工具-CommonConvertUtil

public class CommonConvertUtil {

    /**
     * 通用转换服务
     */
    private static CommonConversionService conversionService = new CommonConversionServiceImpl();

    /**
     * 类型转换
     * @param source
     * @param targetType
     * @param <T>
     * @return
     */
    public static <T> T convert(Object source, Class<T> targetType) {
        return conversionService.convert(source, targetType);
    }

8 使用工具

使用场景:
studentModeDTO 转 StudentModeDO

StudentModeDTO studentModeDTO = new StudentModeDTO();
StudentModeDO studentModeDO= CommonConvertUtil.convert(studentModeDTO, StudentModeDO.class);

通过调用该封装好的工具即可。

以后只需要在 CommonConversionServiceImpl 加具体转换器即可使用在CommonConvertUtil 中使用 。

当时用于 CommonConversionServiceImpl 是需要默认初始化,所有可以声明为工厂bean文章来源地址https://www.toymoban.com/news/detail-677133.html


public class CommonConversionServiceFactoryBean implements FactoryBean<CommonConversionService>,
                                                InitializingBean {

    /** 转换器定义 */
    private Set<?>                  converters;

    /** 通用转换服务 */
    private CommonConversionService conversionService;

    /**
     * 注入转换器
     * @param converters
     */
    public void setConverters(Set<?> converters) {
        this.converters = converters;
    }

    @Override
    public CommonConversionService getObject() throws Exception {
        return this.conversionService;
    }

    @Override
    public Class<?> getObjectType() {
        return GenericConversionService.class;
    }

    @Override
    public boolean isSingleton() {
        return false;
    }

    /**
     * 创建转换服务
     * @return
     */
    protected CommonConversionService createConversionService() {
        return new CommonConversionServiceImpl();
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        this.conversionService = createConversionService();
        ConversionServiceFactory.registerConverters(this.converters, this.conversionService);
    }
}

到了这里,关于spring 自定义类型转换-ConverterRegistry的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Mybatis Plus自定义枚举类型转换

    这里实际使用的是mybatis plus的枚举工具,只不过拷贝出来修改为自己的枚举接口以及想用什么值进行转换;我这里使用的是通过数据库里面保存的数字类型进行转换,然后通过自动装配替换原生的枚举类型,原来的类型 MybatisEnumTypeHandler 通过自动装配替换原来的枚举类型处理

    2024年02月06日
    浏览(23)
  • 二、GoLang输出HelloWorld、基本数据类型、变量常量定义、基本类型转换

    go语言中,想要输出内容到控制台,package必须是main,包括方法名也必须是main, go语言输出的语法是 fmt 库。 Go语言的基本类型有: boolean:布尔类型 true / false string :字符串类型 数值型: int8:有符号8位整型(-128到127)长度 int16:有符号16位整型(-32768到32767)长度 int32:有

    2024年02月09日
    浏览(47)
  • SpringBoot复习:(59)自定义类型转换器

    一、自定义类型转换器: 二、将自定义类型转换器注册到Spring boot 三、请求测试:

    2024年02月10日
    浏览(36)
  • Python 变量的定义和数据类型的转换

    变量的定义 基本语法: 变量名 = 值 变量名是给对象贴一个用于访问的标签,给对象绑定名字的过程也称为赋值,赋值符号 “=” 变量名自定义,要满足标识符命名规则。 Python中, 不需要事先声明变量名及其类型 ,直接赋值即可创建各种类型的对象变量。 变量在第一次赋值

    2024年02月07日
    浏览(49)
  • 二、GoLang输出HelloWorld、变量定义、数据类型的转换

    go语言中,想要输出内容到控制台,package必须是main,包括方法名也必须是main, go语言输出的语法是 fmt 库。 Go语言的基本类型有: boolean:布尔类型 true / false string :字符串类型 数值型: int8:有符号8位整型(-128到127)长度 int16:有符号16位整型(-32768到32767)长度 int32:有

    2024年02月10日
    浏览(35)
  • Spring 类型转换、数值绑定与验证(一)— DataBinder

     DataBinder 是Spring用于数据绑定、类型转换及验证的类。使用场景有:1)xml配置文件定义bean,Spring 内部使用DataBinder 来完成属性的绑定;2)Web请求参数绑定,在Spring MVC 中,Controller的方法参数通常会自动绑定到请求参数中,主要用DataBinder来完成。3)自定义数据绑定,可手动创

    2024年02月22日
    浏览(32)
  • 最新最全面的Spring详解(三)——Resources,验证、数据绑定和类型转换与Spring表达式语言(SpEL)

    本文为 【Spring】Resources与Spring表达式语言(SpEL) 等相关知识,下边将对 Resources (包含: Resource接口 、 内置的 Resource的实现 、 ResourceLoader接口 、 应用环境和资源路径 ), 验证、数据绑定和类型转换 (包含: BeanWrapper 、 PropertyEditor属性编辑器 、 类型转换 、 配置 DataB

    2023年04月26日
    浏览(36)
  • 【mybatis-plus实体类复杂对象字段json自动相互转换,以及自定义字段类型解析器】

    引言: mybatis-plus集合对象字段json如何自动进行相互的转换? 怎样在使用mybatis-plus操作数据表的时候自动对实体类属性进行自动解析? 我们平时在做开发的时候,会遇到一个字段保存json串的情况。一般情况下mybatis-plus在做插入/更新之前将对象手动转换成json串,查询要用的时

    2023年04月13日
    浏览(89)
  • Spring boot之WEB 开发-静态资源访问--自定义转换器--处理JSON--内容协商

    在线文档: https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.developing-web-applications 1. 只要静态资源放在类路径下: /static 、/public 、/resources 、/META-INF/resources可以被直接访问- 对应文件WebProperties.java 2. 常见静态资源:JS、CSS 、图片(.jpg .png .gif .bmp .svg)、字体

    2024年02月09日
    浏览(47)
  • Python类型转换,数据类型转换函数大全 与 strip()函数介绍

    虽然 Python 是弱类型编程语言,不需要像 Java 或 C 语言那样还要在使用变量前声明变量的类型,但在一些特定场景中,仍然需要用到类型转换。 比如说,我们想通过使用 print() 函数输出信息“您的身高:”以及浮点类型 height 的值,如果在交互式解释器中执行如下代码: 会发

    2024年01月24日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包