jeesite快速开发平台(七)—-代码生成原理

jeesite快速开发平台(七)—-代码生成原理

一、原理讲解


jeesite代码生成用的是FreeMarker模板引擎结合xml技术来实现的,定义的模板都放在resources/templates/modules/gen下


jeesite快速开发平台(七)----代码生成原理


一看就知道crud就是基本的增删改查,dao是数据库操作,treetable是有关树方面的模板,其中主要的配置文件就是config.xml,该文件中定义了生成的模板,以及java类型,查询类型,字段显示类型等一些数据。

<?xml version="1.0" encoding="utf-8"?>

<config>

<!-- 生成分类 -->

<category>

<category value="curd" label="增删改查(单表)">

<template>curd/controller.xml</template>

<template>curd/service.xml</template>

<template>category-ref:dao</template>

<template>curd/viewForm.xml</template>

<template>curd/viewList.xml</template>

</category>

<category value="curd_many" label="增删改查(一对多)">

<template>curd/controller.xml</template>

<template>curd/serviceMany.xml</template>

<template>category-ref:dao</template>

<template>curd/viewFormMany.xml</template>

<template>curd/viewList.xml</template>

<childTable>

<template>category-ref:dao</template>

</childTable>

</category>

<category value="dao" label="仅持久层(dao/entity/mapper)">

<template>dao/dao.xml</template>

<template>dao/entity.xml</template>

<template>dao/mapper.xml</template>

</category>

<category value="treeTable" label="树结构表(一体)">

<template>treetable/controller.xml</template>

<template>treetable/service.xml</template>

<template>treetable/dao.xml</template>

<template>treetable/entity.xml</template>

<template>treetable/mapper.xml</template>

<template>treetable/viewForm.xml</template>

<template>treetable/viewList.xml</template>

</category>

<category value="treeTableAndList" label="树结构表(左树右表)">

<template>category-ref:dao</template>

</category>

</category>

<!-- java类型 -->

<javaType>

<dict value="String" label="String"/>

<dict value="Long" label="Long"/>

<dict value="Integer" label="Integer"/>

<dict value="Double" label="Double"/>

<dict value="java.util.Date" label="Date"/>

<dict value="com.thinkgem.jeesite.modules.sys.entity.User" label="User"/>

<dict value="com.thinkgem.jeesite.modules.sys.entity.Office" label="Office"/>

<dict value="com.thinkgem.jeesite.modules.sys.entity.Area" label="Area"/>

<dict value="This" label="ThisObj" description="生成当前对象"/>

<dict value="Custom" label="Custom" description="自定义对象,生成后手动设置"/>

</javaType>

<!-- 查询类型 -->

<queryType>

<dict value="=" label="="/>

<dict value="!=" label="!="/>

<dict value=">" label=">"/>

<dict value=">=" label=">="/>

<dict value="<" label="<"/>

<dict value="<=" label="<="/>

<dict value="between" label="Between"/>

<dict value="like" label="Like"/>

<dict value="left_like" label="Left Like"/>

<dict value="right_like" label="Right Like"/>

</queryType>

<!-- 字段显示类型 -->

<showType>

<dict value="input" label="单行文本"/>

<dict value="textarea" label="多行文本"/>

<dict value="select" label="下拉选项"/>

<dict value="radiobox" label="单选按钮"/>

<dict value="checkbox" label="复选框"/>

<dict value="dateselect" label="日期选择"/>

<dict value="userselect" label="人员选择"/>

<dict value="officeselect" label="部门选择"/>

<dict value="areaselect" label="区域选择"/>

<dict value="treeselect" label="树选择控件"/>

<dict value="fileselect" label="文件上传选择"/>

</showType>

</config>


其中

<childTable>

<template>category-ref:dao</template>

</childTable>

定义了子表,初看jeesite的代码生成,有个困惑的地方就是,一般通过FreeMarker进行代码生成定义的模板都是ftl格式的,而这里却是xml,什么鬼,难道这里不是用FreeMarker进行生成的??我们先来看下xml文件中的内容就清楚了:

<?xml version="1.0" encoding="utf-8"?>

<template>

<name>controller</name>

<filePath>src/main/java/${packageName}/${moduleName}/web/${subModuleName}</filePath>

<fileName>${ClassName}Controller.java</fileName>

