[关闭]
@chenpbh 2018-10-31T02:45:53.000000Z 字数 10356 阅读 543

新源基础开发框架使用手册 V1.7

公共文档

变更历史

版本 日期 人员 变更内容
1.1 2017-08-02 陈鹏 版本初定义
1.2 2017-09-06 陈鹏 增加字典格式化
1.3 2017-11-22 陈鹏 增加名称格式化
1.4 2018-03-05 陈鹏 增加开发规范章节,介绍了权限控制、缓存处理、日志采集
1.6 2018-03-06 陈鹏 增加系统自动化工具章节
1.7 2018-04-10 陈鹏 增加导出文件的规范和流程

1 框架说明

1.1 组件介绍

框架基于Spring Boot进行开发,目前主要使用了如下的相关组件:

1.2 框架图

image_1bmgtkev8lh9hr51ac870k1dpr9.png-41.7kB

需要注意几点:

1.3 包类名规范

在此与test_demo表为例,子系统名即为:test,相关类的目录规范如下

1.3.1 后端代码

1.3.2 前端代码

1.3.3 自定义样式脚本图片

二次开发自定义编写的脚本,样式,还有引用的图片,必须按规定放在/resources/static/extend目录。引用的第三方前端组件,按规定放到/resources/static/frame目录

image_1bmgv7il819df11bn45nnaq1fa4m.png-5.2kB

1.4 配置项说明

2 数据库规范

表名和字段名,统一采用小写+下划线,并且应该是有意义而且易于理解的,最好是能够表达字段含义的英文字母。
注意,所有的表和字段都必须填写相关注释。

2.1 表名

2.2 字段

3 代码细节

3.1 混合模型支持

image_1bmh14fhn1ao16rh1u3j194ro7j1j.png-25.5kB
image_1bmh20tpeansvuo2l3hpmo1019.png-18.1kB

3.1 业务层

image_1bmh2d8s31mti158idhc1fiobp51m.png-15.7kB

4 组件标签

4.1 select

序号 属性名 描述 是否必须 默认值 示例
1 name select选择框名称 status
2 ds 数据源,dict:字典,sql:sql sql
3 key 键值,若ds=dict,key对应字典管理里的编码,或ds=sql,对应xml里的sqlid base.RoleMapper.roles
4 value 当前值
5 verify 验证规则名

如果ds=sql,那么sql应该固定返回valname字段,比如select id as val,name as name from xxxx

示例

  1. <div class="layui-form-item">
  2. <label class="layui-form-label">状态</label>
  3. <div class="layui-input-block">
  4. <@core.select name="status" ds="dict" key="USER_STATE" value="1" />
  5. </div>
  6. </div>

4.2 radio

序号 属性名 描述 是否必须 默认值 示例
1 name radio名称 status
2 ds 数据源,dict:字典,sql:sql sql
3 key 键值,若ds=dict,key对应字典管理里的编码,或ds=sql,对应xml里的sqlid base.RoleMapper.roles
4 value 当前值
5 verify 验证规则名

如果ds=sql,那么sql应该固定返回valname字段,比如select id as val,name as name from xxxx

4.3 checkbox

4.3.1 属性定义

序号 属性名 描述 是否必须 默认值 示例
1 name checkbox名称 status
2 ds 数据源,dict:字典,sql:sql sql
3 key 键值,若ds=dict,key对应字典管理里的编码,或ds=sql,对应xml里的sqlid base.RoleMapper.roles
4 value 当前值,支持多个值,用逗号“,”分隔
5 verify 验证规则名

如果ds=sql,那么sql应该固定返回valname字段,比如select id as val,name as name from xxxx

4.4 dialog (列表弹窗选择器)

4.4.1 属性定义

序号 属性名 描述 是否必须 默认值 示例
1 name select选择框名称 status
2 value 当前值,支持多个值 1,2
3 display 显示文本 程序员,前端工程师
4 refer 引用页面dom的ID,在页面为隐藏域,开发人员不需要手动增加隐藏域 roleIds
5 key sql,对应xml里的sqlid base.RoleMapper.roles
6 args 附加参数 k1:v1,k2:v2
7 title 标题 请选择角色
8 width 长度,单位为px 500px 500px
9 height 高度,单位为px 600px 600px
11 multiple 是否多选 false false
12 verify 验证规则名
13 queryParam 明文传参到ftl页面

sql应该固定返回idname字段,比如select id as id,name as name from xxxx

