Spring Boot使用freemarker解析、替换文本内容

没有需求,谈什么技术呢?之前有做过微信模版消息推送,今天遇到一个需求,需求方要求内容可以根据传入的字段自由组合,但是并不是毫无规则的组合,而是根据调用方传入的Json数据填充一个业务方自定义的模版。那么其实这个需求并不难,因为借助模版引擎就可以实现。那么接下来我们就进一步探究一下。

在Java中其实也有很多模版引擎,比如:freemarkerthymeleafvelocity等,这里的选择freemarker作为我们这次的主角,

那么,在开始之前,先简单的了解它的几个基语法:

  • 取值:占位符方式${name},对象方式${obj.name}
  • 判断:<#if vo.CUSTCODE ?exists ></#if>
  • 比较:<#if vo.CUSTCODE ?exists || vo.PHONE ?length gt 0></#if>
  • 运算符:${num+num1},${num-num1}

在开始之前,我们需要先引入jar包:

1
2
3
4
5
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.30</version>
</dependency>

好了,继续我们今天的主题。来,先举个例子,下面是我的微信模版配置

模版key 替换内容
first 该订单信息${orderNo},共支付${money}
keyword1 ${orderNo}
keyword2 ${orderTime}
keyword3 ${money}
keyword4 ${pay}
remark 说明${orderNo},通过${pay}支付了${money}
假如我的请求参数是
1
2
3
4
5
6
{
"orderNo": "5555555",
"money": "8888888",
"orderTime":"2020-09-03 15:46:56",
"pay":"支付宝"
}
这里我们就借助freemarker来解析我们的模版,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
Map<String, String> template = new HashMap<String,String>() {{
put("first", "该订单信息${orderNo},共支付${money} ");
put("keyword1", "${orderNo}");
put("keyword2", "${orderTime}");
put("keyword3", "${money}");
put("keyword4", "${pay}");
put("remark", "说明${orderNo},通过${pay}支付了${money} ");
}};
List<WxMpTemplateData> wxMpTemplateData = new ArrayList<>(template.size());
JSONObject jsonObject= JSON.parseObject("{\n" +
" \"orderNo\": \"5555555\",\n" +
" \"money\": \"8888888\",\n" +
" \"orderTime\":\"2020-09-03 15:46:56\",\n" +
" \"pay\":\"支付宝\"\n" +
" }");
template.forEach((key, value) -> {
try {
Template tpl = new Template(null, value, null);
Writer out = new StringWriter(2048);
tpl.process(jsonObject,out);
wxMpTemplateData.add(new WxMpTemplateData(key,out.toString()));
} catch (IOException | TemplateException e) {
e.printStackTrace();
}

});
TemplateParameterDto parameterDto=new TemplateParameterDto();
parameterDto.setAppId("wxb677b1efd92ade95");
parameterDto.setOpenId("oEd4cw2JNl-l_d7_RKnPzKyI-M7U");
parameterDto.setTemplateId("suUhCCo9owmD8QYbdcSgmG3uXwPsDE1Wn8eKThztS7U");
parameterDto.setUrl("https://www.baidu.com");
parameterDto.setTemplateDataList(wxMpTemplateData);
log.info("模版内容:[{}]",JSON.toJSONString(wxMpTemplateData));
pushService.sendWxTemplateMsg(parameterDto);
sendWxTemplateMsg方法的逻辑在之前的文章中稍微作了一些调整
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public String sendWxTemplateMsg(TemplateParameterDto parameterDto) {
// 发送模板消息接口
WxMpTemplateMessage templateMessage = WxMpTemplateMessage.builder()
// 接收者openid
.toUser(parameterDto.getOpenId())
// 模板id
.templateId(parameterDto.getTemplateId())
// 模板跳转链接
.url(parameterDto.getUrl())
.build();
// 添加模板数据
templateMessage.setData(parameterDto.getTemplateDataList());
String msgId = null;
try {
//根据appId切换公众号
wxMpService.switchover(parameterDto.getAppId());
// 发送模板消息
msgId = wxMpService.getTemplateMsgService().sendTemplateMsg(templateMessage);
} catch (WxErrorException e) {
e.printStackTrace();
}
return msgId;
}

解析后的模版内容如下:

1
模版内容:[[{"name":"keyword3","value":"8888888"},{"name":"keyword4","value":"支付宝"},{"name":"keyword1","value":"5555555"},{"name":"keyword2","value":"2020-09-03 15:46:56"},{"name":"remark","value":"说明5555555,通过支付宝支付了8888888 "},{"name":"first","value":"该订单信息5555555,共支付8888888 "}]]


刚才用freemarker填充了简单的模版,其实它还可以完成更加复杂的对象,我们来举个栗子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Map<String, String> template = new HashMap<String,String>() {{
put("first", "${ext.greet},${ext.name}");
put("keyword1", "${orderNo}");
put("keyword2", "${orderTime}");
put("keyword3", "${money}");
put("keyword4", "${pay}");
put("remark", "说明${orderNo},通过${pay}支付了${money},${ext.memo} ");
}};
List<WxMpTemplateData> wxMpTemplateData = new ArrayList<>(template.size());
JSONObject jsonObject= JSON.parseObject("{\n" +
" \"orderNo\": \"5555555\",\n" +
" \"money\": \"8888888\",\n" +
" \"orderTime\": \"2020-09-03 15:46:56\",\n" +
" \"pay\": \"支付宝\",\n" +
" \"ext\": {\n" +
" \"greet\": \"你好\",\n" +
" \"name\": \"靓大叔\",\n" +
" \"memo\": \"大兄弟,感谢你的支持\"\n" +
" }\n" +
" }");

最后解析出来的结果是这样子的

1
[[{"name":"keyword3","value":"8888888"},{"name":"keyword4","value":"支付宝"},{"name":"keyword1","value":"5555555"},{"name":"keyword2","value":"2020-09-03 15:46:56"},{"name":"remark","value":"说明5555555,通过支付宝支付了8888888,大兄弟,感谢你的支持 "},{"name":"first","value":"你好,靓大叔"}]]

freemarker还支持一些复杂的表达等,这里暂时用不上,就不继续探究了。因为业务是想尽量将控制放在我们这里,而不是调用方,所以才行想这样的方式来处理。

You forgot to set the qrcode for Alipay. Please set it in _config.yml.
You forgot to set the qrcode for Wechat. Please set it in _config.yml.
You forgot to set the business and currency_code for Paypal. Please set it in _config.yml.
You forgot to set the url Patreon. Please set it in _config.yml.
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×