Spring boot

Springboot整合Dozer深度复制

2021-02-04  本文已影响0人  三也视界

Dozer

Dozer是一种Java Bean到Java Bean的映射器,递归地将数据从一个对象复制到另一个对象,它是一个强大的,通用的,灵活的,可重用的和可配置的开源映射框架。

常用于:

注意的场景:

建议:

SpringBoot整合Dozer

jar依赖引入

pom.xml加入以下依赖

<!--       深度复制: Dozer可以灵活的对对象进行转换,且使用简单-->
        <dependency>
            <groupId>net.sf.dozer</groupId>
            <artifactId>dozer-spring</artifactId>
            <version>5.5.1</version>
        </dependency>
        <dependency>
            <groupId>net.sf.dozer</groupId>
            <artifactId>dozer</artifactId>
            <version>5.5.1</version>
            <exclusions>
                <exclusion>
                    <artifactId>jcl-over-slf4j</artifactId>
                    <groupId>org.slf4j</groupId>
                </exclusion>
            </exclusions>
        </dependency>

dozer配置xml引入

resource文件夹下新建dozer文件夹, 并新建bean-mappings.xml, global-configuration.xml

bean-mappings.xml

<?xml version="1.0" encoding="UTF-8"?>
<mappings xmlns="http://dozer.sourceforge.net" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://dozer.sourceforge.net
          http://dozer.sourceforge.net/schema/beanmapping.xsd">
</mappings>

global-configuration.xml

<?xml version="1.0" encoding="UTF-8"?>
<mappings xmlns="http://dozer.sourceforge.net" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://dozer.sourceforge.net
          http://dozer.sourceforge.net/schema/beanmapping.xsd">
    <configuration>
        <date-format>yyyy-MM-dd HH:mm:ss</date-format>
        <wildcard>true</wildcard>
        <trim-strings>false</trim-strings>
        <!-- 自定义的枚举与Integer转换器, 下节介绍 -->
        <!--<custom-converters>
            <converter type="com.dongao.beacon.ds.rest.admin.tookit.EnumIntegerBiDirectionalDozerConverter">
                <class-a>java.lang.Enum</class-a>
                <class-b>java.lang.Integer</class-b>
            </converter>
        </custom-converters>-->
    </configuration>
</mappings>

自定义DozerConverter,实现CustomConverter并重写convert
枚举转换与Integer转换, 只是简单的把枚举index与Integer转换, 同理枚举转字符串只是转的name. 复杂枚举name, code, dispalyname的转换就不适用默认规则了, 这时需要自定义转换器.

public class EnumIntegerBiDirectionalDozerConverter implements CustomConverter {

    @Override
    public Object convert(Object destination, Object source, Class<?> destinationClass, Class<?> sourceClass) {
        if (EmptyUtils.isEmpty(source)) {
            return null;
        }
        if (source instanceof Enum) {
            return getInteger(destinationClass, source);
        } else if (source instanceof Integer) {
            return getEnum(destinationClass, source);
        } else {
            throw new MappingException(new StringBuilder("Converter ").append(this.getClass().getSimpleName())
                    .append(" was used incorrectly. Arguments were: ").append(destinationClass.getClass().getName())
                    .append(" and ").append(source).toString());
        }
    }

