使用Freemarker生成XML报文
最近项目需要跟一家供应商对接系统,对方的接口支持Webservice协议和HTTP协议,总之都是使用XML传输报文。现在API接口一般使用Json比较多,使用XML的还是比较少见的。好多年没搞XML序列化和反序列相关代码了,jdom、dom4j、xpath等等好多年没用过了,贸然用起来还有点不放心,干脆搞些不一样的!
FreeMarker
FreeMaker一般是作为前端模版引擎来使用的,使用FTL指令,可以在页面上生成动态内容。利用这个特性,我们也可以使用它完成填充XML中的占位符参数,实现动态生成XML报文,简单说就是模版+数据=动态结果。下面上代码:
- 添加FreeMarker依赖,我们使用最新的版本
2.3.30
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.30</version>
</dependency>
- 在项目
resources
下创建一个ftl文件(test.ftl),内容如下。其中${}
是参数占位符
<Request service="TEST_SERVICE" lang="zh-CN">
<Boms>
<Bom>
<SkuNo>${mainSku}</SkuNo>
<Items>
<#list subList as sku >
<Item>
<Sequence>${sku.sequence}</Sequence>
<SkuNo>${sku.barcode}</SkuNo>
<Quantity>${sku.quantity}</Quantity>
</Item>
</#list>
</Items>
</Bom>
</Boms>
</Request>
- 读取xml文件内容,并动态填充占位符
//读取xml文件为字符串(工具类就是普通的java文件读取操作)
String xmlStr = FreeMarkUtils.getOrLoadFtl("/test.ftl");
//创建2个对象
SFBomSubSku subSku1 = SFBomSubSku.builder()
.barcode("10000010")
.quantity("1")
.sequence("1")
.build();
SFBomSubSku subSku2 = SFBomSubSku.builder()
.barcode("10000011")
.quantity("3")
.sequence("2")
.build();
List<SFBomSubSku> list = Lists.newArrayList(subSku1, subSku2);
//设置参数值
Map<String, Object> args = new HashMap<>();
args.put("mainSku", "111111");
args.put("subList", list);
//配置FreeMarker
Configuration cfg = new Configuration(Configuration.VERSION_2_3_30);
cfg.setDefaultEncoding("UTF-8");
cfg.setNumberFormat("computer");
//动态填充参数
Template template = new Template("", source, cfg);
StringWriter out = new StringWriter();
template.process(dataModel, out);
//获取填充后的xml字符串,完成
String data = out.toString();
System.out.println(data)
- 运行上面的代码,打印出以下内容,可以看到xml中的占位符被参数正确替换掉了。
<Request service="TEST_SERVICE" lang="zh-CN">
<Boms>
<Bom>
<SkuNo>111111</SkuNo>
<Items>
<Item>
<Sequence>1</Sequence>
<SkuNo>10000010</SkuNo>
<Quantity>1</Quantity>
</Item>
<Item>
<Sequence>2</Sequence>
<SkuNo>10000011</SkuNo>
<Quantity>3</Quantity>
</Item>
</Items>
</Bom>
</Boms>
</Request>
使用
通过上面的介绍可以看到,使用FreeMarker动态替换XML中的参数占位符,可以省去手工拼XML或使用对象序列化带来的麻烦,只需要在项目中创建一个ftl文件,通过工具类快递完成XML报文的生成,然后通过HttpClient发送请求即可
ResponseEntity<String> responseEntity = restTemplate.postForEntity(url, data, String.class);