java解析{{}}变量名以及文本内容替换操作

发短信、发邮件的时候经常会遇到模板内容需要替换成实际数据的问题,本文介绍从文本模板中解析出变量列表,以及参数填入后得到实际文本内容的办法:

/**
 * 根据正则表达式获取文本中的变量名列表
 * @param pattern
 * @param content
 * @return
 */
public static List<String> getParams(String pattern, String content) {
 Pattern p = Pattern.compile(pattern);
 Matcher m = p.matcher(content);

 List<String> result = new ArrayList<String>();
 while (m.find()) {
  result.add(m.group(1));
 }
 return result;
}

/**
 * 根据正则表达式将文本中的变量使用实际的数据替换成无变量的文本
 * @param pattern
 * @param content
 * @param data
 * @return
 */
public static String parse(String pattern, String content, Map<String, String> data) {
 Pattern p = Pattern.compile(pattern);
 Matcher m = p.matcher(content);

 StringBuffer sb = new StringBuffer();
 while (m.find()) {
  String key = m.group(1);
  String value = data.get(key);
  m.appendReplacement(sb, value == null ? "" : value);
 }
 m.appendTail(sb);
 return sb.toString();
}

public static void main(String[] args) {
 String content = "恭喜{{姓名}}报名成功,请凭报名编号{[code]}到现场参加活动";
 String reg = "\\{\\{(.+?)\\}\\}";
 List<String> params = getParams(reg, content);
 System.out.println(params);

 Map<String, String> data = new HashMap<String, String>();
 data.put("姓名", "张三丰");
 data.put("code", "930118");
 String text = parse(reg, content, data);
 System.out.println(text);
}

上面的代码介绍的是针对{{}}形式的变量值的解析办法,大家可以修改一下正则表达式,改成可以解析${}变量的办法

补充知识:java模板字符串优雅解析(占位符解析)

项目中常常需要解析字符串模板,比如user:{userId}:{userType}用于redis的key等,比较常见的做法就是使用String.format(“user:%s:%s”, 1, 1)方法,但个人感觉那样的模板不够明了,而使用模板解析器可更好地有助于解析此类字符串。

可使用map用于解析,也可使用对象进行解析,也可使用类似String.format可变参数进行解析,多样化解析对象值。有点类似于js的模板字符串${}。

也可自定义前缀后缀进行解析。如PlaceholderResolver.getResolver("{", “}”)该对象可解析{}该类型的占位符.

性能方面:

PlaceholderResolve解析结果

String.format解析结果

解析100w次,占位符解析比String.format平均都会快个0.4~0.5s,so 性能应该问题不大。最主要的是不需要调用太多的对象方法,自动解析,方便快捷。

源代码如下:

/**
 * 占位符解析器
 *
 * @author meilin.huang
 * @version 1.0
 * @date 2018-11-13 1:42 PM
 */
public class PlaceholderResolver {
 /**
  * 默认前缀占位符
  */
 public static final String DEFAULT_PLACEHOLDER_PREFIX = "${";

 /**
  * 默认后缀占位符
  */
 public static final String DEFAULT_PLACEHOLDER_SUFFIX = "}";

 /**
  * 默认单例解析器
  */
 private static PlaceholderResolver defaultResolver = new PlaceholderResolver();

 /**
  * 占位符前缀
  */
 private String placeholderPrefix = DEFAULT_PLACEHOLDER_PREFIX;

 /**
  * 占位符后缀
  */
 private String placeholderSuffix = DEFAULT_PLACEHOLDER_SUFFIX;

 private PlaceholderResolver(){}

 private PlaceholderResolver(String placeholderPrefix, String placeholderSuffix) {
  this.placeholderPrefix = placeholderPrefix;
  this.placeholderSuffix = placeholderSuffix;
 }

 /**
  * 获取默认的占位符解析器,即占位符前缀为"${", 后缀为"}"
  * @return
  */
 public static PlaceholderResolver getDefaultResolver() {
  return defaultResolver;
 }

