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

  • Post by eyiadmin
  • May 22, 2020
post-thumb

没有需求,谈什么技术呢?之前有做过微信模版消息推送,今天遇到一个需求,需求方要求内容可以根据传入的字段自由组合,但是并不是毫无规则的组合,而是根据调用方传入的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包:

<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}
假如我的请求参数是
{
                "orderNo": "5555555",
                "money": "8888888",
                "orderTime":"2020-09-03 15:46:56",
                "pay":"支付宝"
            }

这里我们就借助freemarker来解析我们的模版,

 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方法的逻辑在之前的文章中稍微作了一些调整

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;
    }

解析后的模版内容如下:

模版内容:[[{"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填充了简单的模版,其实它还可以完成更加复杂的对象,我们来举个栗子

 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" +
                "            }");
        

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

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

我只是记录我的学习过程,由于书读得少,可能很多地方表述或者是理解得不对,请轻喷并指正。

LATEST POST
  • Post By eyiadmin
  • Apr 18, 2021
.NET5快速接入支付宝扫码支付
  • Post By eyiadmin
  • Apr 18, 2021
uView练手开发-开发一个图片小程序
TAG
CATEGORIES