    private Object getInteger(Class<?> destinationClass, Object source) {
        try {
            Enum<?> em = (Enum<?>) source;
            Class<?> clazz = em.getDeclaringClass(); 
            Method getCode = clazz.getMethod("getCode"); 
            Object code = getCode.invoke(source);
            return Integer.valueOf((String) code);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    private Object getEnum(Class<?> destinationClass, Object source) {
        try {
            Method m = destinationClass.getDeclaredMethod("valueOfCode", String.class);
            Object enumeration = m.invoke(destinationClass.getClass(), String.valueOf(source));
            return enumeration;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

}

Dozer的JavaConfig

用于SpringBoot寻找DozerBeanMapperFactoryBean的配置
新建DozerMapperConfig.java

@Configuration
public class DozerMapperConfig {
    @Bean
    public DozerBeanMapperFactoryBean dozerBeanMapperFactoryBean(@Value("classpath*:dozer/*.xml" ) Resource[] resources) throws Exception {
        final DozerBeanMapperFactoryBean dozerBeanMapperFactoryBean = new DozerBeanMapperFactoryBean();
        dozerBeanMapperFactoryBean.setMappingFiles(resources);
        return dozerBeanMapperFactoryBean;
    }

 /*   @Bean
    public IGenerator ejbGenerator() {
        return new EJBGenerator();
    }*/
}

格式化工厂

建议新建包专门放置Dozer工具

接口定义: 新建IGenerator.java接口

public interface IGenerator {

    /**
     * 转换
     *
     * @param s   数据对象
     * @param clz 复制目标类型
     * @return {@link T}
     * @Description: 单个对象的深度复制及类型转换,vo/domain , po
     * @author banjuer@outlook.com
     * @Time 2018年5月9日 下午3:53:24
     */
    <T, S> T convert(S s, Class<T> clz);

    /**
     * @Description: 深度复制结果集(ResultSet为自定义的分页结果集)
     * @param s 数据对象
     * @param clz 复制目标类型
     * @return
     * @author banjuer@outlook.com
     * @Time 2018年5月9日 下午3:53:24
     */
    //<T, S> Result<T> convert(Result<S> s, Class<T> clz);

    /**
     * 转换
     * @param s   数据对象
     * @param clz 复制目标类型
     * @return {@link List<T>}
     * @Description: list深度复制
     * @author banjuer@outlook.com
     * @Time 2018年5月9日 下午3:54:08
     */
    <T, S> List<T> convert(List<S> s, Class<T> clz);

    /**
     *
     * @param s
     * @param clz
     * @param <T>
     * @param <S>
     * @return
     */
    <T, S> Paging<T> convertPaging(Paging<S> s, Class<T> clz);
    /**
     * @param s   数据对象
     * @param clz 复制目标类型
     * @return
     * @Description: set深度复制
     * @author banjuer@outlook.com
     * @Time 2018年5月9日 下午3:54:39
     */
    <T, S> Set<T> convert(Set<S> s, Class<T> clz);

    /**
     * @param s   数据对象
     * @param clz 复制目标类型
     * @return
     * @Description: 数组深度复制
     * @author banjuer@outlook.com
     * @Time 2018年5月9日 下午3:54:57
     */
    <T, S> T[] convert(S[] s, Class<T> clz);

    /**
     * 分页信息转换
     * @return {@link PageResult<T>}
     */
    <T, S> PageResult<T> convertPageInfo(PageInfo<S> s, Class<T> clz);
}

IGenerator实现

@Component
@Lazy(true)
public class EJBGenerator implements IGenerator {

    @Autowired
    protected Mapper dozerMapper;

    @Override
    public <T, S> T convert(final S s, Class<T> clz) {
        return s == null ? null : this.dozerMapper.map(s, clz);
    }

    @Override
    public <T, S> List<T> convert(List<S> s, Class<T> clz) {
        return s == null ? null : s.stream().map(vs -> this.dozerMapper.map(vs, clz)).collect(Collectors.toList());
    }

    @Override
    public <T, S> Paging<T> convertPaging(Paging<S> paging, Class<T> clz) {
        Paging<T> pagingVo=new  Paging<T>();
        pagingVo.setRecords(convert(paging.getRecords(),clz));
        pagingVo.setTotal(paging.getTotal());
        return pagingVo;
    }

    @Override
    public <T, S> Set<T> convert(Set<S> s, Class<T> clz) {
        return s == null ? null : s.stream().map(vs -> this.dozerMapper.map(vs, clz)).collect(Collectors.toSet());
    }

    @Override
    public <T, S> T[] convert(S[] s, Class<T> clz) {
        if (s == null) {
            return null;
        }
        @SuppressWarnings("unchecked")
        T[] arr = (T[]) Array.newInstance(clz, s.length);
        for (int i = 0; i < s.length; i++) {
            arr[i] = this.dozerMapper.map(s[i], clz);
        }
        return arr;
    }

    @Override
    public <T, S> PageResult<T> convertPageInfo(PageInfo<S> s, Class<T> clz) {
        return new PageResult(s.getTotal(), convert(s.getList(), clz));
    }
}

demo使用

使用Demo
一般在公共父类中引入, 此处例子为前端公共Controller引入

@Controller
public class BaseController  {

    @Autowired
    protected EJBGenerator ejbGenerator = new EJBGenerator();


}
// 个人信息变更记录session
SessionUserDetails userDetails = ejbGenerator.convert(userVo, SessionUserDetails.class);
上一篇下一篇

猜你喜欢

热点阅读