4.4.2 示例

  1. <div class="layui-form-item">
  2. <label class="layui-form-label">角色</label>
  3. <div class="layui-input-block">
  4. <@core.dialog name="roleNames" key="base.RoleMapper.treeNodes" value="" multiple=true refer="roleIds" title="请选择角色" height="600px" />
  5. </div>
  6. </div>

4.5 tree (树形选择器)

4.5.1 属性定义

序号 属性名 描述 是否必须 默认值 示例
1 name select选择框名称 status
2 value 当前值,支持多个值 1,2
3 display 显示文本 程序员,前端工程师
4 refer 引用页面dom的ID,在页面为隐藏域,开发人员不需要手动增加隐藏域 roleIds
5 key sql,对应xml里的sqlid base.RoleMapper.roles
6 args 附加参数
7 title 标题 请选择角色
8 width 长度,单位为px 500px 500px
9 height 高度,单位为px 600px 600px
11 multiple 是否多选 false false
12 verify 验证规则名

sql应该固定返回idname字段,比如select id as id,name as name from xxxx

4.5.2 示例

  1. <div class="layui-form-item">
  2. <label class="layui-form-label">父节点</label>
  3. <div class="layui-input-block">
  4. <@core.tree name="parentName" key="base.AreaMapper.treeNodes" value="${(obj.parentId)!}" display="${(obj.tails.parentName)!}" multiple=true refer="parentId" title="请选择上级区域"/>
  5. </div>
  6. </div>

4.6 lngLat (经纬度拾取器)

4.6.1 属性定义

序号 属性名 是否必填 描述 示例
1 lngName 经度html元素名称 lng
2 latName 纬度html元素名称 lat
3 lng 当前经度值 0
4 lng 当前纬度值 0
5 verifyLngName 经度校验规则名称
6 verifyLatName 纬度校验规则名称

4.6.2 示例

  1. <div class="layui-form-item">
  2. <@core.lngLat lngName="lng" latName="lat" lng="${(obj.lng)!0}" lat="${(obj.lat)!0}" addressFrom="address"/>
  3. <div>

image_1c72no9fc1bf1jiqi1a1dmg1ht72m.png-220.3kB

5 格式化标签

5.1 字典格式化

序号 属性名 描述 是否必须 默认值 示例
1 code 字典编码 BASE_EMPLOYEE_IS_USE
2 key 字段名,对应column的field名 inUser

示例

  1. <@formatter.dict code='BASE_EMPLOYEE_IS_USE' key='isUse'/>
  2. #表格
  3. {field: 'isUse', title: '权限状态', width: 120, templet:"#isUse"},

image_1bpakcpqafff5dl1omfmqn13hmp.png-76.2kB

5.2 名称格式化

此标签主要用于列表格式化显示,另外`DataLoader.loadNames(Object)`方法可用于在编辑、查看页面,将外键关联的名称显示出来,而不必通过关联表查询。同样在处理导出时,调用此方法,也可以将相关数据查询出来。

5.2.1 属性

序号 属性名 描述 是否必须 默认值 示例
1 key 字段名,对应column的field名 roleIds
2 url 点击弹出页面,一般为查看详情页面,若url为空,width和height可为空 /role/view
3 width 窗口宽度 500px
4 height 窗口高度 500px

5.2.2 使用说明

1、 在domain实体的相应get方法增加@LinkName注解

  1. @LinkName(table = "base_role")
  2. public String getRoleIds() {
  3. return roleIds;
  4. }

2、 在service层显示调用DataLoader.loadNames(Object)方法(目前传参支持List、LayModel和TailBean的子类)

  1. LayModel layModel = new LayModel();
  2. ayModel.setCount(pm.getTotal());
  3. layModel.setData(pm.getRows());
  4. DataLoader.loadNames(layModel);
  5. return layModel;

3、在前端页面使用标签

  1. <@formatter.name key='roleIds' url='/role/update' width="600px" height='500px'/>
  2. <script>
  3. #表格列定义
  4. {field: 'roleNames', title: '角色',templet: '#roleIds'},
  5. </script>

5.2.3 效果

image_1bvg4m9fc1jcva7026igbq1hq69.png-27.8kB

6 开发规范

此章节主要约定了开发过程中的规范,避免开发人员在开发过程中,出现遗漏和不规范的情况。

6.1 权限控制