<content><![CDATA[

/**

* Copyright &copy; 2012-2016 <a href="https://github.com/thinkgem/jeesite">JeeSite</a> All rights reserved.

*/

package ${packageName}.${moduleName}.web<#if subModuleName != "">.${subModuleName}</#if>;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import org.apache.shiro.authz.annotation.RequiresPermissions;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Controller;

import org.springframework.ui.Model;

import org.springframework.web.bind.annotation.ModelAttribute;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RequestParam;

import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import com.thinkgem.jeesite.common.config.Global;

import com.thinkgem.jeesite.common.persistence.Page;

import com.thinkgem.jeesite.common.web.BaseController;

import com.thinkgem.jeesite.common.utils.StringUtils;

import ${packageName}.${moduleName}.entity<#if subModuleName != "">.${subModuleName}</#if>.${ClassName};

import ${packageName}.${moduleName}.service<#if subModuleName != "">.${subModuleName}</#if>.${ClassName}Service;

/**

* ${functionName}Controller

* @author ${functionAuthor}

* @version ${functionVersion}

*/

@Controller

@RequestMapping(value = "${r"${adminPath}"}/${urlPrefix}")

public class ${ClassName}Controller extends BaseController {

@Autowired

private ${ClassName}Service ${className}Service;

@ModelAttribute

public ${ClassName} get(@RequestParam(required=false) String id) {

${ClassName} entity = null;

if (StringUtils.isNotBlank(id)){

entity = ${className}Service.get(id);

}

if (entity == null){

entity = new ${ClassName}();

}

return entity;

}

@RequiresPermissions("${permissionPrefix}:view")

@RequestMapping(value = {"list", ""})

public String list(${ClassName} ${className}, HttpServletRequest request, HttpServletResponse response, Model model) {

Page<${ClassName}> page = ${className}Service.findPage(new Page<${ClassName}>(request, response), ${className});

model.addAttribute("page", page);

return "${lastPackageName}/${viewPrefix}List";

}

@RequiresPermissions("${permissionPrefix}:view")

@RequestMapping(value = "form")

public String form(${ClassName} ${className}, Model model) {

model.addAttribute("${className}", ${className});

return "${lastPackageName}/${viewPrefix}Form";

}

@RequiresPermissions("${permissionPrefix}:edit")

@RequestMapping(value = "save")

public String save(${ClassName} ${className}, Model model, RedirectAttributes redirectAttributes) {

if (!beanValidator(model, ${className})){

return form(${className}, model);

}

${className}Service.save(${className});

addMessage(redirectAttributes, "保存${functionNameSimple}成功");

return "redirect:"+Global.getAdminPath()+"/${viewPrefix}/?repage";

}

@RequiresPermissions("${permissionPrefix}:edit")

@RequestMapping(value = "delete")

public String delete(${ClassName} ${className}, RedirectAttributes redirectAttributes) {

${className}Service.delete(${className});

addMessage(redirectAttributes, "删除${functionNameSimple}成功");

return "redirect:"+Global.getAdminPath()+"/${viewPrefix}/?repage";

}

}]]>

</content>

</template>


其中的xml格式为:

<?xml version="1.0" encoding="utf-8"?>

<template>

<name>controller</name>

<filePath>src/main/java/${packageName}/${moduleName}/web/${subModuleName}</filePath>

<fileName>${ClassName}Controller.java</fileName>

<content><![CDATA[]]>

</content>

</template>

发现其中的奥秘没,他把模板内容都放在了content标签的CDATA[]区。而且config.xml有相对应的bean,用来实现xml转对象:


/**

* 生成方案Entity

* @author ThinkGem

* @version 2013-10-15

*/

@XmlRootElement(name="config")

