网站租空间多少钱,wordpress不用插件,百度收录怎么查询,湖南网站建设哪家专业Java 模板变量替换——字符串替换器#xff08;思路Mybatis的GenericTokenParser#xff09; 思路字符串替换器 思路
模板变量替换无非是寻找出字符串#xff08;模板#xff09;中的特殊标记#xff0c;用对应的变量进行字符串替换。 提到变量替换#xff0c;大家第一能… Java 模板变量替换——字符串替换器思路Mybatis的GenericTokenParser 思路字符串替换器 思路
模板变量替换无非是寻找出字符串模板中的特殊标记用对应的变量进行字符串替换。 提到变量替换大家第一能联想到的可能是Mybatis的动态SQL语句的解析又或者是mybatis.xml配置文件中用于解析${username:root}的默认值。 在Mybatis的源码中这些功能则是通过GenericTokenParser类来实现的通过查看源码可以很明显的知道GenericTokenParser只是查找指定的占位符而具体的解析行为会根据其持有的TokenHandler实现的不同而有所不同这里是采用了策略模式。 那么接下来我们就使用Mybatis的思路试着写一个字符串替换器吧
字符串替换器
GenericTokenParser
public class GenericTokenParser {private final String openToken;private final String closeToken;private final TokenHandler handler;public GenericTokenParser(String openToken, String closeToken, TokenHandler handler) {this.openToken openToken;this.closeToken closeToken;this.handler handler;}public String parse(String text) {if (text null || text.isEmpty()) {return ;}// search open tokenint start text.indexOf(openToken, 0);if (start -1) {return text;}char[] src text.toCharArray();int offset 0;final StringBuilder builder new StringBuilder();StringBuilder expression null;while (start -1) {if (start 0 src[start - 1] \\) {// this open token is escaped. remove the backslash and continue.builder.append(src, offset, start - offset - 1).append(openToken);offset start openToken.length();} else {// found open token. lets search close token.if (expression null) {expression new StringBuilder();} else {expression.setLength(0);}builder.append(src, offset, start - offset);offset start openToken.length();int end text.indexOf(closeToken, offset);while (end -1) {if (end offset src[end - 1] \\) {// this close token is escaped. remove the backslash and continue.expression.append(src, offset, end - offset - 1).append(closeToken);offset end closeToken.length();end text.indexOf(closeToken, offset);} else {expression.append(src, offset, end - offset);offset end closeToken.length();break;}}if (end -1) {// close token was not found.builder.append(src, start, src.length - start);offset src.length;} else {builder.append(handler.handleToken(expression.toString()));offset end closeToken.length();}}start text.indexOf(openToken, offset);}if (offset src.length) {builder.append(src, offset, src.length - offset);}return builder.toString();}
}TokenHandler
public interface TokenHandler {String handleToken(String content);
}以上代码是Mybatis的源码可以直接抄接下来编写核心的逻辑 这里的数据使用MapString,Object来存储key是变量名称value是变量值value的类型下列代码仅支持了String和List对应的可以实现直接变量替换和循环变量替换有其他需要可以在此基础上新增功能而List的泛型仅支持MapString,String即不支持多层嵌套。 在这个例子中我使用${变量名}表示普通变量变量名/变量名表示循环变量标签内的内容将被循环展示
public class ReportGenerator {public static void main(String[] args) {String reportTemplate 这是一份贵司专属总结报告请查收\n 您的订单编号${firstShowId}产品名称${firstProductName}于${firstOnlineDate}正式生效今天是贵司正式启用电子签名的第90天截至今天您的订单使用情况如下#{${a}/${b}}\n orders${orders.productName}累计消耗${orders.displayConsumeAmount}${orders.units}/orders 如对使用情况和数据报告有任何疑问可随时联系你的客户成功经理。\n contracts合同编号${contracts.contractId}合同负责人:${contracts.contractManager}${name}/contracts;MapString, Object data new HashMap();data.put(firstShowId, 123456789);data.put(firstProductName, 测试产品);data.put(firstOnlineDate, 2023-01-01);data.put(productName, 测试产品);data.put(name, 张三);data.put(a, 100);data.put(b, 10);data.put(c, 10);ListMapString, String orders new ArrayList();MapString, String param1 new HashMap();param1.put(productName, 测试产品1);param1.put(displayConsumeAmount, 100);param1.put(units, 元);orders.add(param1);MapString, String param2 new HashMap();param2.put(productName, 测试产品2);param2.put(displayConsumeAmount, 200);param2.put(units, 元);orders.add(param2);data.put(orders, orders);ListMapString, String contracts new ArrayList();MapString, String param3 new HashMap();param1.put(contractId, 12312543243213);param1.put(contractManager, 杜甫);contracts.add(param1);MapString, String param4 new HashMap();param2.put(contractId, 1234353453);param2.put(contractManager, 李白);contracts.add(param2);data.put(contracts, contracts);String handler handler(data, reportTemplate);// 打印报告System.out.println(handler);}public static String handler(MapString, Object data, String templateContent) {// 循环变量仅支持一层嵌套MapString, ListMapString, String loopVariables new HashMap();// 基本参数MapString, String basicVariables new HashMap();// 分类循环变量基本参数计算参数for (Map.EntryString, Object entry : data.entrySet()) {String key entry.getKey();Object value entry.getValue();if (value instanceof List) {loopVariables.put(key, (ListMapString, String) value);} else if (value instanceof String) {basicVariables.put(key, (String) value);}}// 处理循环变量for (Map.EntryString, ListMapString, String entry : loopVariables.entrySet()) {String key entry.getKey();ListMapString, String value entry.getValue();ForEachTokenParser forEachTokenParser new ForEachTokenParser(key, value, \n);GenericTokenParser genericTokenParser new GenericTokenParser( key , / key , forEachTokenParser);templateContent genericTokenParser.parse(templateContent);}// 处理基本参数VariableTokenParser variableTokenParser new VariableTokenParser(basicVariables);GenericTokenParser genericTokenParser new GenericTokenParser(${, }, variableTokenParser);templateContent genericTokenParser.parse(templateContent);// // 计算参数// EquationTokenParser equationTokenParser new EquationTokenParser();// GenericTokenParser equationParser new GenericTokenParser(#{, }, equationTokenParser);// templateContent equationParser.parse(templateContent);return templateContent;}/*** 循环变量参数*/static class ForEachTokenParser implements TokenHandler {private final String variableName;private final ListMapString, String variables;private final String separator;public ForEachTokenParser(String variableName, ListMapString, String variable, String separator) {this.variableName variableName;this.variables variable;this.separator separator;}Overridepublic String handleToken(String content) {if (variables null || variables.isEmpty()) {throw new RuntimeException(变量不存在 content);}StringBuilder builder new StringBuilder();for (MapString, String variable : variables) {VariableTokenParser variableTokenParser new VariableTokenParser(variable);GenericTokenParser genericTokenParser new GenericTokenParser(${ variableName ., }, variableTokenParser);builder.append(genericTokenParser.parse(content)).append(separator);}return builder.toString();}}/*** 基础变量参数*/static class VariableTokenParser implements TokenHandler {private final MapString, String variables;public VariableTokenParser(MapString, String variable) {this.variables variable;}Overridepublic String handleToken(String content) {String value variables.get(content);if (value null) {throw new RuntimeException(变量不存在 content);}return value;}}/*** 计算参数* 目前仅支持除法运算#{100/10}*/// static class EquationTokenParser implements TokenHandler {//// Override// public String handleToken(String content) {// return String.valueOf(evaluateExpression(content));// }//// private static double evaluateExpression(String expression) {// String[] parts expression.split(/);// if (parts.length 2) {// BigDecimal numerator new BigDecimal(parts[0].trim());// BigDecimal denominator new BigDecimal(parts[1].trim());// return numerator.divide(denominator, 2, RoundingMode.HALF_UP).doubleValue();// }// return 0;// }// }
}