该框架采用 Apache Shiro实现用户访问权限的控制,支持前后端的权限控制。其中前端采用的是Freemarker标签方式,而后台是需要在控制器方法中,增加注解。而权限控制的核心元素,则是资源编码(对应模块管理中的编码)。另外,建议编码的命名为业务大模块_功能模块_动作,比如新增用户,命名为BASE_USER_ADD

通过代码生成器生成的代码,已经生成了对应的资源信息。如果是单独开发的,需要必须手工增加资源信息,并在前后端代码中,加以控制。我们约定,在下面章节点,我们将以新增用户的权限处理来举例说明,权限是如何控制的

image_1c7qhteji4ijqk3i01dai17sl9.png-30.2kB

6.1.1 前端控制

前端通过freemarker标签进行控制,常用的标签包括:

  • hasPermission: 验证当前用户是否拥有该权限
  • authenticated: 验证用户是否已经登录系统
  • lacksPermission:验证当前用户不拥有某种权限,与hasPermission标签是相对的

1、 为了对新增用户进行权限控制,首先我们需要在前台页面/base/user/list.ftl页面中,html的新增按钮元素用freemarker标签已经包括起来

  1. <@shiro.hasPermission name="BASE_USER_ADD">
  2. <a class="layui-btn btn-add btn-default" id="btn-add">新增</a>
  3. </@shiro.hasPermission>

2、然后,出于安全和隐私控制,我们同时将新增相关的JS代码也进行控制

  1. <@shiro.hasPermission name="BASE_USER_ADD">
  2. //绑定新增按钮事件
  3. bindAdd('/base/user/add','新增',"540px","530px",gridObj);
  4. </@shiro.hasPermission>

6.1.2 后端控制

在控制器通过注解@RequiresPermissions控制权限(注意,功能关联的其他请求,也应该加上注解进行控制,常用的就是包括页面和Ajax调用)

  1. /**
  2. * 新增页面
  3. * @param model
  4. * @return
  5. */
  6. @GetMapping(value = "/add")
  7. @RequiresPermissions("BASE_USER_ADD")
  8. @SLog(action = "新增页面")
  9. public String add(Model model) {
  10. return BASE+"add";
  11. }
  12. /**
  13. * 保存
  14. * @param job
  15. * @return
  16. */
  17. @PostMapping(value = "/add")
  18. @ResponseBody
  19. @RequiresPermissions("BASE_USER_ADD")
  20. @SLog(action = "新增用户")
  21. public AppBean add(User user){
  22. userService.insert(user);
  23. return new AppBean("增加成功");
  24. }

6.2 日志收集

系统日志目前是通过提供自定义的注解方式实现,提供的注解为下:
* Module: 模块名,比如用户管理
* SLog: 动作名,比如新增

下面我们以新增用户举例:

1、需要在控制类声明上加上@Module注解

  1. /**
  2. * 用户管理
  3. * @author 陈鹏
  4. * @Time 2017-07-04 18:29:52
  5. */
  6. @Module(name = "用户管理")
  7. @Controller
  8. @RequestMapping(value = "/user")

2、在新增方法加上注解SLog注解,由于新增涉及到两个请求,所以此处在这两个方法都加上SLog注解

  1. /**
  2. * 新增页面
  3. * @param model
  4. * @return
  5. */
  6. @GetMapping(value = "/add")
  7. @RequiresPermissions("BASE_USER_ADD")
  8. @SLog(action = "新增页面")
  9. public String add(Model model) {
  10. return BASE+"add";
  11. }
  12. /**
  13. * 保存
  14. * @param job
  15. * @return
  16. */
  17. @PostMapping(value = "/add")
  18. @ResponseBody
  19. @RequiresPermissions("BASE_USER_ADD")
  20. @SLog(action = "新增用户")
  21. public AppBean add(User user){
  22. userService.insert(user);
  23. return new AppBean("增加成功");
  24. }

3、日志采集情况可以通过日志管理中查看。
image_1c7qk7g2q1hu6if51mu91g8v1u1m35.png-94kB

6.3 缓存处理

6.3.1 Mybatis二级缓存

框架对于Mybatis二级缓存进行扩展,由Mybatis默认的内存改为了Redis。使用方式如下:

1、配置文件,在application.yml的redis配置中,增加mybatis缓存配置spring.redis.mybatis.index,即指定二级缓存放的redis的db

  1. spring:
  2. redis:
  3. database: 12
  4. host: 192.168.6.141
  5. port: 6380
  6. password: 123456
  7. mybatis:
  8. index: 13