public class GenConfig implements Serializable {

private static final long serialVersionUID = 1L;

private List<GenCategory> categoryList; // 代码模板分类

private List<Dict> javaTypeList; // Java类型

private List<Dict> queryTypeList; // 查询类型

private List<Dict> showTypeList; // 显示类型

public GenConfig() {

super();

}

@XmlElementWrapper(name = "category")

@XmlElement(name = "category")

public List<GenCategory> getCategoryList() {

return categoryList;

}

public void setCategoryList(List<GenCategory> categoryList) {

this.categoryList = categoryList;

}

@XmlElementWrapper(name = "javaType")

@XmlElement(name = "dict")

public List<Dict> getJavaTypeList() {

return javaTypeList;

}

public void setJavaTypeList(List<Dict> javaTypeList) {

this.javaTypeList = javaTypeList;

}

@XmlElementWrapper(name = "queryType")

@XmlElement(name = "dict")

public List<Dict> getQueryTypeList() {

return queryTypeList;

}

public void setQueryTypeList(List<Dict> queryTypeList) {

this.queryTypeList = queryTypeList;

}

@XmlElementWrapper(name = "showType")

@XmlElement(name = "dict")

public List<Dict> getShowTypeList() {

return showTypeList;

}

public void setShowTypeList(List<Dict> showTypeList) {

this.showTypeList = showTypeList;

}

}


其中的

private List<GenCategory> categoryList; // 代码模板分类

private List<Dict> javaTypeList; // Java类型

private List<Dict> queryTypeList; // 查询类型

private List<Dict> showTypeList; // 显示类型


对应的就是xml中预先定义好的

<?xml version="1.0" encoding="utf-8"?>

<config>

<!-- 生成分类 -->

<category>

<category value="curd" label="增删改查(单表)">

<template>curd/controller.xml</template>

....

</category>

<category value="curd_many" label="增删改查(一对多)">

<template>curd/controller.xml</template>

....

<childTable>

<template>category-ref:dao</template>

</childTable>

</category>

<category value="dao" label="仅持久层(dao/entity/mapper)">

<template>dao/dao.xml</template>

....

</category>

<category value="treeTable" label="树结构表(一体)">

<template>treetable/controller.xml</template>

....

</category>

<category value="treeTableAndList" label="树结构表(左树右表)">

<template>category-ref:dao</template>

</category>

</category>

<!-- java类型 -->

<javaType>

<dict value="String" label="String"/>

....

</javaType>

<!-- 查询类型 -->

<queryType>

<dict value="=" label="="/>

....

</queryType>

<!-- 字段显示类型 -->

<showType>

<dict value="input" label="单行文本"/>

<dict value="textarea" label="多行文本"/>

....

</showType>

</config>

其中的代码模板分类

jeesite快速开发平台(七)----代码生成原理

通过@XmlElement(name = “category”)引用了GenCategory类,其中定义了主子模板

/**

* 生成方案Entity

* @author ThinkGem

* @version 2013-10-15

*/

@XmlRootElement(name="category")

public class GenCategory extends Dict {

private static final long serialVersionUID = 1L;

private List<String> template; // 主表模板

private List<String> childTableTemplate;// 子表模板

public static String CATEGORY_REF = "category-ref:";

public GenCategory() {

super();

}

@XmlElement(name = "template")

public List<String> getTemplate() {

return template;

}

public void setTemplate(List<String> template) {

this.template = template;

}

@XmlElementWrapper(name = "childTable")

@XmlElement(name = "template")

public List<String> getChildTableTemplate() {

return childTableTemplate;

}

public void setChildTableTemplate(List<String> childTableTemplate) {

this.childTableTemplate = childTableTemplate;

}

}


这两个主子其实对应的就是

jeesite快速开发平台(七)----代码生成原理

在GenUtils中通过getConfig()方法可获取转换成bean的对象

jeesite快速开发平台(七)----代码生成原理

而其中的数据就是在配置业务表是初始化的一些数据,比如当我们选择某一张表时,然后点击下一步


jeesite快速开发平台(七)----代码生成原理


就会调用GenTableController中的form方法,把一些配置参数设置进去


jeesite快速开发平台(七)----代码生成原理

然后在genTableForm.jsp页面进行渲染

<%@ page contentType="text/html;charset=UTF-8" %>

<%@ include file="/WEB-INF/views/include/taglib.jsp"%>

<html>

<head>

<title>业务表管理</title>

<meta name="decorator" content="default"/>

<script type="text/javascript">

$(document).ready(function() {

$("#comments").focus();

$("#inputForm").validate({

submitHandler: function(form){

loading('正在提交,请稍等...');

$("input[type=checkbox]").each(function(){

$(this).after("<input type=\"hidden\" name=\""+$(this).attr("name")+"\" value=\""

+($(this).attr("checked")?"1":"0")+"\"/>");

$(this).attr("name", "_"+$(this).attr("name"));

});

form.submit();

},

errorContainer: "#messageBox",

errorPlacement: function(error, element) {

$("#messageBox").text("输入有误,请先更正。");

if (element.is(":checkbox")||element.is(":radio")||element.parent().is(".input-append")){

error.appendTo(element.parent().parent());

} else {

error.insertAfter(element);

}

}

});

});

