JFinal使用技巧-Enjoy魔板代码生成器

^_^ 搞事情~ 要趁早!   demo生成器还不能满足你? 需要service 需要 Controller吗?

1~ 核心动力

package com.momathink.tpp;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

import com.jfinal.kit.Kv;
import com.jfinal.kit.PathKit;
import com.jfinal.template.Engine;

/***
 * jfinal魔板引擎
 * @author dufuzhong
 */
public class JfEnjoy {

    /**
     * 根据具体魔板生成文件
     * @param templateFileName  模板文件名称
     * @param kv                渲染参数
     * @param filePath          输出目录
     * @return 
     */
    public boolean render(String templateFileName, Kv kv, StringBuilder filePath)  {
        BufferedWriter output = null;
        try {
            String baseTemplatePath = new StringBuilder(PathKit.getRootClassPath())
            .append("/")
            .append(PathKit.getPackagePath(this))
            .append("/tpl")
            .toString();
            
            File file = new File(filePath.toString());
            
            File path = new File(file.getParent());
            if ( ! path.exists() ) {
                path.mkdirs();
            }
            output = new BufferedWriter(new FileWriter(file));
            
            Engine.use()
            .setBaseTemplatePath(baseTemplatePath)
            .getTemplate(templateFileName)
            .render(kv, output);
            
            return true;
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }finally{
            try { if( output != null ) output.close(); } catch (IOException e) {}
        }
    }
    
    /**
     * 根据自定义内容生成文件
     * @param data              自定义内容
     * @param filePath          输出目录
     * @return 
     */
    public boolean render(String data, StringBuilder filePath)  {
        BufferedWriter output = null;
        try {
            
            File file = new File(filePath.toString());
            
            File path = new File(file.getParent());
            if ( ! path.exists() ) {
                path.mkdirs();
            }
            output = new BufferedWriter(new FileWriter(file));
            
            output.write(data);
            return true;
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }finally{
            try { if( output != null ) output.close(); } catch (IOException e) {}
        }
    }

}


2~ 业务开跑

package com.momathink.tpp;

import java.util.List;

import javax.sql.DataSource;

import com.demo.common.model._JFinalDemoGenerator;
import com.jfinal.kit.Kv;
import com.jfinal.kit.PathKit;
import com.jfinal.plugin.activerecord.dialect.MysqlDialect;
import com.jfinal.plugin.activerecord.generator.DataDictionaryGenerator;
import com.jfinal.plugin.activerecord.generator.MetaBuilder;
import com.jfinal.plugin.activerecord.generator.TableMeta;

/**
 * 代码生成器
 * @author dufuzhong
 */
public class JfGenerator {
    
    public static final JfGenerator me  = new JfGenerator();
    protected final JfEnjoy jfEngine    = new JfEnjoy();
    
    protected Kv tablemetaMap       = null;
    protected String packageBase    = "com.momathink";
    protected String srcFolder      = "src";
    protected String viewFolder     = "_view";
    protected String basePath       = "";
    
    public JfGenerator setPackageBase(String packageBase){
        this.packageBase = packageBase;
        return this;
    }
    
    public JfGenerator setBasePath(String basePath){
        this.basePath = basePath;
        return this;
    }
    
    public JfGenerator setSrcFolder(String srcFolder){
        this.srcFolder = srcFolder;
        return this;
    }
    
    public JfGenerator setViewFolder(String viewFolder){
        this.viewFolder = viewFolder;
        return this;
    }
    
    protected class DataGenerator extends DataDictionaryGenerator {
        public DataGenerator(DataSource dataSource, String dataDictionaryOutputDir) {
            super(dataSource, dataDictionaryOutputDir);
        }
        public void rebuildColumnMetas(List<TableMeta> tableMetas) {
            super.rebuildColumnMetas(tableMetas);
        }
    };
    
    public TableMeta getTableMeta(String tableName){
        if( tablemetaMap == null ){
            
            DataSource dataSource = _JFinalDemoGenerator.getDataSource();
            
            MetaBuilder metaBuilder = new MetaBuilder(dataSource);
            metaBuilder.setDialect(new MysqlDialect());
            //metaBuilder.addExcludedTable(_JFinalDemoGenerator.excludedTable);
            List<TableMeta> tableMetas = metaBuilder.build();
            new DataGenerator(dataSource, null).rebuildColumnMetas(tableMetas);
            
            if (tableMetas.size() == 0) {
                System.out.println("TableMeta 数量为 0,不生成任何文件");
                return null;
            }
            Kv kv = Kv.create();
            for (TableMeta tableMeta : tableMetas) {
                kv.set(tableMeta.name, tableMeta);
            }
            tablemetaMap = kv;
        }
        return (TableMeta) tablemetaMap.get(tableName);
    }
    
