最近项目需要跟一家供应商对接系统,对方的接口支持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>
|
String xmlStr = FreeMarkUtils.getOrLoadFtl("/test.ftl");
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);
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);
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);
|

“扫一扫接着看”