</script>

</head>

<body>

<ul class="nav nav-tabs">

<li><a href="${ctx}/gen/genTable/">业务表列表</a></li>

<li class="active"><a href="${ctx}/gen/genTable/form?id=${genTable.id}&name=${genTable.name}">业务表<shiro:hasPermission name="gen:genTable:edit">${not empty genTable.id?'修改':'添加'}</shiro:hasPermission><shiro:lacksPermission name="gen:genTable:edit">查看</shiro:lacksPermission></a></li>

</ul>

<c:choose>

<c:when test="${empty genTable.name}">

<form:form id="inputForm" modelAttribute="genTable" action="${ctx}/gen/genTable/form" method="post" class="form-horizontal">

<form:hidden path="id"/>

<sys:message content="${message}"/>

<br/>

<div class="control-group">

<label class="control-label">表名:</label>

<div class="controls">

<form:select path="name" class="input-xxlarge">

<form:options items="${tableList}" itemLabel="nameAndComments" itemValue="name" htmlEscape="false"/>

</form:select>

</div>

<div class="form-actions">

<input id="btnSubmit" class="btn btn-primary" type="submit" value="下一步"/> 

<input id="btnCancel" class="btn" type="button" value="返 回" onclick="history.go(-1)"/>

</div>

</div>

</form:form>

</c:when>

<c:otherwise>

<form:form id="inputForm" modelAttribute="genTable" action="${ctx}/gen/genTable/save" method="post" class="form-horizontal">

<form:hidden path="id"/>

<sys:message content="${message}"/>

<fieldset>

<legend>基本信息</legend>

<div class="control-group">

<label class="control-label">表名:</label>

<div class="controls">

<form:input path="name" htmlEscape="false" maxlength="200" class="required" readonly="true"/>

</div>

</div>

<div class="control-group">

<label class="control-label">说明:</label>

<div class="controls">

<form:input path="comments" htmlEscape="false" maxlength="200" class="required"/>

</div>

</div>

<div class="control-group">

<label class="control-label">类名:</label>

<div class="controls">

<form:input path="className" htmlEscape="false" maxlength="200" class="required"/>

</div>

</div>

<div class="control-group">

<label class="control-label">父表表名:</label>

<div class="controls">

<form:select path="parentTable" cssClass="input-xlarge">

<form:option value=""></form:option>

<form:options items="${tableList}" itemLabel="nameAndComments" itemValue="name" htmlEscape="false"/>

</form:select>

 当前表外键:

<form:select path="parentTableFk" cssClass="input-xlarge">

<form:option value=""></form:option>

<form:options items="${genTable.columnList}" itemLabel="nameAndComments" itemValue="name" htmlEscape="false"/>

</form:select>

<span class="help-inline">如果有父表,请指定父表表名和外键</span>

</div>

</div>

<div class="control-group hide">

<label class="control-label">备注:</label>

<div class="controls">

<form:textarea path="remarks" htmlEscape="false" rows="4" maxlength="200" class="input-xxlarge"/>

</div>

</div>

<legend>字段列表</legend>

<div class="control-group">

<table id="contentTable" class="table table-striped table-bordered table-condensed">

<thead><tr>

<th title="数据库字段名">列名</th>

<th title="默认读取数据库字段备注">说明</th>

<th title="数据库中设置的字段类型及长度">物理类型</th>

<th title="实体对象的属性字段类型">Java类型</th>

<th title="实体对象的属性字段(对象名.属性名|属性名2|属性名3,例如:用户user.id|name|loginName,属性名2和属性名3为Join时关联查询的字段)">Java属性名称 <i class="icon-question-sign"></i></th>

<th title="是否是数据库主键">主键</th><th title="字段是否可为空值,不可为空字段自动进行空值验证">可空</th><th title="选中后该字段被加入到insert语句里">插入</th>

<th title="选中后该字段被加入到update语句里">编辑</th><th title="选中后该字段被加入到查询列表里">列表</th>

<th title="选中后该字段被加入到查询条件里">查询</th><th title="该字段为查询字段时的查询匹配放松">查询匹配方式</th>