 public static PlaceholderResolver getResolver(String placeholderPrefix, String placeholderSuffix) {
  return new PlaceholderResolver(placeholderPrefix, placeholderSuffix);
 }

 /**
  * 解析带有指定占位符的模板字符串,默认占位符为前缀:${ 后缀:}<br/><br/>
  * 如:template = category:${}:product:${}<br/>
  * values = {"1", "2"}<br/>
  * 返回 category:1:product:2<br/>
  *
  * @param content 要解析的带有占位符的模板字符串
  * @param values 按照模板占位符索引位置设置对应的值
  * @return
  */
 public String resolve(String content, String... values) {
  int start = content.indexOf(this.placeholderPrefix);
  if (start == -1) {
   return content;
  }
  //值索引
  int valueIndex = 0;
  StringBuilder result = new StringBuilder(content);
  while (start != -1) {
   int end = result.indexOf(this.placeholderSuffix);
   String replaceContent = values[valueIndex++];
   result.replace(start, end + this.placeholderSuffix.length(), replaceContent);
   start = result.indexOf(this.placeholderPrefix, start + replaceContent.length());
  }
  return result.toString();
 }

 /**
  * 解析带有指定占位符的模板字符串,默认占位符为前缀:${ 后缀:}<br/><br/>
  * 如:template = category:${}:product:${}<br/>
  * values = {"1", "2"}<br/>
  * 返回 category:1:product:2<br/>
  *
  * @param content 要解析的带有占位符的模板字符串
  * @param values 按照模板占位符索引位置设置对应的值
  * @return
  */
 public String resolve(String content, Object[] values) {
  return resolve(content, Stream.of(values).map(String::valueOf).toArray(String[]::new));
 }

 /**
  * 根据替换规则来替换指定模板中的占位符值
  * @param content 要解析的字符串
  * @param rule 解析规则回调
  * @return
  */
 public String resolveByRule(String content, Function<String, String> rule) {
  int start = content.indexOf(this.placeholderPrefix);
  if (start == -1) {
   return content;
  }
  StringBuilder result = new StringBuilder(content);
  while (start != -1) {
   int end = result.indexOf(this.placeholderSuffix, start);
   //获取占位符属性值,如${id}, 即获取id
   String placeholder = result.substring(start + this.placeholderPrefix.length(), end);
   //替换整个占位符内容,即将${id}值替换为替换规则回调中的内容
   String replaceContent = placeholder.trim().isEmpty() ? "" : rule.apply(placeholder);
   result.replace(start, end + this.placeholderSuffix.length(), replaceContent);
   start = result.indexOf(this.placeholderPrefix, start + replaceContent.length());
  }
  return result.toString();
 }

 /**
  * 替换模板中占位符内容,占位符的内容即为map key对应的值,key为占位符中的内容。<br/><br/>
  * 如:content = product:${id}:detail:${did}<br/>
  * valueMap = id -> 1; pid -> 2<br/>
  * 经过解析返回 product:1:detail:2<br/>
  *
  * @param content 模板内容。
  * @param valueMap 值映射
  * @return 替换完成后的字符串。
  */
 public String resolveByMap(String content, final Map<String, Object> valueMap) {
  return resolveByRule(content, placeholderValue -> String.valueOf(valueMap.get(placeholderValue)));
 }

 /**
  * 根据properties文件替换占位符内容
  * @param content
  * @param properties
  * @return
  */
 public String resolveByProperties(String content, final Properties properties) {
  return resolveByRule(content, placeholderValue -> properties.getProperty(placeholderValue));
 }

