Java字符串模板替换(模板渲染)

losetowin 发布于:2019-8-20 19:51 分类:Java  有 300 人浏览,获得评论 0 条  

本文地址:http://www.dutycode.com/post-168.html
除非注明,文章均为 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
除非注明,文章均为 《攀爬蜗牛》 原创,欢迎转载!转载请注明本文地址,谢谢。