2、需要在mybatis的mapper的xml开启二级缓存支持,即cache的type为com.bitnei.cloud.common.cache.MybatisRedisCache

  1. <mapper namespace="com.bitnei.cloud.base.mapper.JobMapper">
  2. <cache type="com.bitnei.cloud.common.cache.MybatisRedisCache" eviction="LRU" flushInterval="6000000" size="1024" readOnly="false"/>
  3. ...........
  4. </mapper>

3、缓存管理,为了避免出现开发人员使用不当导致内存不同步的情况,框架提供了mybatis二级缓存的管理功能,支持查看和清理等操作。
image_1c7qls7tu182lt7ddvilh71fh63i.png-105.7kB

6.4 导出文件

6.4.1 流程描述

Created with Raphaël 2.1.2开始1、编写MyBatis SQL语句2、业务层采集数据3、配置excel模板结束

在这里,以导出系统日志为示例:

1、编写mysql语句: 正常情况下,我们可以直接使用数据列表的sql语句,如下

  1. <!-- 分页查询 -->
  2. <select id="pagerModel" resultMap="tailResults" parameterType="java.util.HashMap">
  3. select
  4. <include refid="moreColumns"/>
  5. from
  6. base_log log
  7. where
  8. 1=1
  9. <if test="username != null">
  10. and log.username like "%"#{username}"%"
  11. </if>
  12. <if test="moudle != null">
  13. and log.moudle like "%"#{moudle}"%"
  14. </if>
  15. <if test="action != null">
  16. and log.action like "%"#{action}"%"
  17. </if>
  18. ORDER BY log.TIME DESC
  19. </select>

2、业务层采集数据: 如果模块代码是通过代码生成工具生成的,正常业务层代码是不需要改动的

  1. @Override
  2. public void export() {
  3. List list = findBySqlId("pagerModel",ServletUtil.getQueryParams());
  4. String srcBase = RequestContext.class.getResource("/templates/").getFile();
  5. String srcFile = srcBase +"module/base/log/export.xls";
  6. ExcelData ed = new ExcelData();
  7. ed.setTitle("日志管理");
  8. ed.setExportTime(DateUtil.getNow());
  9. ed.setData(list);
  10. String outName = String.format("%s-导出-%s.xls", "日志管理", DateUtil.getShortDate());
  11. EasyExcel.renderResponse(srcFile,outName,ed);
  12. }

3、配置excel模板: 框架的excel模板为export.xls,excel文件中共有两个sheet,一个为列定义,一个参数配置。详细的excel配置,将在下面章节进行描述。

image_1canetudj142pth715jo160h9ljm.png-93.8kB
image_1caneuo7n8jmfev16ac1vgq1eu51j.png-49.3kB

6.4.2 excel配置

6.4.2.1 列定义

列定义采用Freemarker实现,支持freemarker指令表达式。在这里,框架默认对象名为obj,比如Log实体定义为

  1. public class Job extends TailBean {
  2. /** **/
  3. private String id;
  4. /** 任务名称 **/
  5. private String name;
  6. /** 类名 **/
  7. private String className;
  8. /** 方法名 **/
  9. private String methodName;
  10. /** Cron表达式 **/
  11. private String cron;
  12. /** 上次执行时间 **/
  13. private String lastJobTime;
  14. /** 最后异常信息 **/
  15. private String lastException;
  16. /** 启用状态 **/
  17. private Integer status;
  18. /** 耗时 **/
  19. private Integer takeTime;
  20. /** 创建时间 **/
  21. private String createTime;
  22. /** 创建人 **/
  23. private String createBy;
  24. /** 更新时间 **/
  25. private String updateTime;
  26. /** 更新人 **/
  27. private String updateBy;
  28. /** 备注 **/
  29. private String note;
  30. ....getter/setter........
  31. }

然后在excel中就可以根据实现情况,进行配置模板。另外,导出文件的样式,也可以直接调整。导出文件,样式和模板的保持一致。

6.4.2.2 参数配置

目前框架支持的参数项如下:

6.4.3 导出文件名规范

7 系统自动化工具

7.1 代码生成

代码生成依赖于数据库表的注释,详细注释规则参见# 2 数据库规范

image_1c7tcainrag1nu11tjr1qsu1v10p.png-53.1kB

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注