• JFinal Enjoy指令扩展管理常用文本模板



    个人博客 地址:http://www.wenhaofan.com/article/20190304102258

    平时在项目中使用短信模板 邮件模板以及 站内消息通知等文本模板一般都是通过手动的字符串拼接来完成,例如:"欢迎"+user.getName()+"加入俱乐部。"

    然而这种方法不仅代码难看而且还不方便管理,因此为了更方便的在项目中管理使用这类文本模板,参考JFinal源码中的activerecord管理sql的代码来扩展了Enjoy的指令。


    1.扩展代码

    package com.autu.common.keys;
     
     
    import com.jfinal.kit.StrKit;
    import com.jfinal.template.Directive;
    import com.jfinal.template.Env;
    import com.jfinal.template.expr.ast.Const;
    import com.jfinal.template.expr.ast.Expr;
    import com.jfinal.template.expr.ast.ExprList;
    import com.jfinal.template.io.Writer;
    import com.jfinal.template.stat.ParseException;
    import com.jfinal.template.stat.Scope;
    
    /**
     * KeysDirective
     */
    public class KeysDirective extends Directive {
    	
    	static final String KEYS_DIRECTIVE="_KEYS_DIRECTIVE";
    	
    	private String id;
    	
    	public void setExprList(ExprList exprList) {
    		if (exprList.length() == 0) {
    			throw new ParseException("The parameter of #keys directive can not be blank", location);
    		}
    		if (exprList.length() > 1) {
    			throw new ParseException("Only one parameter allowed for #keys directive", location);
    		}
    		Expr expr = exprList.getExpr(0);
    		if (expr instanceof Const && ((Const)expr).isStr()) {
    		} else {
    			throw new ParseException("The parameter of #keys directive must be String", location);
    		}
    		
    		this.id = ((Const)expr).getStr();
    	}
    	
    	
    	public void exec(Env env, Scope scope, Writer writer) {
    		String beforeKey=(String)scope.get(KeysDirective.KEYS_DIRECTIVE);
     
    		String key = StrKit.isBlank(beforeKey) ? id : beforeKey + "." + id;
    		scope.set(KEYS_DIRECTIVE, key);
    	
    		stat.exec(env, scope, writer);
    	
    	}
    	
    	public boolean hasEnd() {
    		return true;
    	}
    }
    package com.autu.common.keys;
     
     
    import java.util.Map;
    
    import com.jfinal.kit.StrKit;
    import com.jfinal.template.Directive;
    import com.jfinal.template.Env;
    import com.jfinal.template.Template;
    import com.jfinal.template.expr.ast.Const;
    import com.jfinal.template.expr.ast.Expr;
    import com.jfinal.template.expr.ast.ExprList;
    import com.jfinal.template.io.Writer;
    import com.jfinal.template.stat.ParseException;
    import com.jfinal.template.stat.Scope;
    
    /**
     * KeyDirective
     */
    public class KeyDirective extends Directive {
    	
    	static final String KEY_DIRECTIVE="_KEY_DIRECTIVE";
    	
    	private String id;
    	
    	public void setExprList(ExprList exprList) {
    		if (exprList.length() == 0) {
    			throw new ParseException("The parameter of #key directive can not be blank", location);
    		}
    		if (exprList.length() > 1) {
    			throw new ParseException("Only one parameter allowed for #key directive", location);
    		}
    		Expr expr = exprList.getExpr(0);
    		if (expr instanceof Const && ((Const)expr).isStr()) {
    		} else {
    			throw new ParseException("The parameter of #key directive must be String", location);
    		}
    		
    		this.id = ((Const)expr).getStr();
    	}
    	
    	
    	@SuppressWarnings("unchecked")
    	public void exec(Env env, Scope scope, Writer writer) {
    		String nameSpace = (String)scope.get(KeysDirective.KEYS_DIRECTIVE);
    		String key = StrKit.isBlank(nameSpace) ? id : nameSpace + "." + id;
    		Map<String, Template> keyTemplateMap = (Map<String, Template>)scope.get(KeyKit.KEY_TEMPLATE_MAP_KEY);
    		if (keyTemplateMap.containsKey(key)) {
    			throw new ParseException("Key already exists with key : " + key, location);
    		}
    		
    		keyTemplateMap.put(key, new Template(env, stat));
    	}
    	
    	public boolean hasEnd() {
    		return true;
    	}
    }
    package com.autu.common.keys;
    
     
    import com.jfinal.template.source.ISource;
    
    /**
     * 封装 key 模板源
     */
    class KeySource {
    	
    	String file;
    	ISource source;
    	
    	KeySource(String file) {
    		this.file = file;
    		this.source = null;
    	}
    	
    	KeySource(ISource source) {
    		this.file = null;
    		this.source = source;
    	}
    	
    	boolean isFile() {
    		return file != null;
    	}
    }
    package com.autu.common.keys;
    
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    import com.jfinal.kit.Kv;
    import com.jfinal.kit.StrKit;
    import com.jfinal.template.Engine;
    import com.jfinal.template.Template;
    import com.jfinal.template.source.ISource;
    import com.jfinal.template.stat.ParseException;
    
    /**
     * Email Kit
     */
    public class KeyKit {
    
    	static final String KEY_TEMPLATE_MAP_KEY = "_KEY_TEMPLATE_MAP_";
    	static final boolean DEFAULT_DEV_MODE=false;
    	public static final String MAIN_CONFIG_NAME = "keys";
    	public String configName;
    	private  boolean devMode=false;
    	private Engine engine;
    	private List<KeySource> keySourceList = new ArrayList<KeySource>();
    	public Map<String, Template> keyTemplateMap;
    
    	private static final Map<String,KeyKit> keyKitMap=new HashMap<>();
    	
    	public static KeyKit use(String configName) {
    		return keyKitMap.get(configName);
    	}
    	
    	public static KeyKit use() {
    		return use(MAIN_CONFIG_NAME);
    	}
    	
    	private KeyKit(boolean devMode) {
    		this(MAIN_CONFIG_NAME, devMode);
    	}
    
    	public static KeyKit load(String configName) {
    		
    		if(keyKitMap.containsKey(configName)) {
    			return keyKitMap.get(configName);
    		}
    		
    		return new KeyKit(configName,DEFAULT_DEV_MODE);
    	}
    	
    	public static KeyKit load(boolean devMode) {
    		if(keyKitMap.containsKey(MAIN_CONFIG_NAME)) {
    			return keyKitMap.get(MAIN_CONFIG_NAME);
    		}
    		return new KeyKit(devMode);
    	}
    
    	public static KeyKit load(String configName, boolean devMode) {
    		if(keyKitMap.containsKey(configName)) {
    			return keyKitMap.get(configName);
    		}
    		return new KeyKit(configName, devMode);
    	}
    
    	private KeyKit(String configName, boolean devMode) {
    		this.configName = configName;
    		this.devMode = devMode;
    
    		if(keyKitMap.containsKey(configName)) {
    			throw new ParseException("Key already exists", null );
    		}
    		
    		engine = new Engine(configName);
    		engine.setDevMode(devMode);
    		engine.addDirective("key", KeyDirective.class);
    		engine.addDirective("keys", KeysDirective.class);
    		engine.addSharedMethod(new StrKit());
    		
    		
    		keyKitMap.put(configName, this);
    	}
    
    	public KeyKit(String configName) {
    		this(configName, false);
    	}
    
    	public Engine getEngine() {
    		return engine;
    	}
    
    	public void setDevMode(boolean devMode) {
    		this.devMode = devMode;
    		engine.setDevMode(devMode);
    	}
    
    	public KeyKit setBaseKeyTemplatePath(String baseKeyTemplatePath) {
    		engine.setBaseTemplatePath(baseKeyTemplatePath);
    		return this;
    	}
    
    	public KeyKit addTemplate(String KeyTemplate) {
    		if (StrKit.isBlank(KeyTemplate)) {
    			throw new IllegalArgumentException("keyTemplate can not be blank");
    		}
    		keySourceList.add(new KeySource(KeyTemplate));
    		return this;
    	}
    
    	public void addTemplate(ISource keyTemplate) {
    		if (keyTemplate == null) {
    			throw new IllegalArgumentException("keyTemplate can not be null");
    		}
    		keySourceList.add(new KeySource(keyTemplate));
    	}
    
    	public synchronized KeyKit parseKeysTemplate() {
    		Map<String, Template> keyTemplateMap = new HashMap<String, Template>(512, 0.5F);
    		for (KeySource ss : keySourceList) {
    			Template template = ss.isFile() ? engine.getTemplate(ss.file) : engine.getTemplate(ss.source);
    			Map<Object, Object> data = new HashMap<Object, Object>();
    			data.put(KEY_TEMPLATE_MAP_KEY, keyTemplateMap);
    			template.renderToString(data);
    		}
    		this.keyTemplateMap = keyTemplateMap;
    		return this;
    	}
    
    	private void reloadModifiedKeyTemplate() {
    		engine.removeAllTemplateCache(); // 去除 Engine 中的缓存,以免 get 出来后重新判断 isModified
    		parseKeysTemplate();
    	}
    
    	private boolean isKeyTemplateModified() {
    		for (Template template : keyTemplateMap.values()) {
    			if (template.isModified()) {
    				return true;
    			}
    		}
    		return false;
    	}
    
    	private Template getKeyTemplate(String key) {
    		Template template = keyTemplateMap.get(key);
    		if (template == null) { // 此 if 分支,处理起初没有定义,但后续不断追加 key 的情况
    			if (!devMode) {
    				return null;
    			}
    			if (isKeyTemplateModified()) {
    				synchronized (this) {
    					if (isKeyTemplateModified()) {
    						reloadModifiedKeyTemplate();
    						template = keyTemplateMap.get(key);
    					}
    				}
    			}
    			return template;
    		}
    
    		if (devMode && template.isModified()) {
    			synchronized (this) {
    				template = keyTemplateMap.get(key);
    				if (template.isModified()) {
    					reloadModifiedKeyTemplate();
    					template = keyTemplateMap.get(key);
    				}
    			}
    		}
    		return template;
    	}
     
    	
    	/**
    	 * 示例: 1:模板 定义 #key("key")
    	 * 
    	 * #end
    	 *
    	 * 2:java 代码 getContent("key", Kv);
    	 */
    	public String getContent(String key, Kv kv) {
    		Template template = getKeyTemplate(key);
    		if (template == null) {
    			return null;
    		}
    		return template.renderToString(kv);
    	}
    
    	
    	public java.util.Set<java.util.Map.Entry<String, Template>> getKeyMapEntrySet() {
    		return keyTemplateMap.entrySet();
    	}
    
    	public String toString() {
    		return "KeyTplKit for config : " + configName;
    	}
    }

    2.模板文件

    image.png

        3.1 all_emails.tpl

    #keys("comment")
    	#include("innerKeys.tpl")
    #end

        3.2 comment.tpl

    #key("comment_title")
    [#(config.title)评论通知] Re:#(title)
    #end

        3.3 inner.tpl

    #keys("inner")
       #include("comment.tpl")
    #end

    3.创建管理工具

    KeyKit.load(p.getBoolean("devMode", false))
        .setBaseKeyTemplatePath(PathKit.getRootClassPath() + "/email")
        .addTemplate("all_emails.tpl")
        .parseKeysTemplate();	

    4.使用

       String keyContent=	KeyKit.use().getContent("comment.inner.comment_title", 
    	    		Kv.by("config",new Config().setTitle("test")).set("title", "title1"));
    		System.out.println(keyContent);

    输出结果

      [test评论通知] Re:title1

    5.说明

        此处演示的为多层嵌套keys的使用,单层和jfinal的sql管理一样使用

  • 相关阅读:
    Oracle-创建PDB
    win10怎么看IP地址、怎么看主机名
    怎么读dll文件
    Windows的注册表是什么?
    DbHelperOra类的相关链接(没看)
    C#中//注释和///注释的区别
    有关C#的序列化
    【智能指针 | 01】std::shared_ptr的使用教程
    coreump
    d
  • 原文地址:https://www.cnblogs.com/fanwenhao/p/10478199.html
Copyright © 2020-2023  润新知