<th title="字段在表单中显示的类型">显示表单类型</th><th title="显示表单类型设置为“下拉框、复选框、点选框”时,需设置字典的类型">字典类型</th><th>排序</th></tr></thead>

<tbody>

<c:forEach items="${genTable.columnList}" var="column" varStatus="vs">

<tr${column.delFlag eq '1'?' class="error" title="已删除的列,保存之后消失!"':''}>

<td nowrap>

<input type="hidden" name="columnList[${vs.index}].id" value="${column.id}"/>

<input type="hidden" name="columnList[${vs.index}].delFlag" value="${column.delFlag}"/>

<input type="hidden" name="columnList[${vs.index}].genTable.id" value="${column.genTable.id}"/>

<input type="hidden" name="columnList[${vs.index}].name" value="${column.name}"/>${column.name}

</td>

<td>

<input type="text" name="columnList[${vs.index}].comments" value="${column.comments}" maxlength="200" class="required" style="width:100px;"/>

</td>

<td nowrap>

<input type="hidden" name="columnList[${vs.index}].jdbcType" value="${column.jdbcType}"/>${column.jdbcType}

</td>

<td>

<select name="columnList[${vs.index}].javaType" class="required input-mini" style="width:85px;*width:75px">

<c:forEach items="${config.javaTypeList}" var="dict">

<option value="${dict.value}" ${
dict.value==column.javaType?'selected':''} title="${dict.description}">
${dict.label}</option>

</c:forEach>

</select>

</td>

<td>

<input type="text" name="columnList[${vs.index}].javaField" value="${column.javaField}" maxlength="200" class="required input-small"/>

</td>

<td>

<input type="checkbox" name="columnList[${vs.index}].isPk" value="1" ${
column.isPk eq '1' ? 'checked' : ''}/>

</td>

<td>

<input type="checkbox" name="columnList[${vs.index}].isNull" value="1" ${
column.isNull eq '1' ? 'checked' : ''}/>

</td>

<td>

<input type="checkbox" name="columnList[${vs.index}].isInsert" value="1" ${
column.isInsert eq '1' ? 'checked' : ''}/>

</td>

<td>

<input type="checkbox" name="columnList[${vs.index}].isEdit" value="1" ${
column.isEdit eq '1' ? 'checked' : ''}/>

</td>

<td>

<input type="checkbox" name="columnList[${vs.index}].isList" value="1" ${
column.isList eq '1' ? 'checked' : ''}/>

</td>

<td>

<input type="checkbox" name="columnList[${vs.index}].isQuery" value="1" ${
column.isQuery eq '1' ? 'checked' : ''}/>

</td>

<td>

<select name="columnList[${vs.index}].queryType" class="required input-mini">

<c:forEach items="${config.queryTypeList}" var="dict">

<option value="${fns:escapeHtml(dict.value)}" ${
fns:escapeHtml(dict.value)==column.queryType?'selected':''} title="${dict.description}">
${fns:escapeHtml(dict.label)}</option>

</c:forEach>

</select>

</td>

<td>

<select name="columnList[${vs.index}].showType" class="required" style="width:100px;">

<c:forEach items="${config.showTypeList}" var="dict">

<option value="${dict.value}" ${
dict.value==column.showType?'selected':''} title="${dict.description}">
${dict.label}</option>

</c:forEach>

</select>

</td>

<td>

<input type="text" name="columnList[${vs.index}].dictType" value="${column.dictType}" maxlength="200" class="input-mini"/>

</td>

<td>

<input type="text" name="columnList[${vs.index}].sort" value="${column.sort}" maxlength="200" class="required input-min digits"/>

</td>

</tr>

</c:forEach>

</tbody>

</table>

</div>

</fieldset>

<div class="form-actions">

<shiro:hasPermission name="gen:genTable:edit"><input id="btnSubmit" class="btn btn-primary" type="submit" value="保 存"/> </shiro:hasPermission>

<input id="btnCancel" class="btn" type="button" value="返 回" onclick="history.go(-1)"/>

</div>

</form:form>

</c:otherwise>

</c:choose>

</body>

</html>


注意其中的name属性

name="columnList[${vs.index}].xxx"

在GenTable中是用list来装的

jeesite快速开发平台(七)----代码生成原理


