一直都想写一套自动生成代码的小工具,也没顾上,年后趁着空闲的时间整理了一下。本项目是基于springboot+jpa+freemarker+hui的框架。hui可以百度一下了解一下 官网地址:hui
1.引入pom。
<!-- freemarker 依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<!-- spring data jpa -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
2.field 属性类,此类存放属性的详细信息 用来存储model类需要的数据
import com.application.base.jpa.condition.MatchType;
/**
* @author fpb
* @description 属性类
* @date 2019/2/14.
*/
public class Field {
//字段名
private String fieldName;
//字段类型
private String fieldType;
//字段注释
private String fieldRemarks;
//字段名首字母大写
private String fieldNameUpperFirstLetter;
//是否是查询字段 true:是查询字段
private boolean queryFlag;
//查询管理 查询条件拼接 例如:= like < >等等
private MatchType matchType;
public Field() {
}
public Field(String fieldName, String fieldType, String fieldRemarks, boolean queryFlag, MatchType matchType) {
this.fieldName = fieldName;
this.fieldType = fieldType;
this.fieldRemarks = fieldRemarks;
this.fieldNameUpperFirstLetter = Generator.upperFirstLetter(fieldName);
this.queryFlag = queryFlag;
this.matchType = matchType;
}
public String getFieldName() {
return fieldName;
}
public void setFieldName(String fieldName) {
this.fieldName = fieldName;
}
public String getFieldType() {
return fieldType;
}
public void setFieldType(String fieldType) {
this.fieldType = fieldType;
}
public String getFieldRemarks() {
return fieldRemarks;
}
public void setFieldRemarks(String fieldRemarks) {
this.fieldRemarks = fieldRemarks;
}
public String getFieldNameUpperFirstLetter() {
return fieldNameUpperFirstLetter;
}
public void setFieldNameUpperFirstLetter(String fieldNameUpperFirstLetter) {
this.fieldNameUpperFirstLetter = fieldNameUpperFirstLetter;
}
public boolean isQueryFlag() {
return queryFlag;
}
public void setQueryFlag(boolean queryFlag) {
this.queryFlag = queryFlag;
}
public MatchType getMatchType() {
return matchType;
}
public void setMatchType(MatchType matchType) {
this.matchType = matchType;
}
}
3.MatchType类 此类是一个数据查询关系的枚举类。服务于查询条件
package com.application.base.jpa.condition;
/**
* @author fpb
* @description
* @date 2019/1/25.
*/
public enum MatchType {
//下面四个用于Number类型的比较
gt, // filed > value
ge, // field >= value
lt, // field < value
le, // field <= value
equal, // filed = value
notEqual, // field != value
like, // field like value
notLike, // field not like value
//下面四个用于可比较类型(Comparable)的比较
greaterThan, // field > value
greaterThanOrEqualTo, // field >= value
lessThan, // field < value
lessThanOrEqualTo // field <= value
}
4.MyClass类 此类包含了创建java文件需要的属性信息。
package com.application.generator;
import java.util.Date;
import java.util.List;
/**
* @author fpb
* @description 实体类
* @date 2019/2/14.
*/
public class MyClass {
//类名
private String className;
//类中文名称
private String chinaName;
//model类所在的包名
private String modelPackageName;
//repository类所在的包名
private String repositoryPackageName;
//Controller所在的包名
private String controllerPackageName;
//字段的集合
private List<Field> fieldList;
//创建人
private String author;
//创建日期
private Date date;
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
public List<Field> getFieldList() {
return fieldList;
}
public void setFieldList(List<Field> fieldList) {
this.fieldList = fieldList;
}
public String getModelPackageName() {
return modelPackageName;
}
public void setModelPackageName(String modelPackageName) {
this.modelPackageName = modelPackageName;
}
public String getRepositoryPackageName() {
return repositoryPackageName;
}
public void setRepositoryPackageName(String repositoryPackageName) {
this.repositoryPackageName = repositoryPackageName;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public String getControllerPackageName() {
return controllerPackageName;
}
public void setControllerPackageName(String controllerPackageName) {
this.controllerPackageName = controllerPackageName;
}
public String getChinaName() {
return chinaName;
}
public void setChinaName(String chinaName) {
this.chinaName = chinaName;
}
}
5. Generator类
/**
* @author fpb
* @description
* @date 2019/2/14.
*/
public class Generator {
//首字母大写
public static String upperFirstLetter(String src){
String firstLetter = src.substring(0, 1).toUpperCase();
String otherLetters = src.substring(1);
return firstLetter + otherLetters;
}
//首字母小写
public static String lowerFirstLetter(String src){
String firstLetter = src.substring(0, 1).toLowerCase();
String otherLetters = src.substring(1);
return firstLetter + otherLetters;
}
//表名转类名
public static String tableNameToClassName(String tableName){
StringBuilder className = new StringBuilder();
//aa_bb_cc AaBbCc
String[] split = tableName.split("_");
for (String item : split) {
className.append(upperFirstLetter(item));
}
return className.toString();
}
}
6.ColDef类 此类是为了生成前端列表页服务
/**
* @author fpb
* @description
* @date 2019/2/14.
*/
public class ColDef {
//列名称
private String title;
//字段
private String field;
//自定义
private boolean selfdefine;
public ColDef() {
}
public ColDef(String title, boolean selfdefine) {
this.title = title;
this.selfdefine = selfdefine;
}
public ColDef(String title, String field, boolean selfdefine) {
this.title = title;
this.field = field;
this.selfdefine = selfdefine;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getField() {
return field;
}
public void setField(String field) {
this.field = field;
}
public boolean isSelfdefine() {
return selfdefine;
}
public void setSelfdefine(boolean selfdefine) {
this.selfdefine = selfdefine;
}
}
7.FreemarkerDemo类 此类是生成代码的核心
package com.application.generator;
import com.alibaba.fastjson.JSON;
import com.application.base.jpa.condition.MatchType;
import com.application.util.DateUtil;
import freemarker.template.Configuration;
import freemarker.template.Template;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import java.io.*;
import java.util.*;
/**
* @author fpb
* @description
* @date 2019/2/14.
*/
public class FreemarkerDemo {
//模板路径
private static final String TEMPLATE_PATH = "src/main/resources/templates/ftl/generator";
public static void main(String[] args) {
//json格式栗子 matchType参考包com.application.base.jpa.condition下的matchType枚举类
/*[{
"MODEL_CLASS_PATH": "src/main/java/com/application/model/other",
"REPOSITORY_CLASS_PATH": "src/main/java/com/application/repository/other",
"CONTROLLER_CLASS_PATH": "src/main/java/com/application/controller/other",
"VIEW_FILE_PATH": "src/main/resources/templates/",
"tableName": "new_content",
"chinaName": "新闻",
"author": "fpb",
"fields": [{
"fieldName": "id",
"fieldType": "Long",
"fieldRemarks": "主键",
"queryFlag": true,
"matchType": "equal"
}, {
"fieldName": "name",
"fieldType": "String",
"fieldRemarks": "姓名",
"queryFlag": true,
"matchType": "like"
}, {
"fieldName": "age",
"fieldType": "Integer",
"fieldRemarks": "年龄",
"queryFlag": false,
"matchType": "equal"
}]
}]*/
String json="[{\"MODEL_CLASS_PATH\":\"src/main/java/com/application/model/other\",\"REPOSITORY_CLASS_PATH\":\"src/main/java/com/application/repository/other\",\"CONTROLLER_CLASS_PATH\":\"src/main/java/com/application/controller/other\",\"VIEW_FILE_PATH\":\"src/main/resources/templates/\",\"tableName\":\"new_content\",\"chinaName\":\"新闻\",\"author\":\"fpb\",\"fields\":[{\"fieldName\":\"id\",\"fieldType\":\"Long\",\"fieldRemarks\":\"主键\",\"queryFlag\":true,\"matchType\":\"equal\"},{\"fieldName\":\"name\",\"fieldType\":\"String\",\"fieldRemarks\":\"姓名\",\"queryFlag\":true,\"matchType\":\"like\"},{\"fieldName\":\"age\",\"fieldType\":\"Integer\",\"fieldRemarks\":\"年龄\",\"queryFlag\":false,\"matchType\":\"equal\"}]}]";
generatorWithJson(json);
}
/**
* 根据JSON生成代码文件
* @param json
*/
public static void generatorWithJson(String json){
JSONArray jsonArray=JSONArray.fromObject(json);
for(int i=0;i<jsonArray.size();i++){
JSONObject jsonObject = jsonArray.getJSONObject(i);
generatorWithJSONObject(jsonObject);
}
}
/**
* 传递参数
* @param jsonObject
*/
public static void generatorWithJSONObject(JSONObject jsonObject){
//model类java文件生成路径
String MODEL_CLASS_PATH =jsonObject.getString("MODEL_CLASS_PATH");
//repository类java文件生成路径
String REPOSITORY_CLASS_PATH =jsonObject.getString("REPOSITORY_CLASS_PATH");
//controller类java文件生成路径
String CONTROLLER_CLASS_PATH =jsonObject.getString("CONTROLLER_CLASS_PATH");
//页面路径
String VIEW_FILE_PATH =jsonObject.getString("VIEW_FILE_PATH");
String tableName=jsonObject.getString("tableName");
MyClass myClass=new MyClass();
//根据表名生成类名
myClass.setClassName(Generator.tableNameToClassName(tableName));
//表中文名称
myClass.setChinaName(jsonObject.getString("chinaName"));
//作者
myClass.setAuthor(jsonObject.getString("author"));
//model包名
myClass.setModelPackageName(getPackageName(MODEL_CLASS_PATH));
//repository类包名
myClass.setRepositoryPackageName(getPackageName(REPOSITORY_CLASS_PATH));
//controller包名
myClass.setControllerPackageName(getPackageName(CONTROLLER_CLASS_PATH));
//日期
myClass.setDate(new Date());
//属性数组
JSONArray fieldsArray = jsonObject.getJSONArray("fields");
List<Field> fields=new ArrayList<>();
for(int i=0;i<fieldsArray.size();i++){
JSONObject fieldSONObject = fieldsArray.getJSONObject(i);
String fieldName = fieldSONObject.getString("fieldName");
String fieldType = fieldSONObject.getString("fieldType");
String fieldRemarks = fieldSONObject.getString("fieldRemarks");
boolean queryFlag = fieldSONObject.getBoolean("queryFlag");
String matchType = fieldSONObject.getString("matchType");
Field field=new Field(fieldName,fieldType,fieldRemarks,queryFlag,MatchType.valueOf(matchType));
fields.add(field);
}
myClass.setFieldList(fields);
//生成文件
generatorAllFile(tableName,myClass,MODEL_CLASS_PATH,REPOSITORY_CLASS_PATH,CONTROLLER_CLASS_PATH,VIEW_FILE_PATH);
}
/**
* 不采用json的方式 硬编码的方式
*/
public static void generatorWithCode(){
//model类java文件生成路径
String MODEL_CLASS_PATH ="src/main/java/com/application/model/other";
//repository类java文件生成路径
String REPOSITORY_CLASS_PATH ="src/main/java/com/application/repository/other";
//controller类java文件生成路径
String CONTROLLER_CLASS_PATH ="src/main/java/com/application/controller/other";
//页面路径
String VIEW_FILE_PATH ="src/main/resources/templates/";
String tableName="new_content";
MyClass myClass=new MyClass();
//根据表名生成类名
myClass.setClassName(Generator.tableNameToClassName(tableName));
//表中文名称
myClass.setChinaName("新闻");
//作者
myClass.setAuthor("fpb");
//model包名
myClass.setModelPackageName(getPackageName(MODEL_CLASS_PATH));
//repository类包名
myClass.setRepositoryPackageName(getPackageName(REPOSITORY_CLASS_PATH));
//controller包名
myClass.setControllerPackageName(getPackageName(CONTROLLER_CLASS_PATH));
//日期
myClass.setDate(new Date());
//字段
Field id=new Field("id","Long","主键",true, MatchType.equal);
Field name=new Field("name","String","姓名",true,MatchType.like);
Field age=new Field("age","Integer","年龄",false,MatchType.equal);
//字段集合
List<Field> fields=new ArrayList<>();
fields.add(id);
fields.add(name);
fields.add(age);
//将所有的字段放入myClass中
myClass.setFieldList(fields);
//生成文件
generatorAllFile(tableName,myClass,MODEL_CLASS_PATH,REPOSITORY_CLASS_PATH,CONTROLLER_CLASS_PATH,VIEW_FILE_PATH);
}
/**
* 生成所有的文件
* @param tableName 表名
* @param myClass 属性
* @param MODEL_CLASS_PATH model类java文件生成路径
* @param REPOSITORY_CLASS_PATH repository类java文件生成路径
* @param CONTROLLER_CLASS_PATH controller类java文件生成路径
* @param VIEW_FILE_PATH //页面文件生成路径
*/
public static void generatorAllFile(String tableName,MyClass myClass,String MODEL_CLASS_PATH,String REPOSITORY_CLASS_PATH,String CONTROLLER_CLASS_PATH,String VIEW_FILE_PATH){
Map<String, Object> dataMap = new HashMap();
//数据库表名称
dataMap.put("tableName", tableName);
//类名称
dataMap.put("className", myClass.getClassName());
//字段
dataMap.put("myClass", myClass);
//作者
dataMap.put("author", myClass.getAuthor());
//创建日期
dataMap.put("date", DateUtil.dateFormat(myClass.getDate(),"yyyy-MM-dd"));
//实体类名小写作为变量名称
dataMap.put("lowerClassName", Generator.lowerFirstLetter(myClass.getClassName()));
//描述
dataMap.put("description",myClass.getChinaName());
//生成model
generatorModel(tableName,myClass,MODEL_CLASS_PATH,dataMap);
//生成Repository
generatorRepository(tableName,myClass,REPOSITORY_CLASS_PATH,dataMap);
//生成Controller
generatorController(tableName,myClass,CONTROLLER_CLASS_PATH,dataMap);
//生成页面
//页面文件生成路径
String STATIC_FILE_PATH =VIEW_FILE_PATH+dataMap.get("lowerClassName");
//生成列表页
generatorListPage(myClass,STATIC_FILE_PATH,dataMap);
//生成添加修改页面
generatorAddPage(myClass,STATIC_FILE_PATH,dataMap);
}
/**
* @description 生成实体
* @param tableName 表明
* @param myClass 类参数
*/
public static void generatorModel(String tableName,MyClass myClass,String classPath,Map<String, Object> dataMap){
//package 包名
dataMap.put("package", myClass.getModelPackageName());
//生成代码
generator(dataMap,Generator.tableNameToClassName(tableName+".java"),"model.ftl",classPath);
}
/**
* @dexcription 生成Repository
* @param tableName
* @param myClass
*/
public static void generatorRepository(String tableName,MyClass myClass,String classPath,Map<String, Object> dataMap ){
//package 包名
dataMap.put("package", myClass.getRepositoryPackageName());
generator(dataMap,Generator.tableNameToClassName(tableName+"Repository.java"),"repository.ftl",classPath);
}
/**
* @dexcription 生成Controller
* @param tableName
* @param myClass
* @param classPath
*/
public static void generatorController(String tableName,MyClass myClass,String classPath,Map<String, Object> dataMap){
//package 包名
dataMap.put("package", myClass.getControllerPackageName());
generator(dataMap,Generator.tableNameToClassName(tableName+"Controller.java"),"controller.ftl",classPath);
}
/**
* 生成列表页
* @param myClass
* @param classPath
* @param dataMap
*/
public static void generatorListPage(MyClass myClass,String classPath,Map<String, Object> dataMap){
String listCol = getListCol(myClass);
dataMap.put("listCol",listCol);
dataMap.put("index",myClass.getFieldList().size());
generator(dataMap,"list"+dataMap.get("className")+".html","listModel.ftl",classPath);
}
/**
* 生成添加和修改页面
* @param myClass
* @param classPath
* @param dataMap
*/
public static void generatorAddPage(MyClass myClass,String classPath,Map<String, Object> dataMap){
generator(dataMap,"add"+dataMap.get("className")+".html","addModel.ftl",classPath);
}
/**
* 获得所有的列 返货json字符串
* @param myClass
* @return
*/
public static String getListCol(MyClass myClass){
List<Field> fieldList = myClass.getFieldList();
List<ColDef> colDefs=new ArrayList<>();
for(Field field:fieldList){
ColDef colDef=new ColDef(field.getFieldRemarks(),field.getFieldName(),false);
colDefs.add(colDef);
}
ColDef operator=new ColDef("操作",true);
colDefs.add(operator);
return JSON.toJSONString(colDefs);
}
/**
* 将文件路径转换成包名
* @param path
* @return
*/
public static String getPackageName(String path){
String com = path.substring(path.indexOf("com")).replace("/", ".");
return com;
}
public static void generator(Map<String, Object> dataMap,String fileName,String templateName,String classPath){
// step1 创建freeMarker配置实例
Configuration configuration = new Configuration(Configuration.getVersion());
Writer out = null;
try {
// step2 获取模版路径
configuration.setDirectoryForTemplateLoading(new File(TEMPLATE_PATH));
// step4 加载模版文件
Template template = configuration.getTemplate(templateName);
// step5 生成数据
File packagePath= new File(classPath);
if(!packagePath.exists()){
packagePath.mkdirs();
}
File docFile = new File(classPath + "\\" + fileName);
out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(docFile)));
// step6 输出文件
template.process(dataMap, out);
System.out.println(fileName+"文件创建成功 !");
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (null != out) {
out.flush();
}
} catch (Exception e2) {
e2.printStackTrace();
}
}
}
}
8.模板文件 model.ftl
package ${package};
import com.application.base.jpa.condition.MatchType;
import com.application.base.jpa.condition.QueryCondition;
import com.application.base.model.BaseModel;
import org.hibernate.annotations.GenericGenerator;
import org.springframework.data.jpa.domain.Specification;
import javax.persistence.*;
/**
* @author ${author}
* @description ${description}
* @date ${date}
*/
@Entity
@Table(name="${tableName}")
public class ${myClass.className} extends BaseModel{
<#list myClass.fieldList as field>
<#if field.fieldName=="id">
@Id
@GeneratedValue(generator = "snowFlakeId")
@GenericGenerator(name = "snowFlakeId", strategy = "com.application.base.utils.SnowflakeId")
</#if>
<#if field.queryFlag?string == "true" >
@QueryCondition(matchType =MatchType.${field.matchType})
</#if>
//${field.fieldRemarks}
private ${field.fieldType} ${field.fieldName};
</#list>
<#list myClass.fieldList as field>
public void set${field.fieldNameUpperFirstLetter}(${field.fieldType} ${field.fieldName}) {
this.${field.fieldName} = ${field.fieldName};
}
public ${field.fieldType} get${field.fieldNameUpperFirstLetter}() {
return ${field.fieldName};
}
</#list>
@Override
public Specification toSpec() {
return super.toSpecWithAnd();
}
}
9.模板文件 repository .ftl
package ${package};
import com.application.base.jpa.BaseRepository;
import ${myClass.modelPackageName}.${className};
/**
* @author ${author}
* @description ${description}
* @date ${date}
*/
public interface ${className}Repository extends BaseRepository<${className},Long> {
}
10.模板文件 controller .ftl
package ${package};
import ${myClass.modelPackageName}.${className};
import ${myClass.repositoryPackageName}.${className}Repository;
import com.application.util.PaginationUtil;
import com.application.util.ReturnMsg;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;
import java.util.Date;
/**
* @author ${author}
* @description ${description}
* @date ${date}
*/
@Controller
public class ${className}Controller {
@Autowired
private ${className}Repository ${lowerClassName}Repository;
/**
*列表页
*/
@GetMapping(value = "/${lowerClassName}")
public String list${className}(${className} ${lowerClassName},Integer pageNo, Integer pageSize, ModelMap map){
//排序
Sort sort=new Sort(Sort.Direction.DESC,"id");
//分页
Pageable pageable = new PageRequest(PaginationUtil.getPageNo(pageNo), PaginationUtil.getPageSize(pageSize),sort);
Page<${className}> page = ${lowerClassName}Repository.findAll(${lowerClassName}.toSpec(), pageable);
map.put("${lowerClassName}",${lowerClassName}==null?new ${className}():${lowerClassName});
PaginationUtil.putPageParam(map,page);
return "${lowerClassName}/list${className}";
}
/**
* 添加
* @param ${lowerClassName}
* @return
*/
@PostMapping("/${lowerClassName}")
@ResponseBody
public ReturnMsg add(${className} ${lowerClassName}){
Integer status=ReturnMsg.SUCCESS;
try{
${lowerClassName}.setCreateDate(new Date());
${lowerClassName}Repository.save(${lowerClassName});
}catch (Exception e){
status=ReturnMsg.FAIL;
}
return new ReturnMsg(status,"","");
}
@DeleteMapping("/${lowerClassName}/{id}")
@ResponseBody
public ReturnMsg delete(@PathVariable("id") Long id){
Integer status=ReturnMsg.SUCCESS;
try {
${lowerClassName}Repository.delete(id);
}catch (Exception e){
status=ReturnMsg.FAIL;
}
return new ReturnMsg(status,"","");
}
/**
* 跳转到添加页面
* @param ${lowerClassName}
* @param map
* @return
*/
@GetMapping("/${lowerClassName}/toAdd")
public String toAdd(${className} ${lowerClassName},ModelMap map){
if(${lowerClassName}!=null&&${lowerClassName}.getId()!=null){
${lowerClassName}=${lowerClassName}Repository.findOne(${lowerClassName}.getId());
}
map.put("_method","post");
map.put("${lowerClassName}",${lowerClassName});
return "${lowerClassName}/add${className}";
}
/**
* 跳转到更新页面
* @param id
* @param map
* @return
*/
@GetMapping("/${lowerClassName}/{id}")
public String toUpdate(@PathVariable("id") Long id, ModelMap map){
${className} ${lowerClassName} = ${lowerClassName}Repository.getOne(id);
map.put("${lowerClassName}",${lowerClassName});
map.put("_method","put");
return "${lowerClassName}/add${className}";
}
/**
* 更新
* @param ${lowerClassName}
* @return
*/
@PutMapping("/${lowerClassName}")
@ResponseBody
public ReturnMsg update(${className} ${lowerClassName}){
Integer status=ReturnMsg.SUCCESS;
try{
${lowerClassName}Repository.save(${lowerClassName});
}catch (Exception e){
status=ReturnMsg.FAIL;
}
return new ReturnMsg(status,"","");
}
}
11.模板文件 列表页模板listModel.ftl
<!DOCTYPE html>
<html lang="en">
<head>
${r'<#include "../ftl/backHeader.ftl" />'}
<link rel="stylesheet" type="text/css" href="/static/js/jquery-easyui/themes/bootstrap/easyui.css">
<link rel="stylesheet" type="text/css" href="/static/js/jquery-easyui/themes/icon.css">
<script type="text/javascript" src="/static/js/jquery-easyui/jquery.easyui.min.js"></script>
<script type="text/javascript" src="/static/js/jquery-easyui/locale/easyui-lang-zh_CN.js"></script>
<title>${myClass.chinaName}管理</title>
</head>
<body>
<div class="page-container">
<div class="text-c">
<form method="get" action="/${lowerClassName}" id="form-list">
<input type="hidden" name="pageNo" value="1" />
<input type="hidden" name="pageSize" value="${r'${pageSize}'}" />
ID:<input id="id" name="id" class="input-text" style="width:120px;" value="${r'${('}${lowerClassName}.id?c)!}" />
<input type="submit" value="查询" class="btn btn-success radius"/>
</form>
<div class="cl pd-5 bg-1 bk-gray mt-20"> <span class="l"><a href="javascript:;" onclick="open_full('添加${myClass.chinaName}','/${lowerClassName}/toAdd')" class="btn btn-primary radius"><i class="Hui-iconfont"></i> 添加${myClass.chinaName}</a></span> </div>
${r'<#assign cols='}${listCol}/>
${r'<@ciftable title="'}${myClass.chinaName}${r'管理" datas=data_list listAction='}'/${lowerClassName}' ${r'formId="form-list" tcols=cols totalcount=total_count;model,colindex>'}
${r'<#if colindex=='}${index}>
<a title="编辑" href="javascript:;" onclick="layer_show('编辑','/${lowerClassName}/${r'${model.id?c}'}','800','510')" class="ml-5" style="text-decoration:none"><i class="Hui-iconfont"></i></a>
<a title="删除" href="javascript:;" onclick="ajaxDelete('/${lowerClassName}/${r'${model.id?c}'}')" class="ml-5" style="text-decoration:none"><i class="Hui-iconfont"></i></a>
${r'</#if>
</@ciftable>'}
</div>
</div>
${r'<#include "../ftl/backFooter.ftl"/>'}
</body>
</html>
12.模板文件 列表页模板addModel.ftl
<!DOCTYPE html>
<html lang="en">
<head>
${r'<#include "../ftl/backHeader.ftl"/>'}
<title>添加(修改)${myClass.chinaName}</title>
</head>
<body>
<article class="page-container">
<form action="/${lowerClassName}" method="post" class="form form-horizontal" id="form-add">
<input type="hidden" name="id" value="${r'${('}${lowerClassName}.id?c)!}"/>
<#list myClass.fieldList as field>
<#if field.fieldName!="id">
<div class="row cl">
<label class="form-label col-xs-4 col-sm-3"><span class="c-red">*</span>${field.fieldRemarks}:</label>
<div class="formControls col-xs-8 col-sm-9">
<input id="${field.fieldName}" value="${r'${'}${lowerClassName}.${field.fieldName}!}" name="${field.fieldName}" type="text" class="input-text" style="width:240px;" placeholder="" >
</div>
</div>
</#if>
</#list>
<div class="row cl">
<div class="col-xs-8 col-sm-9 col-xs-offset-4 col-sm-offset-3">
<input class="btn btn-primary radius" type="button" onclick="ajaxSubmit('/${lowerClassName}','${r'${_method!}'}','form-add')" value=" 提交 ">
</div>
</div>
</form>
</article>
${r'<#include "../ftl/backFooter.ftl"/>'}
</body>
</html>
13.生成效果 基本的增删改查和分页功能均已实现