 /**
  * 根据对象中字段路径(即类似js访问对象属性值)替换模板中的占位符 <br/><br/>
  * 如 content = product:${id}:detail:${detail.id} <br/>
  * obj = Product.builder().id(1).detail(Detail.builder().id(2).build()).build(); <br/>
  * 经过解析返回 product:1:detail:2 <br/>
  *
  * @param content 要解析的内容
  * @param obj 填充解析内容的对象(如果是基本类型,则所有占位符替换为相同的值)
  * @return
  */
 public String resolveByObject(String content, final Object obj) {
  if (obj instanceof Map) {
   return resolveByMap(content, (Map)obj);
  }
  return resolveByRule(content, placeholderValue -> String.valueOf(ReflectionUtils.getValueByFieldPath(obj, placeholderValue)));
 }
}

由于代码还有一些工具类的调用因为篇幅问题没有贴,如有需要可以去 https://gitee.com/objs/mayfly该项目中获取

以上这篇java解析{{}}变量名以及文本内容替换操作就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • Java如何修改.class文件变量

    最近遇到了一个问题,一份很老的代码要修改里面的变量,源码早就和开发者一起不知去向,其中引用了一些jar包导致无法直接编译,只能直接修改.class文件 idea安装jclasslib-bytecode-viewer插件 标准方式安装插件 准备要修改的.class文件 这里我们写一个简单的java方法 /** * @Description: * @author: wei.wang * @since: 2020/9/5 11:18 * @history: 1.2020/9/5 created by

  • java字符串中${}或者{}等的占位符替换工具类

    正如标题所述,这是一个替换java字符串中${}或者{}等占位符的工具类,其处理性能比较令人满意.该类主要通过简单的改写myatis框架中的GenericTokenParser类得到.在日常开发过程中,可以将该类进行简单的改进或封装,就可以用在需要打印日志的场景中,现在张贴出来给有需要的人,使用方式参考main方法,不再赘述! public class Parser { /** * 将字符串text中由openToken和closeToken组成的占位符依次替换为args数组中的值 * @par

  • Java关键字、标识符、常量、变量语法详解

    一.关键字 关键字:被Java语言赋予特定含义的单词.组成关键字的字母全部小写.注:goto和const作为保留字存在,目前并不使用.main并不是关键字. 二.标识符 标识符:就是给类,接口,方法,变量等起名字时使用的字符序列. 组成规则:英文大小写字母.数字字符.$和_ 注意事项:不能以数字开头.不能是Java中的关键字.区分大小写 我们通常会给下面的这些东西起一个标识符: 包.类或者接口.方法和变量.常量 三.注释 单行注释的格式: //注释文字 多行注释的格式: /* 注释文字 */ 文

  • java解析{{}}变量名以及文本内容替换操作

    发短信.发邮件的时候经常会遇到模板内容需要替换成实际数据的问题,本文介绍从文本模板中解析出变量列表,以及参数填入后得到实际文本内容的办法: /** * 根据正则表达式获取文本中的变量名列表 * @param pattern * @param content * @return */ public static List<String> getParams(String pattern, String content) { Pattern p = Pattern.compile(pattern)

  • java实现查找文本内容替换功能示例

    思路: 先看视图层,要有一个JButton控件用来选择文件,一个JTextField控件显示选中文件的绝对路径,一个JLabel控件提示用户输入搜索文本,一个JLabel控件提示用户输入替换后的文本,一个JTextField标签供用户输入要搜索的文本,一个JTextField标签供用户输入替换后的文本,一个JButton控件执行替换,一个JButton控件用来打开修改后的文件.对于选择文件按钮,使用JButton类的addActionListener()方法为其绑定事件,在该事件中定义actio

  • Java环境变量配置教程

    本文实例为大家分享了java的环境变量设置方法,供大家参考,具体内容如下  安装好jdk后找到我的电脑(右键) --> 属性-->高级选项卡-->环境变量,里面有管理员的用户变量,有系统变量.选哪一个都无所谓,我选的是Administrator的用户变量即管理员的用户变量,点击"新建",下面是需要填入的三个环境变量,形式都是环境名=环境值,依次填入即可: JAVA_HOME=c:\j2sdk1.5.0 (jdk安装文件夹位置) classpath=.;%JAVA_HO

  • VSCode同时更改所有相同的变量名或类名的图文教程

    有的时候我们想把代码中某个变量名或类名改一下 但是如果改了,那好多地方都要一起改 如果把所有都一个一个改的话会很浪费时间 所以我们需要一些同时更改所有相同的变量名或类名的方法 多光标 我们可以使用多光标选中所有要改的地方然后一起改 如果多光标的操作不会的话可以去看我的第一篇vscode小操作,链接在文章末尾 演示:  虽然用多光标的确比一个一个改方便了一点,但是还是要用鼠标一个一个去添加光标 重命名 对于我们的类名,变量名之类的有另外一种方法,重命名 操作方式:选中类名或变量名,然后点击重命名符

  • java环境变量配置和adb的配置教程详解

    1.首先需要先把JDK安装好 2.记住自己JDK安装的位置,比如我的是在下图的位置: 3.打开我的电脑–>系统属性–>选择高级系统设置–>选择环境变量 如下图所示: 4. 在系统变量里面新建 系统变量名为 JAVA_HOME 如果已经有就不要新建 因为新建会把之前配的变量覆盖清除掉 变量值:C:\Program Files\Java\jdk1.8.0_181(自己JDK安装的目录) 5. 找到系统变量 Path 变量(这个一般自带的有)→编辑 在变量值最后输入 %JAVA_HOME%\b

  • Java4Android开发教程(四)java的变量

    什么是变量? 在计算机中用来存储信息,通过声明语句来指明存储位置和所需空间. 变量的声明方法及赋值 分号:语句结束标志 赋值号:将=右边的值赋给左边的变量 变量有哪些数据类型? 变量的命名语法规范(合法) 1.以字母.下划线或美元符号开头,后面跟字母.下划线.美元符号或数字. 2.java的变量名没有长度限制. 3.java的变量名对大小写敏感. 驼峰命名法(正确) 1.变量命名选用有意义的英文单词,不使用拼音或拼音缩写. 2.变量名由一个单词组成的则全部小写. 3.变量名由多个单词组成的,从第

  • python关于变量名的基础知识点

    变量名 1.组成:数字.字母.下划线 2.变量名要有意义 3.多个单词则用下划线,如user_id 4.python的变量名不要驼峰显示 字符串: 1.引号内的都称为 字符串 2.常用引号:' '," ",'' '',"" "",''' ''', """ """ 3.支持运算:+,* 数值: 1.支持运算:+,-,*,/,**(指数),%(取余数),//(取商) 如:3**4=81 5%

  • Python变量名详细规则详细变量值介绍

    Python需要使用标识符给变量命名,其实标识符就是用于给程序中变量.类.方法命名的符号(简单来说,标识符就是合法的名称 标识符需要以字母或下划线_开头,可以和字母.数字.下划线进行搭配使用.字母不局限与26个英文字母,其中可以包括中文字符日文字符等等 由于Python 3 也支持 UTF-8 字符集,因此 Python 3 的标识符可以使用 UTF-8 所能表示的多种语言的字符.Python 语言是区分大小写的,因此 abc 和 Abc 是两个不同的标识符. Python 2.x 对中文支持较

  • Android Studio EditText点击图标清除文本内容的实例解析

    这篇文章是继自定义EditText样式之后的功能强化,对于实际应用项目有很大的参考意见,感兴趣的朋友可以移步上一篇,"Android Studion自定义EditText样式".具体清除EditText文本内容功能代码如下: package com.liheng; import android.content.Context; import android.graphics.Rect; import android.graphics.drawable.Drawable; import

  • JAVA过滤标签实现将html内容转换为文本的方法示例

    本文实例讲述了JAVA过滤标签实现将html内容转换为文本的方法.分享给大家供大家参考,具体如下: /** * 把html内容转为文本 * @param html 需要处理的html文本 * @param filterTags 需要保留的html标签样式 * @return */ public static String trimHtml2Txt(String html, String[] filterTags){ html = html.replaceAll("\\<head>[\

随机推荐