JFinal使用技巧-Enjoy使用自定义首定界符'#'换'$'

Enjoy使用自定义首定界符'#'换'$' , 这个功能,在很多模板工具到也有。不过自定义定界符会带来太多使用负担,弊大于利了。但是有些业务确实要用的话,单独 new Engine() 一个不和内置的 Engine 混合,应该也没问题。毕竟再加一个其他模板引擎的话,也是两个写法了差异更大。。。
算了废话不多说了,上码:

还是使用 JFinal 官网 demo 入手:
1、在项目中建一个 包目录:

com.jfinal.template

image.png

2、把JF 源码 EngineConfig.java 拷贝过来,加一个参数 lexerStartDelimiter :

private char lexerStartDelimiter = '#';


/**
 * 设置模板语法指令 起始字符,默认为 #
 */
public void setLexerStartDelimiter(char lexerStartDelimiter) {
    this.lexerStartDelimiter = lexerStartDelimiter;
}

public char getLexerStartDelimiter() {
       return lexerStartDelimiter;
   }

后续再把全部 修改源码贴上来,这里方便阅读操作流程。

3、再创建一个包 stat 如上截图所示:

com.jfinal.template.stat

4、把JF 源码 Lexer.java拷贝过来,加一个参数 startDelimiter:

char startDelimiter;

public Lexer(StringBuilder content, String fileName, Set<String> keepLineBlankDirectives, char startDelimiter) {
    this.keepLineBlankDirectives = keepLineBlankDirectives;

    int len = content.length();
    buf = new char[len + 1];
    content.getChars(0, content.length(), buf, 0);
    buf[len] = EOF;
    this.fileName = fileName;
    this.startDelimiter = startDelimiter;
}

用快捷键 把源码中的 '#' 换成  startDelimiter 变量。

5、把 JF 源码 Parser.java 拷贝过来,再给 new Lexer 加个参数 ec.getLexerStartDelimiter() 自定义的 定界符 变量

public StatList parse() {
    EngineConfig ec = env.getEngineConfig();
    tokenList = new Lexer(content, fileName, ec.getKeepLineBlankDirectives(), ec.getLexerStartDelimiter()).scan();
    tokenList.add(EOF);
    StatList statList = statList();
    if (peek() != EOF) {
       throw new ParseException("Syntax error: can not match \"#" + peek().value() + "\"", getLocation(peek().row));
    }
    return statList;
}

6、修改项目的部署启动脚本 jfinal.sh   Windows 的 jfinal.bat 类似处理。

CP=${APP_BASE_PATH}/lib/你项目打包出来的名字.jar:${APP_BASE_PATH}/config:${APP_BASE_PATH}/lib/*

原理就是 让 jvm 先加载 你改造的 jar,里面有上面改的三个 JF 源码类,后加载 JF 时,这三个类已经占位了。
如果是Tomcat 项目,那么就不用处理了,它会自动先加载 classes目录的。



好了,上测试:
为了方便,还是使用 IndexController :

@Path(value = "/", viewPath = "/index")
public class IndexController extends Controller {
    public void index() {
       Engine en = new Engine();
       en.getEngineConfig().setLexerStartDelimiter('$');
       String v = en.getTemplateByString("$(a) $if(a) OK $end").renderToString(Kv.by("a", "A"));
       set("v", v);
       render("index.html");
    }

}
#@layout()
#define main()
<h1>--#(v)--</h1>
<div class="table_box">
    <p>欢迎来到 JFinal极速开发世界!</p>
    <br><br><br>

上面设置是:
en.getEngineConfig().setLexerStartDelimiter('$');

需要自定义定界字符的功能 就new Engine()一个对象,单独放在自己业务里面,经常调用的话,就用 静态变量声明一下,和普通使用是一样的。


开发启动,idea 会自动先加载 编译目录的:
image.png


------------------------------------------------
源码贴不上了。。。内容应该是太多了,不过改的代码也没几行,自己操作也行。
https://gitee.com/jfinal/jfinal/tree/master/src/main/java/com/jfinal/template

image.png
不建议这样使用!!!除非没办法,比引入多个模板引擎强一点。


PS:未深度测试,需要自己多试用,如果遇到问题,需要改源码,和上面类似处理就行。也欢迎反馈到这个帖子下面,大家如果用到这个功能,也可以避免误踩坑。。。


好了,分享结束!祝元旦快乐~

评论区

山东小木

2025-01-02 07:18

提交PR呀

杜福忠

2025-01-02 12:14

@山东小木 记得以前群里讨论过,弊大于利来着。 先这样吧,有需求的这样用也没问题,后续有升级这几个类的情况,跟着再拷贝一次就行了

热门分享

扫码入社