成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

動手搭建后端框架-Velocity模板引擎的應(yīng)用

villainhr / 3104人閱讀

摘要:目錄建造者模式應(yīng)用。其實(shí)不用也可以,因?yàn)椴皇呛軓?fù)雜,只是為了復(fù)習(xí)一下所學(xué)過的設(shè)計模式知識目錄工廠模式應(yīng)用。

為了提高開發(fā)效率,通常會想辦法把一些模式固定的重復(fù)性的勞動抽取出來,以后再使用的時候,拿來主義就可以了。這樣既可以提高開發(fā)效率,又降低了出錯的風(fēng)險。

這一思想在我們的日常工作中可以說隨處可見,我們完成一項(xiàng)復(fù)雜的工程,并不需要面面俱到什么都自己寫,我們完全可以利用第三方的jar包讓我們達(dá)到事半功倍的效果,比如經(jīng)常使用的apche的commons-lang3包。再比如java中的繼承、我們自己封裝的工具類等等。 另外一方面,對于源碼文件,如果公司有成熟的框架,我們的開發(fā)都是遵循著框架制定的約定來進(jìn)行開發(fā)的,我們在創(chuàng)建某一個業(yè)務(wù)的控制層、業(yè)務(wù)層、持久層的時候,實(shí)際上有相當(dāng)一部分的工作是重復(fù)的。

那么對于源碼文件的編寫我們能否偷偷懶呢?答案肯定是可以的,我們可以利用模板引擎技術(shù),將不變的部分寫在模板文件中,將可變的部分作為變量傳遞到模板引擎的上下文中,最終生成我們想要的源碼文件。

模板引擎的產(chǎn)品有很多,比如前端模板artTemplate、后端模板Velocity、FreeMarker等 本文以Velocity為例,總結(jié)一下它在實(shí)戰(zhàn)中的應(yīng)用

1.基礎(chǔ)知識

搭建過程涉及到的基礎(chǔ)知識包括:Maven、Velocity、工廠模式、建造者模式、單元測試
對于基礎(chǔ)不熟悉的同學(xué),建議看一下下面的兩篇文章
Velocity基礎(chǔ)
Velocity語法摘要

2.搭建工程 2.1模塊目錄

代碼生成功能,在我設(shè)計的后臺框架中,作為一個獨(dú)立的模塊存在,使用Maven構(gòu)建。
builder目錄:建造者模式應(yīng)用。由于代表表結(jié)構(gòu)的Table實(shí)體稍顯復(fù)雜,因此使用了建造者模式構(gòu)建Table對象。其實(shí)不用也可以,因?yàn)門able不是很復(fù)雜,只是為了復(fù)習(xí)一下所學(xué)過的設(shè)計模式知識
factory目錄:工廠模式應(yīng)用。在構(gòu)建源碼文件的時候,由于涉及到了Controller、Service、Dao、Domain這幾種類型的文件,因此針對不同類型的文件,要使用其對應(yīng)的處理類,因此使用了工廠模式
handler目錄:生成源文件的核心代碼
model目錄:在生成domain的時候,由于字段需要從數(shù)據(jù)庫中的表中讀取,因此構(gòu)造了與表對應(yīng)的實(shí)體類方便處理
utils目錄:工具類
Generator.java:程序主文件,調(diào)用入口
test目錄:單元測試

.
├── generator.iml
├── pom.xml
└── src
    ├── main
    │?? ├── java
    │?? │?? └── com
    │?? │??     └── wt
    │?? │??         └── master
    │?? │??             └── generator
    │?? │??                 ├── Generator.java
    │?? │??                 ├── builder
    │?? │??                 │?? ├── MySqlTableBuilder.java
    │?? │??                 │?? └── TableBuilder.java
    │?? │??                 ├── factory
    │?? │??                 │?? └── GeneratorFactory.java
    │?? │??                 ├── handler
    │?? │??                 │?? ├── BaseGenerator.java
    │?? │??                 │?? ├── ControllerGeneratorHandler.java
    │?? │??                 │?? ├── DomainGeneratorHandler.java
    │?? │??                 │?? ├── MapperGeneratorHandler.java
    │?? │??                 │?? └── ServiceGeneratorHandler.java
    │?? │??                 ├── model
    │?? │??                 │?? └── Table.java
    │?? │??                 └── util
    │?? │??                     ├── JdbcUtils.java
    │?? │??                     ├── SpringContextUtils.java
    │?? │??                     ├── TableColumnUtils.java
    │?? │??                     └── TableInfoUtils.java
    │?? └── resources
    │??     ├── config
    │??     │?? ├── applicationContext.xml
    │??     │?? └── db.properties
    │??     └── template
    │??         ├── controller.java.vm
    │??         ├── dao.java.vm
    │??         ├── domain.java.vm
    │??         ├── service.java.vm
    │??         └── serviceimpl.java.vm
    └── test
        └── com.wt.master.generator
            └── GeneratorTest.java
