Dozer
Dozer是一种Java Bean到Java Bean的映射器,递归地将数据从一个对象复制到另一个对象,它是一个强大的,通用的,灵活的,可重用的和可配置的开源映射框架。
常用于:
- 代码层与层之间javabean转换, 如dao层PO转前端VO
- 分布式中, DAO层PO转DTO, DO 以及web层DTO转VO
注意的场景:
- 由于bean之间的深度复制, 在进行一些类似更新, 插入操作时尤其要注意最终接收到PO的一些关键字段如ID是否是真正需要的. 场景: 传入的DTO A为查出的DTO B复制后的, 这时候A里会有B的ID, 在插入A的时候很有可能造成主键冲突.
建议:
- 不用Dozer最好, Dozer带来的是性能开销.(这是不可能…)
- 某些特殊操作可以用切面控制特殊字段进行置空操作
pom.xml加入以下依赖
<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> </dependency>
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.web.admin.tookit.EnumIntegerBiDirectionalDozerConverter"> <class-a>java.lang.Enum</class-a> <class-b>java.lang.Integer</class-b> </converter> </custom-converters> </configuration> </mappings>
用于SpringBoot寻找DozerBeanMapperFactoryBean的配置
新建DozerMapperConfig.java
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; } }
建议新建包专门放置Dozer工具
- 接口定义: 新建
IGenerator.java
接口
public interface IGenerator { /** * @Description: 单个对象的深度复制及类型转换,vo/domain , po * @param s 数据对象 * @param clz 复制目标类型 * @return * @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> ResultSet <T> convert(ResultSet <S> s, Class<T> clz); /** * @Description: list深度复制 * @param s 数据对象 * @param clz 复制目标类型 * @return * @author banjuer@outlook.com * @Time 2018年5月9日 下午3:54:08 */ <T, S> List<T> convert(List<S> s, Class<T> clz); /** * @Description: set深度复制 * @param s 数据对象 * @param clz 复制目标类型 * @return * @author banjuer@outlook.com * @Time 2018年5月9日 下午3:54:39 */ <T, S> Set<T> convert(Set<S> s, Class<T> clz); /** * @Description: 数组深度复制 * @param s 数据对象 * @param clz 复制目标类型 * @return * @author banjuer@outlook.com * @Time 2018年5月9日 下午3:54:57 */ <T, S> T[] convert(S[] s, Class<T> clz); }
IGenerator
实现
@Component @Lazy(true) public class EJBGenerator implements IGenerator { @Autowired protected Mapper dozerMapper; public <T, S> T convert(S s, Class<T> clz) { if (s == null) { return null; } return this.dozerMapper.map(s, clz); } public <T, S> ResultSet <T> convert(ResultSet <S> s, Class<T> clz) { if (s == null) { return null; } ResultSet <T> resultSet = newResultSet <T>(); for (S vs : s.getResult()) { resultSet .getResult().add( this.dozerMapper.map(vs, clz)); } resultSet .setTotal(s.getTotal()); resultSet .setExt(s.getExt()); resultSet .setModifyTime(s.getModifyTime()); returnresultSet ; } public <T, S> List<T> convert(List<S> s, Class<T> clz) { if (s == null) { return null; } List<T> list = new ArrayList<T>(); for (S vs : s) { list.add(this.dozerMapper.map(vs, clz)); } return list; } public <T, S> Set<T> convert(Set<S> s, Class<T> clz) { if (s == null) { return null; } Set<T> set = new HashSet<T>(); for (S vs : s) { set.add(this.dozerMapper.map(vs, clz)); } return set; } 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; } }
一般在公共父类中引入, 此处例子为前端公共Controller引入
@Controller public class BaseController { @Autowired protected EJBGenerator ejbGenerator = new EJBGenerator(); protected final Logger logger = LoggerFactory.getLogger(getClass()); }
// 个人信息变更记录session SessionUserDetails userDetails = ejbGenerator.convert(userVo, SessionUserDetails.class);
文章来源: Springboot整合Dozer深度复制