Java字符串模板替换(模板渲染)
losetowin 发布于:2019-8-20 19:51 分类:Java 有 7195 人浏览,获得评论 0 条
除非注明,文章均为 www.dutycode.com 原创,欢迎转载!转载请注明本文地址,谢谢。
1 使用场景
短信模板字符串替换, 通用招呼语的替换。
比如,我们项目中,会给用户发送招呼语,招呼语中有些信息是根据用户不同动态拼装。当然最简单的办法是直接使用字符串拼接,直接拼接成一个可以直接发的信息。
字符串直接拼接的方式,在模板较少的情况下还是比较好处理的,但是当模板变多,每个人可自定义的时候,维护起来就会很麻烦,后期可扩展性也差。
“你好,李某某,邀请你投递 服务员 职位,月薪5000-6000。”
上面的例子中, 李某某、服务员、5000-6000 这三个都是根据接收人及职位信息不同而拼装的。
2 实现方式:
1)、String.format , MessageFormat
/**
* String.format渲染模板
* @param template 模版
* @param params 参数
* @return
*/
public static String processFormat(String template, Object... params) {
if (template == null || params == null)
return null;
return String.format(template, params);
}
/**
* MessageFormat渲染模板
* @param template 模版
* @param params 参数
* @return
*/
public static String processMessage(String template, Object... params) {
if (template == null || params == null)
return null;
return MessageFormat.format(template, params);
}
//使用:
public static void main(String[] args) {
Object[] obj = new Object[]{"张三", "服务员", "5000-6000"};
System.out.println(processFormat("您好%s,邀请你投递:%s职位,月薪:%s", obj));
System.out.println(processMessage("您好{0},邀请你投递:{1}职位,月薪:{2}", obj));
}
优势点:
这两种比较类似,都属于jdk内置,可以直接使用。
劣势点:
这两种需要明确知道占位符的位置,对使用方而言要求会比较高。
2)、使用freeMarker
/**
* Freemarker渲染模板
* @param template 模版
* @param params 参数
* @return
*/
public static String processFreemarker(String template, Map<String, Object> params) {
if (template == null || params == null)
return null;
try {
Configuration cfg = new Configuration();
StringTemplateLoader stl = new StringTemplateLoader();
stl.putTemplate("", template);
cfg.setTemplateLoader(stl);
Template tpl = cfg.getTemplate("");
StringWriter writer = new StringWriter();
tpl.process(params, writer);
return writer.toString();
} catch (Exception e) {
return null;
}
}
//使用:
public static void main(String[] args) {
Map map = new HashMap();
map.put("name", "张三");
map.put("job", "服务员");
map.put("salary", "5000-6000”);
processFreemarker("您好${name},邀请你投递:${job}职位,月薪:${salary}", map);
}
优点:
对使用方较简单,不需要关心变量位置,只需要进行替换即可。
缺点:
需要引入第三方类库。实测下,性能低于JDK原生方式。
3)、 使用velocity
/**
* 使用Velocity作为变量替换引擎,渲染模板
* @param template
* @param params
* @return
*/
public static String processVelocity(String template, Map<String,Object> params){
if (template == null || params == null)
return null;
Context context = new VelocityContext();
//拼装velocity用模板参数
Set<String> keys = params.keySet();
for (String k : keys){
context.put(k, params.get(k));
}
StringWriter sw = new StringWriter();
try {
Velocity.evaluate(context, sw, "velocity", template);
} catch (Exception e) {
e.printStackTrace();
}
return sw.toString();
}
//使用:
public static void main(String[] args) {
Map map = new HashMap();
map.put("name", "张三");
map.put("job", "服务员");
map.put("salary", "5000-6000”);
processVelocity("您好${name},邀请你投递:${job}职位,月薪:${salary}", map);
}
优点:
和freemarker类似, 对使用方较简单,不需要关心变量位置,只需要进行替换即可。
缺点:
需要引入第三方类库。实测下,性能低于JDK原生方式,优于freemarker。
4)、使用自定义方式(正则匹配)
/**
* 自定义渲染模板
* @param template 模版
* @param params 参数
* @return
*/
public static String processTemplate(String template, Map<String, Object> params) {
if (template == null || params == null)
return null;
StringBuffer sb = new StringBuffer();
Matcher m = Pattern.compile("\\$\\{\\w+\\}").matcher(template);
while (m.find()) {
String param = m.group();
Object value = params.get(param.substring(2, param.length() - 1));
m.appendReplacement(sb, value == null ? "" : value.toString());
}
m.appendTail(sb);
return sb.toString();
}
//使用:
public static void main(String[] args) {
Map map = new HashMap();
map.put("name", "张三");
map.put("job", "服务员");
map.put("salary", "5000-6000”);
processTemplate("您好${name},邀请你投递:${job}职位,月薪:${salary}", map);
}
优点:
对使用方较简单,不需要关心变量位置,只需要进行替换即可。
缺点:
实测下,性能低于JDK原生方式,优于velocity。
3 如果变量为空呢?
a) 当变量没有值传入的时候,freemaker会报错。比如 上面我们把map里面的salary去掉,再执行时会抛出异常。
此时,需要再模板上增加freemaker语法,做判空处理。如上,可以替换成:
processFreemarker("您好${name},邀请你投递:${job}职位,月薪:${salary!'默认'}", map)
再次执行,可以得到默认值:默认。
您好张三,邀请你投递:服务员职位,月薪:默认
b)、velocity不会报错,但会直接把${salary}输出出来,体验上不是很好。
在变量前加上! ,可以在值不存在的时候,输出为空。("!"用来强制把不存在的变量显示为空白。)
您好$!{name},邀请你投递:$!{job}职位,月薪:$!{salary}
salary为空的情况下, 输出结果为:
您好张三,邀请你投递:服务员职位,月薪:
也可以跟freemaker一样,为空的时候,设置为默认值,但是语法相对麻烦些
System.out.println(processVelocity("您好${name},邀请你投递:${job}职位,月薪:#if($salary) ${salary} #else 默认 #end", map));
4 性能比较:
5 备注:
如果对后续扩展上要求比较多的话, 建议使用freemarker和velocity。可以借助各自的语法完成扩展。
对性能有要求的话,可以使用自定义的方式,但扩展性相对较差,后续维护起来相对麻烦些(需要自定义语法支持扩展)。
参考:
https://www.cnblogs.com/softidea/p/9140204.html
版权所有:《攀爬蜗牛》 => 《Java字符串模板替换(模板渲染)》
本文地址:https://www.dutycode.com/post-168.html
除非注明,文章均为 《攀爬蜗牛》 原创,欢迎转载!转载请注明本文地址,谢谢。