Java模板工具类实现解析简单的表达式

package util;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * @author aiping
 * @description : do some thing
 * @since 2019/2/27 0027
 */
public class SimpleTempletUtil {

    public static final String DEFAULT_SPLIT = "$$";
    /**
     * 使用context中对应的值替换templet中用$$包围的变量名(也是context的key)
     * @param templet 模板
     * @param context 用于替换模板中的变量
     * @return 例如  参数 : dddd$$aaa$$$$bbb$$ccc$$, $$, {<aaa, value1>, <bbb, value2>}  结果:ddddvalue1value2ccc$$
     */
    public static String render(String templet, Map<String, String> context) {

        return render(templet, DEFAULT_SPLIT, context);
    }

    /**
     * 使用context中对应的值替换templet中用split包围的变量名(也是context的key)
     * @param templet 模板
     * @param split 用于标识变量名的标志
     * @param context 用于替换模板中的变量
     * @return 例如  参数 : dddd$$aaa$$$$bbb$$ccc$$, $$, {<aaa, value1>, <bbb, value2>}  结果:ddddvalue1value2ccc$$
     */
    public static String render(String templet, String split, Map<String, String> context) {
        Set<String> paramNames = getParamNames(templet, split);

        for (String name : paramNames) {
            String value = context.get(name);
            value = value == null ? "" : value;
            String regex = "\\Q" + split + name + split + "\\E";
            templet = templet.replaceAll(regex, value);
        }

        return templet;
    }

    /**
     * 根据分割符从模板中取得变量的名字($$变量名$$) eg:
     * $$aaa$$$$bbb$$ccc$$ 返回   aaa,bbb
     * @param templet 模板
     * @param split 包围变量名的字符串
     * @return 模板中的变量名
     */
    public static Set<String> getParamNames(String templet, String split) {
        Set<String> paramNames = new HashSet<String>();

        int start = 0, end = 0;
        while (end < templet.length()) {
            start = templet.indexOf(split, end) + split.length();
            if (start == -1) {
                break;
            }
            //start += split.length();

            end = templet.indexOf(split, start);
            if (end == -1) {
                break;
            }
            paramNames.add(templet.substring(start, end));
            end = end + split.length();
        }
        return paramNames;
    }


    public static void main(String[] args) {
       Set<String> paramNames = getParamNames("恭喜您:$$name$$注册成功人人app,您的账号为:$$code$$", "$$");
        System.out.println(paramNames);

        Map<String, String> context = new HashMap<String, String>();
        context.put("name", "小王");
        context.put("code", "125284588");
        String render = render("恭喜您:$$name$$注册成功人人app,您的账号为:$$code$$", context );
        System.out.println(render);
    }
}

输出结果

[code, name]
恭喜您:小王注册成功人人app,您的账号为:125284588
package util;

import java.util.*;

/**
 * 非常非常简单的模板实现
 *
 * @author desheng.tu
 * @date 2015年6月23日 下午4:38:05
 *
 */
public class SimpleTmpl {

    public static void main(String[] args) {
        String t1 = "恭喜您 $$name$$, 注册成功人人app,您的账号为:$$code$$";
        String t2 = "你好 #{name}, 您的验证码是:${code}";

        Map<String,String> param=new HashMap<>();
        param.put("name", "小王");
        param.put("code", "13252623145");

        for (int i = 0; i < 100; i++) {
            SimpleTempletUtil.render(t1, param);
            Templ.of(t2).render(param);
        }

        String result = "";
        long start = 0;

        start = System.currentTimeMillis();
        for (int i = 0; i < 100000; i++) {
            param.put("code", i+"");
            result = SimpleTempletUtil.render(t1, param);
        }
        System.out.println(System.currentTimeMillis() - start);
        System.out.println(result);

        start = System.currentTimeMillis();

        Templ templ = Templ.of(t2);
        for (int i = 0; i < 100000; i++) {
            param.put("code", i+"");
            result = templ.render(param);
        }
        System.out.println(System.currentTimeMillis() - start);

        System.out.println(result);

    }

}

abstract class Exp {

    abstract String resolve(Map<String, String> context);

    static Exp of(String exp) {
        Objects.requireNonNull(exp);
        if (exp.startsWith("#{") || exp.startsWith("${")) {
            return new VarExp(exp);
        }
        return new StrExp(exp);
    }
}

class StrExp extends Exp {

   private String value;

    StrExp(String exp) {
        this.value = exp;
    }

    @Override
    public String resolve(Map<String, String> context) {
        return this.value;
    }

    @Override
    public String toString() {
        return "StrExp [value=" + value + "]";
    }

}

class VarExp extends Exp {

   private String varName;
   private String defaultValue;
   private Boolean nullable = false;

    VarExp(String varName, String defaultValue, Boolean nullable) {
        this.varName = varName;
        this.defaultValue = defaultValue;
        this.nullable = nullable;
    }

    VarExp(String exp) {
        Objects.requireNonNull(exp);
        if (!(exp.startsWith("#{") || exp.startsWith("${")) || !exp.endsWith("}")) {
            throw new IllegalArgumentException("表达式[" + exp + "]必须类似于#{}或${}");
        }

        String[] nodes = exp.substring(2, exp.length() - 1).split(",");
        if (nodes.length > 2) {
            throw new IllegalArgumentException("表达式[" + exp + "]只能出现一个','");
        }

        this.varName = nodes[0].trim();
        this.defaultValue = nodes.length == 2 ? nodes[1].trim() : "";
        this.nullable = exp.startsWith("$");
    }

    @Override
    public String resolve(Map<String, String> context) {
        String value = context.get(varName);
        if (value == null && nullable) {
            value = defaultValue == null ? "" : defaultValue;
        }
        if (value == null) {
            throw new NullPointerException("上下文中没有指定的变量:var=" + varName + " map=" + context);
        }
        return value;
    }

    @Override
    public String toString() {
        return "VarExp [varName=" + varName + ", defaultValue=" + defaultValue + ", nullable="
                + nullable + "]";
    }

}

class Templ {

  private   List<Exp> exps = new ArrayList<>();

    static Templ of(String templStr) {

        Objects.requireNonNull(templStr, "模板为空");

        Templ templ = new Templ();
        StringBuilder sb = new StringBuilder();

        char[] chars = templStr.toCharArray();
        for (int i = 0; i < chars.length; i++) {
            switch (chars[i]) {
                case '#':
                case '$':
                    if(i < chars.length - 1 && chars[i+1] == '{'){
                        templ.addExp(Exp.of(sb.toString()));
                        sb.setLength(0);
                    }
                    sb.append(chars[i]);
                    break;
                case '}':
                    sb.append('}');
                    if(sb.length() > 1 && sb.charAt(1) == '{'){
                        templ.addExp(Exp.of(sb.toString()));
                        sb.setLength(0);
                    }
                    break;
                default:
                    sb.append(chars[i]);
                    break;
            }
        }

        if(sb.length() > 0){
            templ.addExp(Exp.of(sb.toString()));
        }

        return templ;
    }

  private   Templ addExp(Exp exp) {
        Objects.requireNonNull(exp, "表达式为空");
        exps.add(exp);
        return this;
    }

    String render(Map<String, String> context) {
        StringBuilder sb = new StringBuilder(128);
        for (Exp exp : exps) {

            sb.append(exp.resolve(context));
        }
        return sb.toString();
    }
}

输出结果:

529
恭喜您 小王, 注册成功人人咖app,您的账号为:99999
41
你好 小王, 您的验证码是:99999
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值