所以在spring mvc数据绑定的时候可以通过下标的形式来传值


jeesite快速开发平台(七)----代码生成原理


业务表配置好之后,就是生成代码,新建生成方案配置,然后输入一些必须的信息


jeesite快速开发平台(七)----代码生成原理


点击保存并生成代码,会调用GenSchemeController中的save()方法,传入一些参数


jeesite快速开发平台(七)----代码生成原理


然后调用genSchemeService.save()方法进行生成


jeesite快速开发平台(七)----代码生成原理


如果是1的话就生成代码


jeesite快速开发平台(七)----代码生成原理


generateCode方法如下:

private String generateCode(GenScheme genScheme){

StringBuilder result = new StringBuilder();

// 查询主表及字段列

GenTable genTable = genTableDao.get(genScheme.getGenTable().getId());

genTable.setColumnList(genTableColumnDao.findList(new GenTableColumn(new GenTable(genTable.getId()))));

// 获取所有代码模板

GenConfig config = GenUtils.getConfig();

// 获取模板列表

List<GenTemplate> templateList = GenUtils.getTemplateList(config, genScheme.getCategory(), false); //获取所有不包含childTableTemplateList的数据

List<GenTemplate> childTableTemplateList = GenUtils.getTemplateList(config, genScheme.getCategory(), true);

// 如果有子表模板,则需要获取子表列表

if (childTableTemplateList.size() > 0){

GenTable parentTable = new GenTable();

parentTable.setParentTable(genTable.getName());

genTable.setChildList(genTableDao.findList(parentTable));

}

// 生成子表模板代码

for (GenTable childTable : genTable.getChildList()){

childTable.setParent(genTable);

childTable.setColumnList(genTableColumnDao.findList(new GenTableColumn(new GenTable(childTable.getId()))));

genScheme.setGenTable(childTable);

Map<String, Object> childTableModel = GenUtils.getDataModel(genScheme);

for (GenTemplate tpl : childTableTemplateList){

result.append(GenUtils.generateToFile(tpl, childTableModel, genScheme.getReplaceFile()));

}

}

// 生成主表模板代码

genScheme.setGenTable(genTable);

Map<String, Object> model = GenUtils.getDataModel(genScheme);

for (GenTemplate tpl : templateList){

result.append(GenUtils.generateToFile(tpl, model, genScheme.getReplaceFile()));

}

return result.toString();

}

该方法主要是做一些,获取模板,然后进行数据绑定等一些工作。其中的

// 获取模板列表

List<GenTemplate> templateList = GenUtils.getTemplateList(config, genScheme.getCategory(), false); //获取所有不包含childTableTemplateList的数据

List<GenTemplate> childTableTemplateList = GenUtils.getTemplateList(config, genScheme.getCategory(), true);

getTemplateList方法为

/**

* 根据分类获取模板列表

* @param config

* @param category

* @param isChildTable 是否是子表

* @return

*/

public static List<GenTemplate> getTemplateList(GenConfig config, String category, boolean isChildTable){

List<GenTemplate> templateList = Lists.newArrayList();

if (config !=null && config.getCategoryList() != null && category != null){

for (GenCategory e : config.getCategoryList()){

if (category.equals(e.getValue())){

List<String> list = null;

if (!isChildTable){

list = e.getTemplate();

}else{

list = e.getChildTableTemplate();

}

if (list != null){

for (String s : list){

if (StringUtils.startsWith(s, GenCategory.CATEGORY_REF)){

templateList.addAll(getTemplateList(config, StringUtils.replace(s, GenCategory.CATEGORY_REF, ""), false));

}else{

GenTemplate template = fileToObject(s, GenTemplate.class);

if (template != null){

templateList.add(template);

}

}

}

}

break;

}

}

}

return templateList;

}

通过标志位来获取

if (!isChildTable){

list = e.getTemplate();

}else{

list = e.getChildTableTemplate();

}

主表,子表模板,
生成文件的方法是GenUtils.generateToFile(tpl, model, genScheme.getReplaceFile())

/**

* 生成到文件

* @param tpl

* @param model

* @param isReplaceFile

* @return

*/

