Velocity是一个基于Java的模板引擎,与Freemarker类似。相较于Freemarker更轻量,但带来的问题就是功能不如Freemarker强大,所以实际项目中可能会更倾向于用Freemarker,这里不作过多介绍了,本文主要记录一下在使用中碰到的要对引号特殊字符进行转义的问题。
项目应用中使用了Velocity,但是其中的一个模板在执行时会报错,模板如下:
["${content}",${scene_id}]
当content的值中含有特殊字符时,由于本身是List格式,在将变量替换后,会因为变量中的特殊字符导致转换JSON报错。比如
String content = "etsl\"hesaid.\"iathisis";
执行后会报错:
Exception in thread "main" com.alibaba.fastjson.JSONException: syntax error, pos 8, json : ["etsl"hesaid."iathisis",59]
at com.alibaba.fastjson.parser.DefaultJSONParser.parse(DefaultJSONParser.java:1436)
at com.alibaba.fastjson.parser.DefaultJSONParser.parse(DefaultJSONParser.java:1322)
at com.alibaba.fastjson.parser.DefaultJSONParser.parseArray(DefaultJSONParser.java:1206)
at com.alibaba.fastjson.parser.DefaultJSONParser.parseArray(DefaultJSONParser.java:1111)
at com.alibaba.fastjson.JSON.parseArray(JSON.java:508)
由于Velocity功能不够强大,不能像Freemarker那样用自带的函数对特殊字符进行处理。
后来经过查找资料,了解到Velocity有拓展工具类(org.apache.velocity.tools.generic.EscapeTool),查看EscapeTool类的源码,可以发现该类中包含了很多工具方法,比如针对html,js等语言,也有对应的转义方法。当前问题可以使用其中的org.apache.velocity.tools.generic.EscapeTool#java方法来解决。
引入依赖:
org.apache.velocity.tools
velocity-tools-generic
3.1
将template修改为:
String template = "[\"$esc.java(${content})\",${scene_id}]";
并且在创建VelocityContext对象时,将工具类加载进去:
// 创建VelocityContext对象
VelocityContext context = new VelocityContext();
// 向VelocityContext中添加变量
context.put("content", content);
context.put("scene_id", 59);
// 添加自定义工具类
context.put("esc", new EscapeTool());
问题得到解决。
完整代码如下:
public static void main(String[] args) throws Exception {
String template = "[\"$esc.java(${content})\",${scene_id}]";
String content = "etsl\"hesaid.\"iathisis";
System.out.println(content);
// 初始化Velocity引擎
Velocity.init();
// 创建VelocityContext对象
VelocityContext context = new VelocityContext();
// 向VelocityContext中添加变量
context.put("content", content);
context.put("scene_id", 59);
// 添加自定义工具类
context.put("esc", new EscapeTool());
// 合并模板和VelocityContext
StringWriter writer = new StringWriter();
Velocity.evaluate(context, writer, "Velocity Example", template);
// 输出结果
String params = writer.toString();
System.out.println(params);
JSONArray jsonArray = JSONObject.parseArray(params);
System.out.println(jsonArray);
}