spring使用Freemarker自動(dòng)生成代碼(以生成枚舉類為例)

背景:由于項(xiàng)目需要筹淫,需要把csv表里的數(shù)據(jù)進(jìn)行處理后生成枚舉類萄唇,由于數(shù)據(jù)量較大此改,這就需要編寫一個(gè)自動(dòng)生成代碼的程序茫虽。

FreeMarker是一款模板引擎: 即一種基于模板和要改變的數(shù)據(jù)姓赤, 并用來(lái)生成輸出文本(HTML網(wǎng)頁(yè)赡译、電子郵件、配置文件不铆、源代碼等)的通用工具蝌焚。一般來(lái)說(shuō)裹唆,使用FreeMarker生成HTML頁(yè)面較為常用。模板編寫為FreeMarker Template Language (FTL)只洒。它是簡(jiǎn)單的许帐,專用的語(yǔ)言, 不是 像PHP那樣成熟的編程語(yǔ)言毕谴。 那就意味著要準(zhǔn)備數(shù)據(jù)在真實(shí)編程語(yǔ)言中來(lái)顯示成畦,比如數(shù)據(jù)庫(kù)查詢和業(yè)務(wù)運(yùn)算, 之后模板顯示已經(jīng)準(zhǔn)備好的數(shù)據(jù)析珊。在模板中羡鸥,你可以專注于如何展現(xiàn)數(shù)據(jù), 而在模板之外可以專注于要展示什么數(shù)據(jù)

image.png