2.2引入依賴


    
        j2ee
        com.wt.master
        1.0-SNAPSHOT
        ../version/
    
    4.0.0

    generator
    
        
        
            org.apache.velocity
            velocity
            1.7
        
        
        
            junit
            junit
            4.12
            test
        
        
            com.wt.master
            core
            1.0-SNAPSHOT
        
        
        
            com.mchange
            c3p0
            0.9.5.4
        
    
3.核心代碼 3.1模板文件的定義

以controller層生成模板為例
將不變的部分直接寫到.vm文件中
將模板文件中,有可能發(fā)生變化的部分,抽取為變量,變量的值從VelocityContext中獲取
在Velocity架構(gòu)中,有一個上下文的定義,通過上下文,程序?qū)⒆兞糠湃肷舷挛膶ο笾?。而模板從上下文中獲取對應(yīng)變量的值,獲取的方式是${變量名},關(guān)于Velocity模板文件中的語法,參見上文提到的兩篇文章

package ${packagePath}.controller;

import ${packagePath}.domain.${moduleName};
import ${packagePath}.service.${moduleName}Service;
import com.wt.master.core.base.BaseController;
import com.wt.master.core.helper.QueryHelper;
import com.wt.master.core.request.HttpResultEntity;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * ${moduleNameCN}控制器
 *
 * @author
 * @date
 */
@Api(value = "${moduleNameCN}控制器", tags = "${moduleName}Controller", description = "${moduleNameCN}控制器" )
@RestController
@RequestMapping("/${moduleName}" )
@Slf4j
public class ${moduleName}Controller extends BaseController<${moduleName}, ${moduleName}Service> {
    @Autowired
    private ${moduleName}Service ${lowerModuleName}Service;

    @Override
    protected ${moduleName}Service getService() {
        return ${lowerModuleName}Service;
    }

}
3.2工廠類定義

根據(jù)源碼文件類型的不同,定義了不同的處理類,通過工廠模式返回對應(yīng)的處理類

package com.wt.master.generator.factory;

import com.wt.master.generator.Generator;
import com.wt.master.generator.handler.*;

/**
 * 生成器工廠
 *
 * @author [email protected]
 * @date Jun 18, 2019 at 4:02:23 PM
 */
public class GeneratorFactory {
    public static BaseGenerator create(Generator.GenerateItem item) {
        BaseGenerator baseGenerator = null;
        switch (item) {
            case service:
                baseGenerator = new ServiceGeneratorHandler();
                break;
            case controller:
                baseGenerator = new ControllerGeneratorHandler();
                break;
            case mapper:
                baseGenerator = new MapperGeneratorHandler();
                break;
            case domain:
                baseGenerator = new DomainGeneratorHandler();
                break;
            default:
                baseGenerator = new ControllerGeneratorHandler();
        }
        return baseGenerator;
    }
}
3.3源碼生成處理類定義

以controller處理類為例
定義抽象類,作為基類
定義了抽象方法generate,生成源碼文件的處理方法
定義了抽象方法getFilePath,獲取生成文件的路徑
方法的實(shí)現(xiàn)由具體的實(shí)現(xiàn)類來實(shí)現(xiàn)

package com.wt.master.generator.handler;

import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.runtime.RuntimeConstants;
import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintWriter;

/**
 * 生成器抽象
 *
 * @author [email protected]
 * @date May 12, 2019 at 10:44:53 AM
 */
public abstract class BaseGenerator {
    /**
     * 生成代碼
     *
     * @param tableName    表名
     * @param moduleName   模塊英文名
     * @param moduleNameCN 模塊中文名
     * @param packagePath  包路徑
     * @return
     */
    public abstract BaseGenerator generate(String tableName, String moduleName, String moduleNameCN,
                                           String packagePath);

    /**
     * 生成文件路徑
     * @param packagePath
     * @return
     */
    public abstract String getFilePath(String packagePath,String moduleName);