public static String generateToFile(GenTemplate tpl, Map<String, Object> model, boolean isReplaceFile){

// 获取生成文件

String fileName = Global.getProjectPath() + File.separator

+ StringUtils.replaceEach(FreeMarkers.renderString(tpl.getFilePath() + "/", model),

new String[]{"//", "/", "."}, new String[]{File.separator, File.separator, File.separator})

+ FreeMarkers.renderString(tpl.getFileName(), model);

logger.debug(" fileName === " + fileName);

// 获取生成文件内容

String content = FreeMarkers.renderString(StringUtils.trimToEmpty(tpl.getContent()), model);

logger.debug(" content === \r\n" + content);

// 如果选择替换文件,则删除原文件

if (isReplaceFile){

FileUtils.deleteFile(fileName);

}

// 创建并写入文件

if (FileUtils.createFile(fileName)){

FileUtils.writeToFile(fileName, content, true);

logger.debug(" file create === " + fileName);

return "生成成功:"+fileName+"<br/>";

}else{

logger.debug(" file extents === " + fileName);

return "文件已存在:"+fileName+"<br/>";

}

}


生成成功之后,会有如下提示:

jeesite快速开发平台(七)----代码生成原理



版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/101307.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 软件项目管理考前复习资料[通俗易懂]

    软件项目管理考前复习资料[通俗易懂]第一章.软件项目管理概述1.实现项目目标的制约因素有:项目范围成本进度计划客户满意度2.项目管理包括:启动过程组计划过程组执行过程组控制过程组收尾过程组3.什么是项目:为了创造一个唯一的产品或者提供一个唯一的服务而进行的临时性的努力,所以说项目具有临时性特性4.过程管理就是对过程进行管理,目的是要让过程能够被共享,复用,并得到持续的改进5.项目与日常运作的…

  • 数据结构与算法学习笔记

    本文是王争老师的《算法与数据结构之美》的学习笔记,详细内容请看王争的专栏。有不懂的地方指出来,我做修改。数据结构与算法思维导图数据结构指的是“一组数据的存储结构”,算法指的是“操作数据的一组方法”。数据结构是为算法服务的,算法是要作用再特定的数据结构上的。最常用的数据结构预算法:数据结构:数组、链表、栈、队列、散列表、二叉树‘、堆、跳表、图、Tire树 算法:递归…

  • 数组截取数据slice()函数「建议收藏」

    数组截取数据slice()函数「建议收藏」JavaScriptslice()方法定义和用法slice()方法可从已有的数组中返回选定的元素。语法arrayObject.slice(start,end)参数描述start 必需。规定从何处开始选取。如果是负数,那么它规定从数组尾部开始算起的位置。也就是说,-1指最后一个元素,-2指倒数第二个元素,以此类推。end 可选。 必需。规定从何处结束选取。该参数是数组片断结束处的数组下标。如果没有指定该参数,那么切分的数组包含从start到数组结束的所

  • [驱动注册]platform_driver_register()与platform_device_register()「建议收藏」

    [驱动注册]platform_driver_register()与platform_device_register()「建议收藏」[驱动注册]platform_driver_register()与platform_device_register()     设备与驱动的两种绑定方式:在设备注册时进行绑定及在驱动注册时进行绑定。以一个USB设备为例,有两种情形:(1)先插上USB设备并挂到总线中,然后在安装USB驱动程序过程中从总线上遍历各个设备,看驱动程序是否与其相匹配,如果匹配就将两者邦定。这就是p

  • 图解MySQL 内连接、外连接、左连接、右连接、全连接……太多了

    图解MySQL 内连接、外连接、左连接、右连接、全连接……太多了用两个表(a_table、b_table),关联字段a_table.a_id和b_table.b_id来演示一下MySQL的内连接、外连接(左(外)连接、右(外)连接、全(外)连接)。MySQL版本:Serverversion:5.6.31MySQLCommunityServer(GPL)数据库表:a_table、b_table主题:内连接、左连接(左外连

  • linux抓包命令tcpdump保存到wireshark_tcpdump抓包命令举例

    linux抓包命令tcpdump保存到wireshark_tcpdump抓包命令举例一,tcpdump-ilo-s0-n-nn-w/tmp/12345.pcaptcpandport12345注:tcpdump:抓包命令-ilo:抓取lo网卡的数据包(回环网口的包)-s0:从每个分组中读取最开始的snaplen个字节,后面可以跟数字指定截取多少个字节,0是指截取所有。(防止包截断)-nnn:以数字显示主机及端口,不解析主机名…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号