比beanutil更加灵活的dto转换工具dozer
准确的说,是因为pojo无法一招走天下或者说内外部隔离的原因,所以有些时候,不得不在两个bean之间做copy或者转换映射。对于直接性的属性拷贝beanutil以及能够满足大部分要求,但是如果遇到字段不一致或者需要二次处理的情况下,就需要进行人工代码处理了。而且这些重复除非通过某种方式管理起来,不然系统中会有大量的复制粘贴。
周六的时候,一个同事说他们那边使用的dozer,还挺好用的,于是看了下官方手册http://dozer.sourceforge.net/dozer-user-guide.pdf,确实比较灵活,有点类似于mybatis之余jdbc原生代码。DEMO示例(实际使用中建议使用spring IOC方式,以及classpath加载,故非以教程式,而是直接可用的代码为例子)如下。
原bean:
package test; public class SourceObject { private String srcName; private int age; private String notMatch; public String getSrcName() { return srcName; } public void setSrcName(String srcName) { this.srcName = srcName; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getNotMatch() { return notMatch; } public void setNotMatch(String notMatch) { this.notMatch = notMatch; } }
目标bean:
package test; public class DestinationObject { private String destName; private int age; private String notExist; private String dictName; public String getDestName() { return destName; } public void setDestName(String destName) { this.destName = destName; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getNotExist() { return notExist; } public void setNotExist(String notExist) { this.notExist = notExist; } public String getDictName() { return dictName; } public void setDictName(String dictName) { this.dictName = dictName; } public void dictSet(String destName) { this.dictName = "dict " + destName; } }
转换映射文件:
<?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> <stop-on-errors>true</stop-on-errors> <date-format>MM/dd/yyyy HH:mm</date-format> <!-- 设置java.util.Date的默认格式, 用于 --> <wildcard>true</wildcard> </configuration> <mapping> <class-a>test.SourceObject</class-a> <class-b>test.DestinationObject</class-b> <field> <a>srcName</a> <b>destName</b> </field> <field> <a>srcName</a> <!-- 一个属性可以映射到多个目标 --> <b set-method="dictSet">dictName</b> <!-- 会将destName作为参数传递给dictSet方法 --> </field> </mapping> <!-- other custom class mappings would go here....... --> </mappings>
spring配置文件:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd" default-autowire="byName" default-lazy-init="false"> <bean id="mapper" class="org.dozer.spring.DozerBeanMapperFactoryBean"> <property name="mappingFiles"> <list> <value>classpath*:*DTOMapper.xml</value> </list> </property> </bean> </beans>
测试类:
package test; import org.dozer.DozerBeanMapper; import org.dozer.Mapper; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.transaction.TransactionConfiguration; import com.alibaba.fastjson.JSON; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = {"classpath:spring-dozer.xml"}) @TransactionConfiguration(defaultRollback = false) public class DozerBeanMapperTest { @Autowired Mapper mapperNotDefault; @Test public void testDozerBeanMapper(){ SourceObject sourceObject = new SourceObject(); sourceObject.setAge(1); sourceObject.setNotMatch("notmatch"); sourceObject.setSrcName("name1"); DestinationObject destObject; Mapper mapper = new DozerBeanMapper(); destObject = mapper.map(sourceObject, DestinationObject.class); System.out.println(JSON.toJSONString(sourceObject)); System.out.println(JSON.toJSONString(destObject)); destObject = mapperNotDefault.map(sourceObject, DestinationObject.class); System.out.println(JSON.toJSONString(sourceObject)); System.out.println(JSON.toJSONString(destObject)); } }
输出如下:
{"age":1,"notMatch":"notmatch","srcName":"name1"}
{"age":1}
{"age":1,"notMatch":"notmatch","srcName":"name1"}
{"age":1,"destName":"name1","dictName":"dict name1"}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
2016-06-25 公司mysql数据库设计与优化培训ppt