    /**
     * 生成手脚架代码
     */
    public JfGenerator allRender(String className, String tableName) {
        return javaRender(className, tableName).htmlRender(className, tableName);
    }
    
    /**
     * java 代码生成
     * */
    public JfGenerator javaRender(String className, String tableName) {
        //刷新 映射对象
        _JFinalDemoGenerator.main(null);
        
        controller(className);
        validator(className);
        service(className , tableName);
        return this;
    }
    
    private String toClassNameSmall(String className) {
        return new StringBuffer(className.substring(0, 1).toLowerCase()).append(className.substring(1)).toString();
    }
    
    private String toPackages(String className) {
        return new StringBuffer(packageBase).append(".").append(basePath)
                .append(".").append(className.toLowerCase()).toString();
    }
    
    /**
     * 生成Controller
     * @param className         类名称
     */
    public void controller(String className){
        String packages = toPackages(className);
        
        String classNameSmall = toClassNameSmall(className);
        
        jfEngine.render("/java/controller.html", 
                Kv.by("package", packages)
                .set("className", className)
                .set("classNameSmall", classNameSmall)
                .set("basePath", basePath )
                , 
                new StringBuilder()
                .append(System.getProperty("user.dir"))
                .append("/")
                .append(srcFolder)
                .append("/")
                .append(packages.replace(".", "/"))
                .append("/")
                .append(className)
                .append("Controller.java")
                );
    }
    
    /**
     * 生成validator
     * @param className         类名称
     */
    public void validator(String className){
        String packages = toPackages(className);
        
        String classNameSmall = toClassNameSmall(className);
        
        jfEngine.render("/java/validator.html", 
                Kv.by("package", packages)
                .set("className", className)
                .set("classNameSmall", classNameSmall)
                , 
                new StringBuilder()
                .append(System.getProperty("user.dir"))
                .append("/")
                .append(srcFolder)
                .append("/")
                .append(packages.replace(".", "/"))
                .append("/")
                .append(className)
                .append("Validator.java")
                );
    }
    
    /**
     * 生成Service
     * @param className         类名称
     * @param tableName         表名
     */
    public void service(String className, String tableName){
        String packages = toPackages(className);

        String classNameSmall = toClassNameSmall(className);
        
        jfEngine.render("/java/service.html", 
                Kv.by("package", packages)
                .set("className", className)
                .set("classNameSmall", classNameSmall)
                .set("tableName", tableName)
                , 
                new StringBuilder()
                .append(System.getProperty("user.dir"))
                .append("/")
                .append(srcFolder)
                .append("/")
                .append(packages.replace(".", "/"))
                .append("/")
                .append(className)
                .append("Service.java")
                );
    }
    
    /**
     * @param className 
     * @param tableName 
     * */
    public JfGenerator htmlRender(String className, String tableName){
        TableMeta tablemeta = getTableMeta(tableName);
        
        htmlList(className, tablemeta);
        
        return this;
    }
    
    //页面的生成一般定制比较多..就来个简单的吧
    
    public void htmlList(String className, TableMeta tablemeta){
        String packages = toPackages(className);
        String classNameSmall = toClassNameSmall(className);
        String basePathUrl = basePath.replace('.', '/');
        
        jfEngine.render("/html/list.html", 
                Kv.by("tablemeta", tablemeta)
                .set("package", packages)
                .set("className", className)
                .set("classNameSmall", classNameSmall)
                .set("basePath", basePathUrl )
                , 
                new StringBuilder()
                .append(PathKit.getWebRootPath())
                .append("/")
                .append(viewFolder)
                .append("/")
                .append(basePathUrl)
                .append("/")
                .append(classNameSmall)
                .append("/")
                .append(classNameSmall)
                .append("List.html")
                );
    }
    
    // ... 继续扩展吧~
    
    
}


3~  爽的不要不要~ 放两三个模版事例吧...  我这边的模版和业务关联的比较多了, 几乎没什么通用的了,,,, 自己业务扩展吧~

图片.png

package #(package);