    /**
     * 獲取 模板
     *
     * @param templateName 模板文件名稱
     * @return
     */
    Template getTemplate(String templateName) {
        VelocityEngine ve = new VelocityEngine();
        ve.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath" );
        ve.setProperty("classpath.resource.loader.class", ClasspathResourceLoader.class.getName());
        ve.setProperty("input.encoding","utf-8");
        ve.setProperty("output.encoding","utf-8");
        ve.init();
        Template t = ve.getTemplate("/template/" + templateName);
        return t;
    }

    protected void merge(Template template, VelocityContext ctx, String path) {
        File file = new File(path);
        if(!file.exists()){
            new File(file.getParent()).mkdirs();
        }else{
            System.out.println("替換文件"+file.getAbsolutePath());
        }

        PrintWriter writer = null;
        try {
            writer = new PrintWriter(path);
            template.merge(ctx, writer);
            writer.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {
            writer.close();
        }
    }

    /**
     * 獲得根目錄
     * @return
     */
    protected String getRootPath(){
        String rootPath = "";
        try {
            File file = new File(BaseGenerator.class.getResource("/").getFile());
            rootPath = file.getParent();
            rootPath = java.net.URLDecoder.decode(rootPath.substring(0, rootPath.indexOf("target") - 1), "utf-8");
            return rootPath+"/src/main/java";
        } catch (Exception e) {
            e.printStackTrace();
        }
        return rootPath;
    }

    /**
     * 轉(zhuǎn)換包路徑為文件路徑
     * @param packagePath
     * @return
     */
    protected String convertPackagePathToFilePath(String packagePath){
        StringBuilder path = new StringBuilder();
        path.append("/" );
        path.append(packagePath.replace(".", "/" ));
        path.append("/");
        return path.toString();
    }

}
3.4工具類的定義

該類主要是獲取表的信息及對應(yīng)的字段信息

package com.wt.master.generator.util;

import com.wt.master.generator.model.Table;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.util.CollectionUtils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 表操作類
 *
 * @author [email protected]
 * @date Apr 23, 2019 at 11:36:30 PM
 */
public class TableInfoUtils {

    public static final String JDBC_TEMPLATE = "jdbcTemplate";

    public static Table getTableColumnList(String tableName) {
        JdbcTemplate jdbcTemplate = (JdbcTemplate) SpringContextUtils.getBean(JDBC_TEMPLATE);

        List> tableInfo = jdbcTemplate.queryForList(getTableStructureSql(tableName));
        if (CollectionUtils.isEmpty(tableInfo)) {
            throw new RuntimeException("表:" + tableName + "不存在" );
        }

        List> columns = jdbcTemplate.queryForList(getColumnStructureSql(tableName));

        return TableColumnUtils.convertToColumn(columns, tableInfo.get(0));
    }

    /**
     * 獲取查詢表字段屬性的SQL
     *
     * @param tableName 表名
     * @return
     */
    private static String getColumnStructureSql(String tableName) {
        StringBuilder sql = new StringBuilder();
        sql.append("select column_name, data_type,column_comment,column_key " );
        sql.append("from information_schema.columns " );
        sql.append("where table_name = "" + tableName + """ );
        return sql.toString();
    }

    /**
     * 獲取表的信息
     * @param tableName
     * @return
     */
    private static String getTableStructureSql(String tableName) {
        StringBuilder sql = new StringBuilder();
        sql.append("select table_name,table_comment " );
        sql.append("from information_schema.tables " );
        sql.append("where table_name= "" + tableName + """ );
        return sql.toString();
    }


}
3.5應(yīng)用入口

代用create方法來生成源碼文件

package com.wt.master.generator;

import com.wt.master.generator.builder.MySqlTableBuilder;
import com.wt.master.generator.builder.TableBuilder;
import com.wt.master.generator.factory.GeneratorFactory;
import com.wt.master.generator.handler.BaseGenerator;
import com.wt.master.generator.model.Table;
import com.wt.master.generator.util.TableInfoUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.util.Assert;

import java.util.List;

/**
 * 代碼生成工具
 *
 * @author [email protected]
 * @date Apr 23, 2019 at 10:41:51 PM
 */
public class Generator {

