没有需求,谈什么技术呢?之前有做过微信模版消息推送,今天遇到一个需求,需求方要求内容可以根据传入的字段自由组合,但是并不是毫无规则的组合,而是根据调用方传入的Json数据填充一个业务方自定义的模版。那么其实这个需求并不难,因为借助模版引擎就可以实现。那么接下来我们就进一步探究一下。
在Java中其实也有很多模版引擎,比如:freemarker
、thymeleaf
、velocity
等,这里的选择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
还支持一些复杂的表达等,这里暂时用不上,就不继续探究了。因为业务是想尽量将控制放在我们这里,而不是调用方,所以才行想这样的方式来处理。