前文《jeesite代码生成器的使用(实例:报销表)》地址:http://blog.csdn.net/m0_38021128/article/details/68490920
前文中使用了jeesite框架的代码生成功能实现了一个小实例,但是实际上我对jeesite框架的了解还完全不够。
本文将从框架源码的角度对其进行分析理解。
路径:jeesite根目录\src\main\webapp\WEB-INF\views\modules\sys\sysindex.jsp
在eclipse中打开就可以看到首页的源代码了。
生成的实体类:com.thinkgem.jeesite.modules.sys.entity.Expenseclaimrecords
/**
* Copyright © 2012-2016 JeeSite All rights reserved.
*/
package com.thinkgem.jeesite.modules.sys.entity;
import org.hibernate.validator.constraints.Length;
import java.util.List;
import com.google.common.collect.Lists;
import com.thinkgem.jeesite.common.persistence.DataEntity;
/**
* 报销记录Entity
* @author seven
* @version 2017-04-07
*/
public class Expenseclaimrecords extends DataEntity<Expenseclaimrecords> {
private static final long serialVersionUID = 1L;
private String name; // 项目名称
private List expenseclaimdetailsList = Lists.newArrayList(); // 子表列表
public Expenseclaimrecords() {
super();
}
public Expenseclaimrecords(String id){
super(id);
}
@Length(min=1, max=30, message="项目名称长度必须介于 1 和 30 之间")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List getExpenseclaimdetailsList() {
return expenseclaimdetailsList;
}
public void setExpenseclaimdetailsList(List expenseclaimdetailsList) {
this.expenseclaimdetailsList = expenseclaimdetailsList;
}
}
根据它的导入,找到它的父类:com.thinkgem.jeesite.common.persistence.DataEntity
可以看到该方法中写了我们导入数据表中必须包含的备注等类,但还缺少id类,继续找到DataEntity的父类。
/**
* Copyright © 2012-2016 JeeSite All rights reserved.
*/
package com.thinkgem.jeesite.common.persistence;
import java.util.Date;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.validator.constraints.Length;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.thinkgem.jeesite.common.utils.IdGen;
import com.thinkgem.jeesite.modules.sys.entity.User;
import com.thinkgem.jeesite.modules.sys.utils.UserUtils;
/**
* 数据Entity类
* @author ThinkGem
* @version 2014-05-16
*/
public abstract class DataEntity<T> extends BaseEntity<T> {
private static final long serialVersionUID = 1L;
protected String remarks; // 备注
protected User createBy; // 创建者
protected Date createDate; // 创建日期
protected User updateBy; // 更新者
protected Date updateDate; // 更新日期
protected String delFlag; // 删除标记(0:正常;1:删除;2:审核)
public DataEntity() {
super();
this.delFlag = DEL_FLAG_NORMAL;
}
public DataEntity(String id) {
super(id);
}
/**
* 插入之前执行方法,需要手动调用
*/
@Override
public void preInsert(){
// 不限制ID为UUID,调用setIsNewRecord()使用自定义ID
if (!this.isNewRecord){
setId(IdGen.uuid());
}
User user = UserUtils.getUser();
if (StringUtils.isNotBlank(user.getId())){
this.updateBy = user;
this.createBy = user;
}
this.updateDate = new Date();
this.createDate = this.updateDate;
}
/**
* 更新之前执行方法,需要手动调用
*/
@Override
public void preUpdate(){
User user = UserUtils.getUser();
if (StringUtils.isNotBlank(user.getId())){
this.updateBy = user;
}
this.updateDate = new Date();
}
@Length(min=0, max=255)
public String getRemarks() {
return remarks;
}
public void setRemarks(String remarks) {
this.remarks = remarks;
}
@JsonIgnore
public User getCreateBy() {
return createBy;
}
public void setCreateBy(User createBy) {
this.createBy = createBy;
}
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
public Date getCreateDate() {
return createDate;
}
public void setCreateDate(Date createDate) {
this.createDate = createDate;
}
@JsonIgnore
public User getUpdateBy() {
return updateBy;
}
public void setUpdateBy(User updateBy) {
this.updateBy = updateBy;
}
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
public Date getUpdateDate() {
return updateDate;
}
public void setUpdateDate(Date updateDate) {
this.updateDate = updateDate;
}
@JsonIgnore
@Length(min=1, max=1)
public String getDelFlag() {
return delFlag;
}
public void setDelFlag(String delFlag) {
this.delFlag = delFlag;
}
}
com.thinkgem.jeesite.common.persistence.BaseEntity
终于找到了id类,至此我们明白导入数据表的必须项了。
/**
* Copyright © 2012-2016 JeeSite All rights reserved.
*/
package com.thinkgem.jeesite.common.persistence;
import java.io.Serializable;
import java.util.Map;
import javax.xml.bind.annotation.XmlTransient;
import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.google.common.collect.Maps;
import com.thinkgem.jeesite.common.config.Global;
import com.thinkgem.jeesite.common.supcan.annotation.treelist.SupTreeList;
import com.thinkgem.jeesite.common.supcan.annotation.treelist.cols.SupCol;
import com.thinkgem.jeesite.common.utils.StringUtils;
import com.thinkgem.jeesite.modules.sys.entity.User;
import com.thinkgem.jeesite.modules.sys.utils.UserUtils;
/**
* Entity支持类
* @author ThinkGem
* @version 2014-05-16
*/
@SupTreeList
public abstract class BaseEntity<T> implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 实体编号(唯一标识)
*/
protected String id;
/**
* 当前用户
*/
protected User currentUser;
/**
* 当前实体分页对象
*/
protected Page page;
/**
* 自定义SQL(SQL标识,SQL内容)
*/
protected Map sqlMap;
/**
* 是否是新记录(默认:false),调用setIsNewRecord()设置新记录,使用自定义ID。
* 设置为true后强制执行插入语句,ID不会自动生成,需从手动传入。
*/
protected boolean isNewRecord = false;
public BaseEntity() {
}
public BaseEntity(String id) {
this();
this.id = id;
}
@SupCol(isUnique="true", isHide="true")
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
@JsonIgnore
@XmlTransient
public User getCurrentUser() {
if(currentUser == null){
currentUser = UserUtils.getUser();
}
return currentUser;
}
public void setCurrentUser(User currentUser) {
this.currentUser = currentUser;
}
@JsonIgnore
@XmlTransient
public Page getPage() {
if (page == null){
page = new Page();
}
return page;
}
public Page setPage(Page page) {
this.page = page;
return page;
}
@JsonIgnore
@XmlTransient
public Map getSqlMap() {
if (sqlMap == null){
sqlMap = Maps.newHashMap();
}
return sqlMap;
}
public void setSqlMap(Map sqlMap) {
this.sqlMap = sqlMap;
}
/**
* 插入之前执行方法,子类实现
*/
public abstract void preInsert();
/**
* 更新之前执行方法,子类实现
*/
public abstract void preUpdate();
/**
* 是否是新记录(默认:false),调用setIsNewRecord()设置新记录,使用自定义ID。
* 设置为true后强制执行插入语句,ID不会自动生成,需从手动传入。
* @return
*/
public boolean getIsNewRecord() {
return isNewRecord || StringUtils.isBlank(getId());
}
/**
* 是否是新记录(默认:false),调用setIsNewRecord()设置新记录,使用自定义ID。
* 设置为true后强制执行插入语句,ID不会自动生成,需从手动传入。
*/
public void setIsNewRecord(boolean isNewRecord) {
this.isNewRecord = isNewRecord;
}
/**
* 全局变量对象
*/
@JsonIgnore
public Global getGlobal() {
return Global.getInstance();
}
/**
* 获取数据库名称
*/
@JsonIgnore
public String getDbName(){
return Global.getConfig("jdbc.type");
}
@Override
public boolean equals(Object obj) {
if (null == obj) {
return false;
}
if (this == obj) {
return true;
}
if (!getClass().equals(obj.getClass())) {
return false;
}
BaseEntity> that = (BaseEntity>) obj;
return null == this.getId() ? false : this.getId().equals(that.getId());
}
@Override
public String toString() {
return ReflectionToStringBuilder.toString(this);
}
/**
* 删除标记(0:正常;1:删除;2:审核;)
*/
public static final String DEL_FLAG_NORMAL = "0";
public static final String DEL_FLAG_DELETE = "1";
public static final String DEL_FLAG_AUDIT = "2";
}
因为我没学过jsp,只能勉强看一看文档。
上图对应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() {
});
function page(n,s){
$("#pageNo").val(n);
$("#pageSize").val(s);
$("#searchForm").submit();
return false;
}
script>
head>
<body>
<ul class="nav nav-tabs">
<li class="active"><a href="${ctx}/sys/expenseclaimrecords/">报销记录列表a>li>
<shiro:hasPermission name="sys:expenseclaimrecords:edit"><li><a href="${ctx}/sys/expenseclaimrecords/form">报销记录添加a>li>shiro:hasPermission>
ul>
<form:form id="searchForm" modelAttribute="expenseclaimrecords" action="${ctx}/sys/expenseclaimrecords/" method="post" class="breadcrumb form-search">
<input id="pageNo" name="pageNo" type="hidden" value="${page.pageNo}"/>
<input id="pageSize" name="pageSize" type="hidden" value="${page.pageSize}"/>
<ul class="ul-form">
<li class="btns"><input id="btnSubmit" class="btn btn-primary" type="submit" value="查询"/>li>
<li class="clearfix">li>
ul>
form:form>
<sys:message content="${message}"/>
<table id="contentTable" class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>项目名称th>
<th>创建者th>
<th>更新日期th>
<th>备注th>
<shiro:hasPermission name="sys:expenseclaimrecords:edit"><th>操作th>shiro:hasPermission>
tr>
thead>
<tbody>
<c:forEach items="${page.list}" var="expenseclaimrecords">
<tr>
<td><a href="${ctx}/sys/expenseclaimrecords/form?id=${expenseclaimrecords.id}">
${expenseclaimrecords.name}
a>td>
<td>
${expenseclaimrecords.createBy.id}
td>
<td>
<fmt:formatDate value="${expenseclaimrecords.updateDate}" pattern="yyyy-MM-dd HH:mm:ss"/>
td>
<td>
${expenseclaimrecords.remarks}
td>
<shiro:hasPermission name="sys:expenseclaimrecords:edit"><td>
<a href="${ctx}/sys/expenseclaimrecords/form?id=${expenseclaimrecords.id}">修改a>
<a href="${ctx}/sys/expenseclaimrecords/delete?id=${expenseclaimrecords.id}" onclick="return confirmx('确认要删除该报销记录吗?', this.href)">删除a>
td>shiro:hasPermission>
tr>
c:forEach>
tbody>
table>
<div class="pagination">${page}div>
body>
html>
上图对应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() {
//$("#name").focus();
$("#inputForm").validate({
submitHandler: function(form){
loading('正在提交,请稍等...');
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);
}
}
});
});
function addRow(list, idx, tpl, row){
$(list).append(Mustache.render(tpl, {
idx: idx, delBtn: true, row: row
}));
$(list+idx).find("select").each(function(){
$(this).val($(this).attr("data-value"));
});
$(list+idx).find("input[type='checkbox'], input[type='radio']").each(function(){
var ss = $(this).attr("data-value").split(',');
for (var i=0; iif ($(this).val() == ss[i]){
$(this).attr("checked","checked");
}
}
});
}
function delRow(obj, prefix){
var id = $(prefix+"_id");
var delFlag = $(prefix+"_delFlag");
if (id.val() == ""){
$(obj).parent().parent().remove();
}else if(delFlag.val() == "0"){
delFlag.val("1");
$(obj).html("÷").attr("title", "撤销删除");
$(obj).parent().parent().addClass("error");
}else if(delFlag.val() == "1"){
delFlag.val("0");
$(obj).html("×").attr("title", "删除");
$(obj).parent().parent().removeClass("error");
}
}
script>
head>
<body>
<ul class="nav nav-tabs">
<li><a href="${ctx}/sys/expenseclaimrecords/">报销记录列表a>li>
<li class="active"><a href="${ctx}/sys/expenseclaimrecords/form?id=${expenseclaimrecords.id}">报销记录<shiro:hasPermission name="sys:expenseclaimrecords:edit">${not empty expenseclaimrecords.id?'修改':'添加'}shiro:hasPermission><shiro:lacksPermission name="sys:expenseclaimrecords:edit">查看shiro:lacksPermission>a>li>
ul><br/>
<form:form id="inputForm" modelAttribute="expenseclaimrecords" action="${ctx}/sys/expenseclaimrecords/save" method="post" class="form-horizontal">
<form:hidden path="id"/>
<sys:message content="${message}"/>
<div class="control-group">
<label class="control-label">项目名称:label>
<div class="controls">
<form:input path="name" htmlEscape="false" maxlength="30" class="input-xlarge required"/>
<span class="help-inline"><font color="red">*font> span>
div>
div>
<div class="control-group">
<label class="control-label">备注:label>
<div class="controls">
<form:textarea path="remarks" htmlEscape="false" rows="4" maxlength="255" class="input-xxlarge "/>
div>
div>
<div class="control-group">
<label class="control-label">报销项记录表:label>
<div class="controls">
<table id="contentTable" class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th class="hide">th>
<th>报销项th>
<th>报销金额th>
<th>备用th>
<shiro:hasPermission name="sys:expenseclaimrecords:edit"><th width="10"> th>shiro:hasPermission>
tr>
thead>
<tbody id="expenseclaimdetailsList">
tbody>
<shiro:hasPermission name="sys:expenseclaimrecords:edit"><tfoot>
<tr><td colspan="5"><a href="javascript:" onclick="addRow('#expenseclaimdetailsList', expenseclaimdetailsRowIdx, expenseclaimdetailsTpl);expenseclaimdetailsRowIdx = expenseclaimdetailsRowIdx + 1;" class="btn">新增a>td>tr>
tfoot>shiro:hasPermission>
table>
<script type="text/template" id="expenseclaimdetailsTpl">//
script>
<script type="text/javascript">
var expenseclaimdetailsRowIdx = 0, expenseclaimdetailsTpl = $("#expenseclaimdetailsTpl").html().replace(/(\/\/\)/g,"");
$(document).ready(function() {
var data = ${fns:toJson(expenseclaimrecords.expenseclaimdetailsList)};
for (var i=0; i'#expenseclaimdetailsList' , expenseclaimdetailsRowIdx, expenseclaimdetailsTpl, data[i]);
expenseclaimdetailsRowIdx = expenseclaimdetailsRowIdx + 1;
}
});
script>
div>
div>
<div class="form-actions">
<shiro:hasPermission name="sys:expenseclaimrecords: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>
body>
html>
通过jsp找到了服务层代码,过程略。
/**
* Copyright © 2012-2016 JeeSite All rights reserved.
*/
package com.thinkgem.jeesite.modules.gen.service;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.thinkgem.jeesite.common.persistence.Page;
import com.thinkgem.jeesite.common.service.BaseService;
import com.thinkgem.jeesite.common.utils.StringUtils;
import com.thinkgem.jeesite.modules.gen.dao.GenSchemeDao;
import com.thinkgem.jeesite.modules.gen.dao.GenTableColumnDao;
import com.thinkgem.jeesite.modules.gen.dao.GenTableDao;
import com.thinkgem.jeesite.modules.gen.entity.GenConfig;
import com.thinkgem.jeesite.modules.gen.entity.GenScheme;
import com.thinkgem.jeesite.modules.gen.entity.GenTable;
import com.thinkgem.jeesite.modules.gen.entity.GenTableColumn;
import com.thinkgem.jeesite.modules.gen.entity.GenTemplate;
import com.thinkgem.jeesite.modules.gen.util.GenUtils;
/**
* 生成方案Service
* @author ThinkGem
* @version 2013-10-15
*/
@Service
@Transactional(readOnly = true)
public class GenSchemeService extends BaseService {
@Autowired
private GenSchemeDao genSchemeDao;
// @Autowired
// private GenTemplateDao genTemplateDao;
@Autowired
private GenTableDao genTableDao;
@Autowired
private GenTableColumnDao genTableColumnDao;
public GenScheme get(String id) {
return genSchemeDao.get(id);
}
public Page find(Page page, GenScheme genScheme) {
GenUtils.getTemplatePath();
genScheme.setPage(page);
page.setList(genSchemeDao.findList(genScheme));
return page;
}
@Transactional(readOnly = false)
public String save(GenScheme genScheme) {
if (StringUtils.isBlank(genScheme.getId())){
genScheme.preInsert();
genSchemeDao.insert(genScheme);
}else{
genScheme.preUpdate();
genSchemeDao.update(genScheme);
}
// 生成代码
if ("1".equals(genScheme.getFlag())){
return generateCode(genScheme);
}
return "";
}
@Transactional(readOnly = false)
public void delete(GenScheme genScheme) {
genSchemeDao.delete(genScheme);
}
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 templateList = GenUtils.getTemplateList(config, genScheme.getCategory(), false);
List 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 childTableModel = GenUtils.getDataModel(genScheme);
for (GenTemplate tpl : childTableTemplateList){
result.append(GenUtils.generateToFile(tpl, childTableModel, genScheme.getReplaceFile()));
}
}
// 生成主表模板代码
genScheme.setGenTable(genTable);
Map model = GenUtils.getDataModel(genScheme);
for (GenTemplate tpl : templateList){
result.append(GenUtils.generateToFile(tpl, model, genScheme.getReplaceFile()));
}
return result.toString();
}
}
生成表的类。验证了备注等信息。
重点在于导入依赖字符串。
/**
* Copyright © 2012-2016 JeeSite All rights reserved.
*/
package com.thinkgem.jeesite.modules.gen.entity;
import java.util.List;
import org.hibernate.validator.constraints.Length;
import com.google.common.collect.Lists;
import com.thinkgem.jeesite.common.persistence.DataEntity;
import com.thinkgem.jeesite.common.utils.StringUtils;
/**
* 业务表Entity
* @author ThinkGem
* @version 2013-10-15
*/
public class GenTable extends DataEntity {
private static final long serialVersionUID = 1L;
private String name; // 名称
private String comments; // 描述
private String className; // 实体类名称
private String parentTable; // 关联父表
private String parentTableFk; // 关联父表外键
private List columnList = Lists.newArrayList(); // 表列
private String nameLike; // 按名称模糊查询
private List pkList; // 当前表主键列表
private GenTable parent; // 父表对象
private List childList = Lists.newArrayList(); // 子表列表
public GenTable() {
super();
}
public GenTable(String id){
super(id);
}
@Length(min=1, max=200)
public String getName() {
return StringUtils.lowerCase(name);
}
public void setName(String name) {
this.name = name;
}
public String getComments() {
return comments;
}
public void setComments(String comments) {
this.comments = comments;
}
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
public String getParentTable() {
return StringUtils.lowerCase(parentTable);
}
public void setParentTable(String parentTable) {
this.parentTable = parentTable;
}
public String getParentTableFk() {
return StringUtils.lowerCase(parentTableFk);
}
public void setParentTableFk(String parentTableFk) {
this.parentTableFk = parentTableFk;
}
public List getPkList() {
return pkList;
}
public void setPkList(List pkList) {
this.pkList = pkList;
}
public String getNameLike() {
return nameLike;
}
public void setNameLike(String nameLike) {
this.nameLike = nameLike;
}
public GenTable getParent() {
return parent;
}
public void setParent(GenTable parent) {
this.parent = parent;
}
public List getColumnList() {
return columnList;
}
public void setColumnList(List columnList) {
this.columnList = columnList;
}
public List getChildList() {
return childList;
}
public void setChildList(List childList) {
this.childList = childList;
}
/**
* 获取列名和说明
* @return
*/
public String getNameAndComments() {
return getName() + (comments == null ? "" : " : " + comments);
}
/**
* 获取导入依赖包字符串
* @return
*/
public List getImportList(){
List importList = Lists.newArrayList(); // 引用列表
for (GenTableColumn column : getColumnList()){
if (column.getIsNotBaseField() || ("1".equals(column.getIsQuery()) && "between".equals(column.getQueryType())
&& ("createDate".equals(column.getSimpleJavaField()) || "updateDate".equals(column.getSimpleJavaField())))){
// 导入类型依赖包, 如果类型中包含“.”,则需要导入引用。
if (StringUtils.indexOf(column.getJavaType(), ".") != -1 && !importList.contains(column.getJavaType())){
importList.add(column.getJavaType());
}
}
if (column.getIsNotBaseField()){
// 导入JSR303、Json等依赖包
for (String ann : column.getAnnotationList()){
if (!importList.contains(StringUtils.substringBeforeLast(ann, "("))){
importList.add(StringUtils.substringBeforeLast(ann, "("));
}
}
}
}
// 如果有子表,则需要导入List相关引用
if (getChildList() != null && getChildList().size() > 0){
if (!importList.contains("java.util.List")){
importList.add("java.util.List");
}
if (!importList.contains("com.google.common.collect.Lists")){
importList.add("com.google.common.collect.Lists");
}
}
return importList;
}
/**
* 是否存在父类
* @return
*/
public Boolean getParentExists(){
return parent != null && StringUtils.isNotBlank(parentTable) && StringUtils.isNotBlank(parentTableFk);
}
/**
* 是否存在create_date列
* @return
*/
public Boolean getCreateDateExists(){
for (GenTableColumn c : columnList){
if ("create_date".equals(c.getName())){
return true;
}
}
return false;
}
/**
* 是否存在update_date列
* @return
*/
public Boolean getUpdateDateExists(){
for (GenTableColumn c : columnList){
if ("update_date".equals(c.getName())){
return true;
}
}
return false;
}
/**
* 是否存在del_flag列
* @return
*/
public Boolean getDelFlagExists(){
for (GenTableColumn c : columnList){
if ("del_flag".equals(c.getName())){
return true;
}
}
return false;
}
}