    /**
     * 生成代碼入口
     *
     * @param tableName    表名
     * @param moduleName   模塊英文名
     * @param moduleNameCN 模塊中文名
     * @param packagePath  打包路徑
     * @param item         生成項(xiàng)目
     */
    public static void create(String tableName, String moduleName, String moduleNameCN, String packagePath,
                              GenerateItem... item) {
        if (StringUtils.isBlank(tableName) || StringUtils.isBlank(moduleName) || StringUtils.isBlank(moduleNameCN) || StringUtils.isBlank(packagePath)) {
            throw new IllegalArgumentException("參數(shù)非法!" );
        }

        for (GenerateItem generateItem : item) {
            BaseGenerator baseGenerator = GeneratorFactory.create(generateItem);
            baseGenerator.generate(tableName, moduleName, moduleNameCN, packagePath);
        }
    }


    public enum GenerateItem {
        controller, service, mapper, domain
    }

}
4.單元測試
package com.wt.master.generator;

import org.junit.Test;
import org.junit.Before;
import org.junit.After;

/**
 * Generator Tester.
 *
 * @author 
 * @version 1.0
 * @since 
Jun 18, 2019
*/ public class GeneratorTest { @Test public void testCreate() throws Exception { //TODO: Test goes here... Generator.create("SecurityRoleT", "SecurityRole", "角色管理", "com.wt.common.security", Generator.GenerateItem.controller, Generator.GenerateItem.service, Generator.GenerateItem.mapper, Generator.GenerateItem.domain); } }

源碼github地址

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/77841.html

相關(guān)文章

  • 結(jié)合Spring發(fā)送郵件四種正確姿勢,你知道幾種?

    摘要:我拿網(wǎng)易郵箱賬號舉例子,那么我們?nèi)绾尾拍茏屇愕泥]箱賬號可以利用第三方發(fā)送郵件這里的第三方就是我們即將編寫的程序。 一 前言 測試所使用的環(huán)境 測試使用的環(huán)境是企業(yè)主流的SSM 框架即 SpringMVC+Spring+Mybatis。為了節(jié)省時間,我直接使用的是我上次的SSM項(xiàng)目中整合Echarts開發(fā)該項(xiàng)目已經(jīng)搭建完成的SSM環(huán)境。 標(biāo)題說的四種姿勢指的是哪四種姿勢? 發(fā)送text...

    doodlewind 評論0 收藏0
  • Java 程序員必備 15 個框架,前 3 個地位無可動搖!

    摘要:官網(wǎng)源碼推薦從開始手寫一個框架更多請?jiān)诩夹g(shù)棧微信公眾號后臺回復(fù)關(guān)鍵字。是一個開放源代碼的對象關(guān)系映射框架,它對進(jìn)行了非常輕量級的對象封裝,它將與數(shù)據(jù)庫表建立映射關(guān)系,是一個全自動的框架。 Java 程序員方向太多,且不說移動開發(fā)、大數(shù)據(jù)、區(qū)塊鏈、人工智能這些,大部分 Java 程序員都是 Java Web/后端開發(fā)。那作為一名 Java Web 開發(fā)程序員必須需要熟悉哪些框架呢? 今天...

    galaxy_robot 評論0 收藏0
  • 工具集核心教程 | 第四篇: Velocity模板引擎入門到進(jìn)階

    摘要:是一個基于的模板引擎。模板中未被定義的變量將被認(rèn)為是一個字符串。公眾號回復(fù)全棧,領(lǐng)取前端,,產(chǎn)品經(jīng)理,微信小程序,等資源合集大放送。公眾號回復(fù)面試,領(lǐng)取面試實(shí)戰(zhàn)學(xué)習(xí)資源。 Velocity是一個基于java的模板引擎(template engine)。它允許任何人僅僅簡單的使用模板語言(template language)來引用由java代碼定義的對象。 當(dāng)Velocity應(yīng)用于web...

    leon 評論0 收藏0
  • 5分鐘搭建私人Java博客系統(tǒng)——Tale

    摘要:你只需要花分鐘,就能擁有一個屬于自己的私人博客了,并且可以對整個項(xiàng)目有一個完成的概念和感覺。指令和相似,表達(dá)式和保持一致,易學(xué)易用。 本文適合剛學(xué)習(xí)完 Java 語言基礎(chǔ)的人群,跟著本文可了解和運(yùn)行 Tale 項(xiàng)目。示例均在 Windows 操作系統(tǒng)下演示 showImg(https://segmentfault.com/img/bVbwsbo?w=1578&h=868); 本文作者:...

    null1145 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<