栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

【Mybatis】使用 org.apache.ibatis.parsing.PropertyParser 造一个自己的模板引擎

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【Mybatis】使用 org.apache.ibatis.parsing.PropertyParser 造一个自己的模板引擎

在后端编程中,我们经常要做对目标文本进行变量的解析与替换工作。
这时候就会面临纠结,

  1. 用正则表达式去替换,担心性能问题;
  2. 用模板引擎去解析,又觉得是在用高射炮打蚊子,还要引入了第三方依赖;
  3. 想自己撸一个轮子,时间紧、任务重,又担心出 BUG。

那这下好了,Mybatis的源码里面就有这样现成的轮子,它的代码是经过千万用户的使用,总不用担心出 BUG 了吧?
PS:如果真被你用出 BUG 了,转手就去Mybatis搞一波issue + pr也挺香的。

talk is cheap, show me the code.

softwareversion
open jdk1.8
MyBatis3.5.5
测试用例
package com.itplh.parse;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Properties;

public class MyPropertyParserTest {

    public static void main(String[] args) {
        Properties properties = new Properties();
        properties.put("hostName", "my-property-parser-test");
        properties.put("ip", "123.123.123.1");
        String ymd = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(LocalDateTime.now());
        properties.put("alarmTime", ymd);
        properties.put("currentTime", ymd);

        String text1 = new StringBuilder()
                .append("【监控报警】n")
                .append("报警机器:${hostName} | ${ip}n")
                .append("报警时间:${alarmTime}n")
                .append("通知时间:${currentTime}n")
                .toString();
        System.out.println(text1);
        System.out.println(MyPropertyParser.parse(text1, properties));

        String text2 = new StringBuilder()
                .append("【监控报警】n")
                .append("配置名称:{{config:默认配置}}n") // config设置了默认值
                .append("报警机器:{{hostName}} | {{ip:0.0.0.0}}n") // ip设置了默认值
                .append("报警时间:{{alarmTime}}n")
                .append("通知时间:{{currentTime}}n")
                .toString();
        // 启用默认值 定义包裹变量的符号为{{}}
        properties.put(VariableTokenHandler.ENABLE_DEFAULT_VALUE_KEY, "true");
        System.out.println(text2);
        System.out.println(MyPropertyParser.parse(text2, "{{", "}}", properties));
    }

}

控制台输出

【监控报警】
报警机器:${hostName} | ${ip}
报警时间:${alarmTime}
通知时间:${currentTime}

【监控报警】
报警机器:my-property-parser-test | 123.123.123.1
报警时间:2022-06-12 15:21:35
通知时间:2022-06-12 15:21:35

【监控报警】
配置名称:{{config:默认配置}}
报警机器:{{hostName}} | {{ip:0.0.0.0}}
报警时间:{{alarmTime}}
通知时间:{{currentTime}}

【监控报警】
配置名称:默认配置
报警机器:my-property-parser-test | 123.123.123.1
报警时间:2022-06-12 15:21:35
通知时间:2022-06-12 15:21:35
源码 MyPropertyParser
package com.itplh.parse;


import java.util.Properties;

public class MyPropertyParser {

    public static String parse(String text, Properties variables) {
        return parse(text, "${", "}", variables);
    }

    public static String parse(String text, String openToken, String closeToken, Properties variables) {
        VariableTokenHandler handler = new VariableTokenHandler(variables);
        GenericTokenParser parser = new GenericTokenParser(openToken, closeToken, handler);
        return parser.parse(text);
    }

}
GenericTokenParser
package com.itplh.parse;

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()) {
            int start = text.indexOf(this.openToken);
            if (start == -1) {
                return text;
            } else {
                char[] src = text.toCharArray();
                int offset = 0;
                StringBuilder builder = new StringBuilder();

                for (StringBuilder expression = null; start > -1; start = text.indexOf(this.openToken, offset)) {
                    if (start > 0 && src[start - 1] == '\') {
                        builder.append(src, offset, start - offset - 1).append(this.openToken);
                        offset = start + this.openToken.length();
                    } else {
                        if (expression == null) {
                            expression = new StringBuilder();
                        } else {
                            expression.setLength(0);
                        }

                        builder.append(src, offset, start - offset);
                        offset = start + this.openToken.length();

                        int end;
                        for (end = text.indexOf(this.closeToken, offset); end > -1; end = text.indexOf(this.closeToken, offset)) {
                            if (end <= offset || src[end - 1] != '\') {
                                expression.append(src, offset, end - offset);
                                break;
                            }

                            expression.append(src, offset, end - offset - 1).append(this.closeToken);
                            offset = end + this.closeToken.length();
                        }

                        if (end == -1) {
                            builder.append(src, start, src.length - start);
                            offset = src.length;
                        } else {
                            builder.append(this.handler.handleToken(expression.toString(), this.openToken, this.closeToken));
                            offset = end + this.closeToken.length();
                        }
                    }
                }

                if (offset < src.length) {
                    builder.append(src, offset, src.length - offset);
                }

                return builder.toString();
            }
        } else {
            return "";
        }
    }
}
TokenHandler
package com.itplh.parse;

public interface TokenHandler {
    String handleToken(String content, String openToken, String closeToken);
}
VariableTokenHandler
package com.itplh.parse;

import java.util.Properties;

public class VariableTokenHandler implements TokenHandler {

    public static final String ENABLE_DEFAULT_VALUE_KEY = "enable-default-value";
    public static final String DEFAULT_VALUE_SEPARATOR_KEY = "default-value-separator";

    private final Properties variables;
    private final boolean enableDefaultValue;
    private final String defaultValueSeparator;

    public VariableTokenHandler(Properties variables) {
        this.variables = variables;
        this.enableDefaultValue = Boolean.parseBoolean(this.getPropertyValue(ENABLE_DEFAULT_VALUE_KEY, "false"));
        this.defaultValueSeparator = this.getPropertyValue(DEFAULT_VALUE_SEPARATOR_KEY, ":");
    }

    private String getPropertyValue(String key, String defaultValue) {
        return this.variables == null ? defaultValue : this.variables.getProperty(key, defaultValue);
    }

    @Override
    public String handleToken(String content, String openToken, String closeToken) {
        if (this.variables != null) {
            String key = content;
            if (this.enableDefaultValue) {
                int separatorIndex = content.indexOf(this.defaultValueSeparator);
                String defaultValue = null;
                if (separatorIndex >= 0) {
                    key = content.substring(0, separatorIndex);
                    defaultValue = content.substring(separatorIndex + this.defaultValueSeparator.length());
                }

                if (defaultValue != null) {
                    return this.variables.getProperty(key, defaultValue);
                }
            }

            if (this.variables.containsKey(key)) {
                return this.variables.getProperty(key);
            }
        }

        return openToken + content + closeToken;
    }

}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/969564.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号