背景:由于項(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ù)
模板(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)生成枚舉類代碼的編寫啦