import com.jfinal.aop.Before;
import com.jfinal.core.Controller;
import com.demo.common.model.#(className);

/**
 * #(className) 管理    
 * 描述:
 * 
 */
public class #(className)Controller extends Controller {

    //private static final Log log = Log.getLog(#(className)Controller.class);
    
    static #(className)Service srv = #(className)Service.me;
    
    /**
     * 列表
     * /#(basePath)/#(classNameSmall)/list
     */
    public void list() {
        setAttr("page", srv.paginate(getParaToInt("p", 1), 40));
        render("#(classNameSmall)List.html");
    }
    
    /**
     * 准备添加
     * /#(basePath)/#(classNameSmall)/add
     */
    public void add() {
        render("#(classNameSmall)Add.html");
    }
    
    /**
     * 保存
     * /#(basePath)/#(classNameSmall)/save
     */
    @Before({#(className)Validator.class})
    public void save() {
        srv.save(getModel(#(className).class));
        renderJson("isOk", true);
    }

    /**
     * 准备更新
     * /#(basePath)/#(classNameSmall)/edit
     */
    public void edit() {
        #(className) #(classNameSmall) = srv.findById(getParaToInt("id"));
        setAttr("#(classNameSmall)", #(classNameSmall));
        render("#(classNameSmall)Edit.html");
    }

    /**
     * 更新
     * /#(basePath)/#(classNameSmall)/update
     */
    @Before(#(className)Validator.class)
    public void update() {
        srv.update(getModel(#(className).class));
        renderJson("isOk", true);
    }

    /**
     * 查看
     * /#(basePath)/#(classNameSmall)/view
     */
    public void view() {
        #(className) #(classNameSmall) = srv.findById(getParaToInt("id"));
        setAttr("#(classNameSmall)", #(classNameSmall));
        render("#(classNameSmall)View.html");
    }
     
    /**
     * 删除
     * /#(basePath)/#(classNameSmall)/delete
     */
    public void delete() {
        srv.delete(getParaToInt("id"));
        renderJson("isOk", true);
    }
    
}
package #(package);

import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Page;
import com.demo.common.model.#(className);

/**
 * #(className) 管理    
 * 描述:
 */
public class #(className)Service {

    //private static final Log log = Log.getLog(#(className)Service.class);
    
    public static final #(className)Service me = new #(className)Service();
    private final #(className) dao = new #(className)().dao();
    
    
    /**
    * 列表-分页
    */
    public Page<#(className)> paginate(int pageNumber, int pageSize) {
        return dao.paginate(pageNumber, pageSize, "SELECT * ", "FROM #(tableName)");
    }
    
    /**
    * 保存
    */
    public void save(#(className) #(classNameSmall)) {
        #(classNameSmall).save();
    }
    
    /**
    * 更新
    */
    public void update(#(className) #(classNameSmall)) {
        #(classNameSmall).update();
    }
    
    /**
    * 查询
    */
    public #(className) findById(int #(classNameSmall)Id) {
        return dao.findFirst("select * from #(tableName) where id=?", #(classNameSmall)Id);
    }
    
    /**
    * 删除
    */
    public void delete(int #(classNameSmall)Id) {
        Db.update("delete from #(tableName) where id=?", #(classNameSmall)Id);
    }
    
    
}

// 其他模版就不放了, 自己扩展吧~~

再放个页面的吧 , 比较有代表性

/tpl/html/list.html

#("#")@adminLayout()
#("#")define main()
<div class="admin-content-box">
    <!-- 列表 -->
    <div class="jf-admin-panel-box">
        <div>
            <button class="layui-btn" onclick="showFancyBox('/#(basePath)/#(classNameSmall)/add">添加#(tablemeta.remarks)</button>
        </div>
        <table class="layui-table" lay-skin="line">
          <thead>
            <tr>
               #for(x : tablemeta.columnMetas)
              <th>#(x.remarks)</th>
            #end
              <th>操作</th>
            </tr>
          </thead>
          <tbody>
           #("#")for(x : page.list)
            <tr>
                #for(x : tablemeta.columnMetas)
                  <td>#("#")(x.#(x.name))</td>
                  #end
              <td>
                    <span onclick="showFancyBox('/#(basePath)/#(classNameSmall)/view?id=#("#")(x.id)')">查看</span>
                    <span onclick="showFancyBox('/#(basePath)/#(classNameSmall)/edit?id=#("#")(x.id)')">更新</span>
                    <span onclick="showFancyBox('/#(basePath)/#(classNameSmall)/delete?id=#("#")(x.id)')">删除</span>
              </td>
            </tr>
           #("#")end
          </tbody>
        </table>

        #("#")@paginate(accountPage.pageNumber, accountPage.totalPage, "/#(basePath)/#(classNameSmall)/list?p=")

    </div>

</div>
#("#")end

#("#")define css()

#("#")end

#("#")define js()

    <script type="text/javascript">

    </script>
#("#")end


这个功能包建在外面, 再Build Path进去, 算是可插拔哦~
图片.png

码云:
https://git.oschina.net/bean80/tpp.git


评论区

高达1234

2017-08-15 16:19

@杜福忠 这是什么语法啊?开源里有介绍吗?或者有什么使用方法的资料?

JFinal

2017-08-15 16:21

@高达1234 在本站首页右侧可以下载到 Enjoy 3.2 手册,内容很少,一会就看完了。表达式规则与 java 保持一致,所以学习成本很低

高达1234

2017-08-15 16:59

@JFinal 见到大神很亲切!多谢指点!

欲风217

2017-08-17 14:27

膜拜大神~

prq910

2017-09-25 15:24

极致

王业群

2017-12-18 14:03

今天闲着没事,想自己弄个简单的,没想到已经有现成的了,谢谢大神!!

小松

2018-01-04 16:46

大神,我现在以main 方法运行 生成的html中没有中文乱码,以controller的方式生成的html有中文乱码。

杜福忠

2018-01-04 19:14

@小松 首先确认编辑器(eclipse)的文本文件编码格式是UTF-8,
微信截图_20180104191000.png
其次确认项目的编码:
微信截图_20180104191202.png
最后确认Tomcat的编码:URIEncoding="UTF-8"
修改tomcat服务器下的conf文件夹下的service.xml文件。
需要修改的地方1:
URIEncoding="UTF-8" port="8009" protocol="AJP/1.3" redirectPort="8443"/>
需要修改的地方2:URIEncoding="UTF-8" connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>

小松

2018-01-05 09:08

还有个问题,我在本地以main方法执行时java文件,html都可以生成,以web的方式,controller 执行的时候java文件就生不成了。

杜福忠

2018-01-05 09:20

@小松 这些代码生成的原理都是渲染文本,然后保存文本的时候,文件名为.java了而已, 所以你那个“不能生成”应该是生成到其他的位置去了, 你可以试试把生成的地址先写死,指定到某个文件夹下面,再看看。 因为如果是其他的错误如文件夹权限等, 那你的代码生成时早都报错了

小松

2018-01-05 09:27

@杜福忠 感谢回复,我这边用的是IDEA 编码设置的都是UTF-8,tomcat的编码也设置为UTF-8,html中仍然有中文乱码。

杜福忠

2018-01-05 10:02

@小松 最粗暴的方法:在其他编辑打开(正常的), 然后复制,再粘贴到你的IDEA中打开相应文件,把乱码的覆盖掉。。。

小松

2018-01-05 11:18

@杜福忠 嗯,以web的方式,它生成到别的地方了,System.getProperty("user.dir") ,它指到tomcat下的bin目录里了。

小松

2018-01-05 16:26

@杜福忠 这种办法简单,粗暴,就是不太灵活。

xupengjifnal

2018-02-09 17:42

@小松 我遇到跟你一样的问题了,在controller下生成的代码是乱码的,System.getProperty("user.dir") 这个路径我写死就乱码了

杜福忠

2018-02-09 17:48

@xupengjifnal 打个断点,追踪一下,看是什么时候乱码的,环境都确认好是否UTF-8

xupengjifnal

2018-02-09 18:26

@杜福忠 乱码问题解决了哦,要用fileoutputstream来设置编码方式

moooy

2018-04-11 14:59

搞事情啊~~

np

2018-05-03 14:09

@JFinal 大神,metaBuilder.setDialect(new OracleDialect());改成oracle连接方式,提示流已关闭怎么回事

15901451417

2018-06-27 14:32

利害!

bobotianxia

2019-04-12 17:20

这个controller.html有使用吗?

minggxu9

2019-11-28 08:51

好东西要顶的

杜福忠

2019-11-28 09:22

@minggxu9 好东西:复制粘贴 《 代码生成 《 通用模板

上面的代码,如果用JF新版本, 还有很多优化的地方,只是提供一个思路了

热门分享

扫码入社