模板(FTL編程)是由如下部分混合而成的:

  • 文本:文本會(huì)照著原樣來(lái)輸出忠寻。

  • 插值:這部分的輸出會(huì)被計(jì)算的值來(lái)替換惧浴。插值由 ${ and } 所分隔(或者 #{ and },這種風(fēng)格已經(jīng)不建議再使用了)奕剃;

  • FTL 標(biāo)簽:FTL標(biāo)簽和HTML標(biāo)簽很相似衷旅,但是它們卻是給FreeMarker的指示, 而且不會(huì)打印在輸出內(nèi)容中纵朋。

  • 注釋:注釋和HTML的注釋也很相似柿顶,但它們是由 <#---->來(lái)分隔的。注釋會(huì)被FreeMarker直接忽略操软, 更不會(huì)在輸出內(nèi)容中顯示嘁锯。

常用指令參考:
? if, else, elseif 進(jìn)行判斷

<#if condition>
  ...
<#elseif condition2>
  ...
<#elseif condition3>
  ...
...
<#else>
  ...
</#if>

? list, else, items, sep, break 進(jìn)行循環(huán)

<#list sequence>
   ....
    <#items as item>
        ....
    </#items>
    ....
<#else>
    ....
</#list>

?include 在你的模板中插入另外一個(gè) FreeMarker 模板文件 (由 path 參數(shù)指定)

<#include path>

<#include path options>

? switch, case, default, break

<#switch value>
  <#case refValue1>
    ...
    <#break>
  <#case refValue2>
    ...
    <#break>
  ...
  <#case refValueN>
    ...
    <#break>
  <#default>
    ...
</#switch>

本程序的目的是實(shí)現(xiàn)通過(guò)freemarker將csv中的數(shù)據(jù)轉(zhuǎn)為枚舉類并生成.java文件

首先添加依賴

        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
        </dependency>

.ftl文件如下 (需要放在resources/templates)

package ${package_name};

public enum ${enum_class_name}Enum {

<#if enum_list?exists>
    <#list enum_list as enum>
        ${enum.enumName}("${enum.fullName}","${enum.description}",${enum.dataType},${enum.section})<#if enum_index == ((enum_list?size) - 1)>;<#else >,</#if>
    </#list>
</#if>


    private String fullName;
    private String description;
    private DataType dataType;
    private Section section;



    ${enum_class_name}Enum(String fullName, String description, DataType dataType,Section section) {

    }



    public String getFullName() {
        return fullName;
    }

    public void setFullName(String fullName) {
        this.fullName = fullName;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public DataType getDataType() {
        return dataType;
    }

    public void setDataType(DataType dataType) {
        this.dataType = dataType;
    }
    
    public Section getSection() {
        return section;
    }
}

CSV生成枚舉類的主程序

/**
 * CSV轉(zhuǎn)枚舉類
 * created by lug on 2019/7/18.
 */
public class CSV2Enum {

    private static ReflectionFactory reflectionFactory = ReflectionFactory.getReflectionFactory();

    //枚舉需要生成到那個(gè)包下面
    private static String packageName = "com.enumerate";

    //枚舉類名稱
    private static String enumClassName = "name";
    //枚舉類生成后類上的注解
    private static String enumAnnotation = "枚舉類";
    //這里比較重要

    //類上的作者
    private static String AUTHOR = "Lug";
    //類上的日期
    private static String CURRENT_DATE = new SimpleDateFormat("yyyy-MM-dd").format(new Date());


    public static void main(String[] args) throws Exception {

       //我這里是把多個(gè)csv文件放到一個(gè)文件夾中并讀取的所有文件
        File file=new File("...");
        File[] files=file.listFiles();
        List<File> fileList=Arrays.asList(files);
        List<DataDomain> list=handleCSV(fileList); //將CSV文件存入list中
        generateEnumClassFile(list);
        System.out.println("執(zhí)行結(jié)束!");
    }

    public static void generateEnumClassFile(List<DataDomain> list) throws Exception{
        final String suffix = "Enum.java"; //后綴
        final String path = "D:\\" + suffix; //.java文件的地址
        final String templateName = "EnumClass.ftl"; //ftl文件的地址
        File mapperFile = new File(path);
        Map<String,Object> dataMap = new HashMap<>();

        dataMap.put("enum_list", list);
        generateFileByTemplate(templateName,mapperFile,dataMap);
    }

    public static void generateFileByTemplate(final String templateName,File file,Map<String,Object> dataMap) throws Exception{
        Template template = FreeMarkerTemplateUtils.getTemplate(templateName);
        FileOutputStream fos = new FileOutputStream(file);
        dataMap.put("author",AUTHOR);
        dataMap.put("date",CURRENT_DATE);
        dataMap.put("package_name",packageName);
        dataMap.put("enum_annotation",enumAnnotation);
        dataMap.put("enum_class_name",enumClassName);
        Writer out = new BufferedWriter(new OutputStreamWriter(fos, "utf-8"),10240);
        template.process(dataMap,out);
    }

    //CSV存入list中
    private static List<DataDomain> handleCSV(List<File> files) {
        //DataDomain是CSV文件對(duì)應(yīng)實(shí)體類聂薪,這個(gè)不多加贅述
        List<DataDomain> list = new ArrayList<>();
        BufferedReader br = null;
        for (File file:files
             ) {
            try {
                br = new BufferedReader(new FileReader(file));
                String[] line;
                while ((line = br.readLine().split(",")) != null) {
                          list.add(new DataDomain(line[0],line[1],line[2]))
                    }
            } catch (Exception e) {
            } finally {
                if (br != null) {
                    try {
                        br.close();
                        br = null;
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }

        return list;
    }

}

Freemarker配置類:

public class FreeMarkerTemplateUtils {
    private FreeMarkerTemplateUtils(){}
    private static final Configuration CONFIGURATION = new Configuration(Configuration.VERSION_2_3_22);

    static{
        //這里比較重要家乘,用來(lái)指定加載模板所在的路徑
        CONFIGURATION.setTemplateLoader(new ClassTemplateLoader(FreeMarkerTemplateUtils.class, "/templates"));
        CONFIGURATION.setDefaultEncoding("UTF-8");
        CONFIGURATION.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
        CONFIGURATION.setCacheStorage(NullCacheStorage.INSTANCE);
    }

    public static Template getTemplate(String templateName) throws IOException {
        try {
            return CONFIGURATION.getTemplate(templateName);
        } catch (IOException e) {
            throw e;
        }
    }

    public static void clearCache() {
        CONFIGURATION.clearTemplateCache();
    }

}

至此,就完成了自動(dòng)生成枚舉類代碼的編寫啦

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末藏澳,一起剝皮案震驚了整個(gè)濱河市仁锯,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌翔悠,老刑警劉巖业崖,帶你破解...
    沈念sama閱讀 219,539評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異蓄愁,居然都是意外死亡双炕,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評(píng)論 3 396
  • 文/潘曉璐 我一進(jìn)店門撮抓,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)妇斤,“玉大人,你說(shuō)我怎么就攤上這事√思茫” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 165,871評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵咽笼,是天一觀的道長(zhǎng)顷编。 經(jīng)常有香客問(wèn)我,道長(zhǎng)剑刑,這世上最難降的妖魔是什么媳纬? 我笑而不...
    開(kāi)封第一講書人閱讀 58,963評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮施掏,結(jié)果婚禮上钮惠,老公的妹妹穿的比我還像新娘。我一直安慰自己七芭,他們只是感情好素挽,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,984評(píng)論 6 393
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著狸驳,像睡著了一般预明。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上耙箍,一...
    開(kāi)封第一講書人閱讀 51,763評(píng)論 1 307
  • 那天撰糠,我揣著相機(jī)與錄音,去河邊找鬼辩昆。 笑死阅酪,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的汁针。 我是一名探鬼主播术辐,決...
    沈念sama閱讀 40,468評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼扇丛!你這毒婦竟也來(lái)了术吗?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤帆精,失蹤者是張志新(化名)和其女友劉穎较屿,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體卓练,經(jīng)...
    沈念sama閱讀 45,850評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡隘蝎,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,002評(píng)論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了襟企。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片嘱么。...
    茶點(diǎn)故事閱讀 40,144評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖顽悼,靈堂內(nèi)的尸體忽然破棺而出曼振,到底是詐尸還是另有隱情几迄,我是刑警寧澤,帶...
    沈念sama閱讀 35,823評(píng)論 5 346
  • 正文 年R本政府宣布冰评,位于F島的核電站映胁,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏甲雅。R本人自食惡果不足惜解孙,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,483評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望抛人。 院中可真熱鬧弛姜,春花似錦、人聲如沸妖枚。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 32,026評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)盅惜。三九已至中剩,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間抒寂,已是汗流浹背结啼。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,150評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留屈芜,地道東北人郊愧。 一個(gè)月前我還...
    沈念sama閱讀 48,415評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像井佑,于是被迫代替她去往敵國(guó)和親属铁。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,092評(píng)論 2 355