Tamper
A Java Bean to Java Bean mapper that recursively copies data from one object to another
Install / Use
/learn @alibaba/TamperREADME
Introduction
tamper是一款处理bean/map进行属性复制映射的工具,支持递归,集合等深度映射.
Why need tamper
这里列觉了几种需要使用tamper的场景:
- model 和 DO的转化 (DO = Data Object , 数据库对象的设计是一种大宽表的设计,domain/model的设计,会有层次结构&具体)。 比如表设计存储会采用json存储动态数据,而在model中会是具体的属性
- model 和 VO的转化 (VO = View Object , 公司的产品detail页面,涉及了后端n多个domain/model的组合展示,这时候会进行包装成VO,包装一些页面组装逻辑)
- model 和 DTO的转化 (DTO = Data Transfer Object ,公司子系统比较多,系统之间会有比较多的rpc等remote调用)
- form -> bean的转化 (现在流行的几个MVC框架,都已经开始支持view层的参数注入,比如@Paramter(name="field")String , @Form("name=xx")Bean)。 提交的form表单数据,基本都是以map+list为主,就会涉及一个mapping
Why tamper
- 解决BeanUtils, BeanCopier?使用上的局限,只能针对同名属性的拷贝
- 相比于BeanUtils,性能提升是它的优势
- 相比于BeanCopier,类型之间的convertor是它的优势
- 支持插件方式的扩展,自身框架的设计也是基于插件扩展。
目前的插件支持:
- default value支持
- convetor转换
- script脚本支持 (EL表达式处理)
- bean creator(嵌套对象自动创建)
Maven repository
<pre name="wiki-code" class="java"><dependency> <groupId>com.alibaba.tamper</groupId> <artifactId>tamper</artifactId> <version>1.0.3</version> </dependency></pre>FAQ
1.How to import to eclipse by maven?
mvn eclipse:eclipse
2.How to build project by maven?
mvn clean package
3.How to run testcase by maven?
mvn test
<h2>Example1:</h2>
<h3>自定义映射规则,处理bean/map <-> bean/map</h3>
<h3>Step 1 (define mapping config)</h3>
<pre name="code" class="java">
bean-mappings xmlns="https://github.com/alibaba/tamper/schema/mapping" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://github.com/alibaba/tamper/schema/mapping https://raw.github.com/alibaba/tamper/master/src/main/resources/META-INF/mapping.xsd">
<!-- (bean-bean) mapping 测试 -->
<bean-mapping batch="true" srcClass="com.agapple.mapping.object.SrcMappingObject" targetClass="com.agapple.mapping.object.TargetMappingObject" reversable="true">
<field-mapping srcName="intValue" targetName="intValue" />
<field-mapping targetName="integerValue" script="src.intValue + src.integerValue" /> <!-- 测试script -->
<field-mapping srcName="start" targetName="start" />
<field-mapping srcName="name" targetName="targetName" /> <!-- 注意不同名 -->
<field-mapping srcName="mapping" targetName="mapping" mapping="true" />
</bean-mapping>
<bean-mapping batch="true" srcClass="com.agapple.mapping.object.NestedSrcMappingObject" targetClass="com.agapple.mapping.object.NestedTargetMappingObject" reversable="true">
<field-mapping srcName="name" targetName="name" defaultValue="ljh" /> <!-- 测试default value -->
<field-mapping srcName="bigDecimalValue" targetName="value" targetClass="string" defaultValue="10" /> <!-- 测试不同名+不同类型+default value -->
</bean-mapping>
</bean-mappings></pre>
<h3>Step 2 (do mapping) </h3>
<pre name="code" class="java">public BeanMapping srcMapping = BeanMapping.create(SrcMappingObject.class, TargetMappingObject.class);
public BeanMapping targetMapping = BeanMapping.create(TargetMappingObject.class , SrcMappingObject.class);
@Test
public void testBeanToBean_ok() {
SrcMappingObject srcRef = new SrcMappingObject();
srcRef.setIntegerValue(1);
srcRef.setIntValue(1);
srcRef.setName("ljh");
srcRef.setStart(true);
TargetMappingObject targetRef = new TargetMappingObject();// 测试一下mapping到一个Object对象
srcMapping.mapping(srcRef, targetRef);
SrcMappingObject newSrcRef = new SrcMappingObject();// 反过来再mapping一次
targetMapping.mapping(targetRef, newSrcRef);
}</pre>
<h2 style="font-size: 1.5em;">Example2: </h2>
<h3>类似于BeanUtils/BeanCopier,根据同名属性进行自动映射,不需要定义任何的mapping.xml</h3>
<pre name="code" class="java">public BeanCopy srcCopy = BeanCopy.create(SrcMappingObject.class, TargetMappingObject.class);
public BeanCopy targetCopy = BeanCopy.create(TargetMappingObject.class , SrcMappingObject.class);
@Test
public void testBeanToBean_ok() {
SrcMappingObject srcRef = new SrcMappingObject();
srcRef.setIntegerValue(1);
srcRef.setIntValue(1);
srcRef.setName("ljh");
srcRef.setStart(true);
TargetMappingObject targetRef = new TargetMappingObject();// 测试一下mapping到一个Object对象
srcCopy.copy(srcRef, targetRef);
SrcMappingObject newSrcRef = new SrcMappingObject();// 反过来再mapping一次
targetCopy.copy(targetRef, newSrcRef);
}</pre>
<h2 style="font-size: 1.5em;">Example3: </h2>
<h3>类似于BeanUtils,处理map<->bean</h3>
<pre name="code" class="java"><span style="white-space: normal;"> <span style="white-space: pre;">public BeanMap beanMap = BeanMap.create(SrcMappingObject.class);
</span></span>
@Test
public void testDescribe_Populate_ok() {
SrcMappingObject srcRef = new SrcMappingObject();
srcRef.setIntegerValue(1);
srcRef.setIntValue(1);
srcRef.setName("ljh");
srcRef.setStart(true);
Map map = beanMap.describe(srcRef);
SrcMappingObject newSrcRef = new SrcMappingObject();// 反过来再mapping一次
beanMap.populate(newSrcRef, map);
}</pre>
<h2>Example4:</h2>
<h3>Mapping API定义映射</h3>
<pre name="code" class="java">BeanMappingBuilder builder = new BeanMappingBuilder() {
protected void configure() {
mapping(HashMap.class, HashMap.class).batch(false).reversable(true).keys("src", "target");
fields(srcField("one"), targetField("oneOther")).convertor("convertor").defaultValue("ljh");
fields(srcField("two").clazz(String.class), targetField("twoOther")).script("1+2").convertor(
StringToCommon.class);
fields(srcField("three").clazz(ArrayList.class), targetField("threeOther").clazz(HashSet.class)).recursiveMapping(
true);
}
};</pre>
<p>通过builder可以比较方便的构造mapping config,最后需要生成mapping实例,还需要做一步: </p>
<pre class="prettyprint">BeanMapping mapping = new BeanMapping(builder);
mapping.mapping(src, dest);//使用</pre>
<p>or </p>
<pre class="prettyprint">BeanMappingConfigHelper.getInstance().register(builder); // 进行注册
BeanMappingObject object = BeanMappingConfigHelper.getInstance().getBeanMappingObject(srcClass,targetClass);
mapping.mapping(src, dest);//使用</pre>
问题反馈
- qq交流群: 161559791
- 邮件交流: jianghang115@gmail.com
- 新浪微博: agapple0002
- 报告issue:<a href="https://github.com/alibaba/tamper/issues">issues</a></p>
Related Skills
node-connect
345.4kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
104.6kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
345.4kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
qqbot-media
345.4kQQBot 富媒体收发能力。使用 <qqmedia> 标签,系统根据文件扩展名自动识别类型(图片/语音/视频/文件)。
