AdminEAP为是基于AdminLTE改造的后台管理框架,包含了组件集成、CURD增删改查、系统工具、工作流、系统权限与安全等基本的系统管理功能和各种交互demo,项目源码已经在Github上开源,并部署到阿里云。
本文介绍使用freemarker模板,在AdminEAP框架下实现代码生成器,以实现CURD功能的快速生成,借助于代码生成器,基础的开发可以节约大量的时间,同时保持了编码的一致性。
使用步骤
下面以Generator实体为例,介绍代码生成器的使用
1、编写实体类
编写实体类,通过自定义注解Header声明相关属性
Header为自定义注解,开发者在建立外键关系时,可通过ManyToOne,也通过joinClass指定关联的实体,dataSource指定了在编辑时,该属性的数据来源,当为字典时,指定为字典父编码,也可以指定一个url。
2、生成xml配置
启动项目后,输入queryId,实体名,业务名,点击“加载配置“,弹出xml配置窗口,可在此配置窗口配置查询xml
AdminEAP的所有数据列表都是基于xml配置的,可支持反射接口查询、sql配置的查询、离线查询(hql)。
3、重启系统使xml配置生效
如果是首次生成xml文件(注意是文件,如果在已有的xml配置内容,则不需要重新,刷新系统即可,系统会读取更新的xml)
4、配置具体参数
输入queryId,点击”加载配置“后,系统读取xml的配置,并回填所有的默认配置,包括要生成的文件,文件路径等等,开发者也可以根据自己的需要更改参数配置。在界面右侧是实体的属性列表,开发者可以勾选数据再编辑时使用的控件类型,也可以勾选是是否作为查询条件,是否在编辑界面中维护等等。
更具体配置说明,包含在今后的技术文档(付费)中
5、根据freemarker模板生成代码
从界面上收集好以上配置参数后,代码生成器将这些参数给配置好的freemarker模板,生成相关的源代码。
以下是控制器模板controller.html
package ${nameSpace}.controller; import java.util.Date; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import com.alibaba.fastjson.JSON; import com.cnpc.framework.base.entity.Dict; import com.cnpc.framework.utils.StrUtil; import org.springframework.beans.BeanUtils; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import com.cnpc.framework.base.service.BaseService; import com.cnpc.framework.annotation.RefreshCSRFToken; import com.cnpc.framework.annotation.VerifyCSRFToken; import com.cnpc.framework.base.pojo.Result; import ${className}; /** * ${modelName}管理控制器 * @author jrn * ${curTime?string("yyyy-MM-dd HH:mm:ss")}由代码生成器自动生成 */ @Controller @RequestMapping("/${htmlPrefix}") public class ${javaPrefix}Controller { @Resource <#if javaTypes?contains("service")> private ${javaPrefix}Service ${htmlPrefix}Service; <#else> private BaseService baseService; @RequestMapping(value="/list",method = RequestMethod.GET) public String list(){ return "${businessPackage}/${htmlPrefix}_list"; } @RefreshCSRFToken @RequestMapping(value="/edit",method = RequestMethod.GET) public String edit(String id,HttpServletRequest request){ request.setAttribute("id", id); return "${businessPackage}/${htmlPrefix}_edit"; } @RequestMapping(value="/detail",method = RequestMethod.GET) public String detail(String id,HttpServletRequest request){ request.setAttribute("id", id); return "${businessPackage}/${htmlPrefix}_detail"; } @RequestMapping(value="/get/{id}",method = RequestMethod.POST) @ResponseBody public ${javaPrefix} get(@PathVariable("id") String id){ return <#if javaTypes?contains("service")>${htmlPrefix}Service<#else>baseService.get(${javaPrefix}.class, id); } @VerifyCSRFToken @RequestMapping(value="/save") @ResponseBody <#assign isObj=1> <#list fields as field> <#if field.columnName?contains(".")> <#assign isObj=0> public Result save(<#if isObj=1>${javaPrefix} ${htmlPrefix}<#else>String obj){ <#if isObj=0> ${javaPrefix} ${htmlPrefix}= JSON.parseObject(obj,${javaPrefix}.class); <#list fields as field> <#if field.columnName?contains(".")> <#assign fieldName=field.columnName?substring(0,field.columnName?index_of("."))> <#assign fieldN=fieldName?substring(0,1)?upper_case+fieldName?substring(1)> ${htmlPrefix}.set${fieldN}(<#if javaTypes?contains("service")>${htmlPrefix}Service<#else>baseService.get(${field.type}.class,${htmlPrefix}.get${fieldN}().getId())); if(StrUtil.isEmpty(${htmlPrefix}.getId())){ <#if dateFields?exists&&(dateFields?size>0)> <#list dateFields as date> ${date}; <#if javaTypes?contains("service")>${htmlPrefix}Service<#else>baseService.save(${htmlPrefix}); } else{ <#if leftFields?exists&&(leftFields?size>0)> ${javaPrefix} ${htmlPrefix}_old=<#if javaTypes?contains("service")>${htmlPrefix}Service<#else>baseService.get(${javaPrefix}.class,${htmlPrefix}.getId()); BeanUtils.copyProperties(${htmlPrefix},${htmlPrefix}_old, <#list leftFields as str><#if str_index==0>"${str}"<#else>,"${str}"); <#if leftDates?exists&&(leftDates?size>0)> <#list leftDates as ld> ${ld}; ${htmlPrefix}_old.setUpdateDateTime(new Date()); <#if javaTypes?contains("service")>${htmlPrefix}Service<#else>baseService.update(${htmlPrefix}_old); <#else> ${htmlPrefix}.setUpdateDateTime(new Date()); <#if javaTypes?contains("service")>${htmlPrefix}Service<#else>baseService.update(${htmlPrefix}); } return new Result(true); } @RequestMapping(value="/delete/{id}",method = RequestMethod.POST) @ResponseBody public Result delete(@PathVariable("id") String id){ ${javaPrefix} ${htmlPrefix}=this.get(id); try{ baseService.delete(${htmlPrefix}); return new Result(); } catch(Exception e){ return new Result(false,"该数据已经被引用,不可删除"); } } }
6、修改生成的代码并重启系统查看效果
开发者根据需要修改生成的代码,并重启系统,查看效果,如果需要分配权限,请先将生成的菜单功能授权,才可有相应的菜单。
通过代码生成生成了一个业务功能的CURD操作。
7、总结
以上操作步骤,在开发环境使用,在项目中使用代码生成器的主要工作量在编写实体,两次重启系统(如果在之前xml追加内容,则是一次重启)上,其余采用默认配置即可。
欢迎大家使用AdminEAP框架,如有意见建议请登录AdminEAP官网给我提意见。