权限管理系统之项目框架搭建并集成日志、mybatis和分页
前一篇博客中使用LayUI实现了列表页面和编辑页面的显示交互,但列表页面table渲染的数据是固定数据,本篇博客主要是将固定数据变成数据库数据。
一、项目框架
首先要解决的是项目框架问题,搭建什么样的框架比较合适,优缺点是什么,扩展性、可读性等方面都要考虑,本项目的框架也是百度参考借鉴网友的,不管是Java还是C#的项目思想都差不多也都是可以互相借鉴的,下图是项目结构图,可能后面还会根据需要再进一步的修改完善。
上面目录结构中主要包含8个包,下面对这几个包进行简单介绍。
com.example:存在main函数类
com.example.config:配置类包,例如druid多数据源配置类
com.example.controller:存放controller
com.example.dao:与数据库交互层,存放mapper接口
com.example.entity:实体层,这个与com.example.pojo有点类似,不过两个还是有区别的,pojo层主要是与数据库单个数据表对应,entity可能是其他对象的抽象,比如多个表联合查询组成的行对应的类、或者前端页面显示对应的类、一对多、多对多关系。
com.example.pojo:数据库表的对应类
com.example.service:业务服务接口层,定义服务接口,优势是什么呢,这样在Controller中注入的是service接口,是面向接口的编程,如果服务的具体实现改变了也不影响其他注入类。
com.example.service.impl:实现服务接口,业务逻辑的具体实现
com.example.utils:基础类、工具类层
二、集成日志
项目使用的log4j2日志框架,由于SpringBoot自带的有日志框架,所以需要先排除掉,然后在引入log4j2日志。
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <artifactId>spring-boot-starter-logging</artifactId> <groupId>org.springframework.boot</groupId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-log4j2</artifactId> </dependency>
可以在application.properties中设置log4j2的相关配置或者创建log4j2.xml放在application.properties同目录下。这里在创建的log4j2.xml中设置日志存放位置在D:\log\logs,在该目录下可以看下日志文件。
二、集成mybatis
集成mybatis主要是引入两个依赖,一个是mysql的,一个是mybatis的。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!-- https://mvnrepository.com/artifact/org.mybatis.spring.boot/mybatis-spring-boot-starter --> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>1.3.2</version> </dependency> <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.11</version> </dependency>
项目是使用的xml方式管理sql,所以在该项目的resource目录下创建了mybatis目录,子目录mapper存放sql映射文件,mybatis-config.xml放mybatis的配置,同时还需要在application.properties设置数据库信息、mybatis文件目录信息。
#mysql spring.datasource.driverClassName = com.mysql.cj.jdbc.Driver #spring.datasource.url = jdbc:mysql://localhost:3306/mybatis spring.datasource.url =jdbc:mysql://127.0.0.1:3306/mybatis?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC spring.datasource.username = root spring.datasource.password = 123456 #mybatis mybatis.type-aliases-package=com.example.model mybatis.config-location=classpath:mybatis/mybatis-config.xml mybatis.mapper-locations=classpath:mybatis/mapper/*.xml
三、集成分页pagehelper
集成pagehelper这里有两种方式,一是spring集成方式,二是SpringBoot集成方式,可参考:https://www.cnblogs.com/1315925303zxz/p/7364552.html 。这里使用的是第一种,另外在这里遇到了一个问题,就是分页操作之后能查出数据但PageInfo的total值一直是0,原来是忘记在mybatis-config.xml配置pagehelper插件并要设置rowBoundsWithCount=true。
<dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>3.4.2</version> </dependency>
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <typeAliases> <typeAlias alias="Integer" type="java.lang.Integer" /> <typeAlias alias="Long" type="java.lang.Long" /> <typeAlias alias="HashMap" type="java.util.HashMap" /> <typeAlias alias="LinkedHashMap" type="java.util.LinkedHashMap" /> <typeAlias alias="ArrayList" type="java.util.ArrayList" /> <typeAlias alias="LinkedList" type="java.util.LinkedList" /> </typeAliases> <plugins> <!-- com.github.pagehelper为PageHelper类所在包名 --> <plugin interceptor="com.github.pagehelper.PageHelper"> <!-- 方言 --> <property name="dialect" value="mysql"/> <!-- 该参数默认为false --> <!-- 设置为true时,使用RowBounds分页会进行count查询 --> <property name="rowBoundsWithCount" value="true"/> </plugin> </plugins> </configuration>
四、数据分页实现
1.首先数据库准备数据
这里在数据表中插入了12条数据。
2.分页
layui的table填充的数据有4个字段,code、msg、count、data,所以在PageDataResult中定义也定义了4个属性。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package com.example.utils; import java.util.List; public class PageDataResult { //总记录数量 private Integer totals; //当前页数据列表 private List<?> list; private Integer code=200; private String msg=""; public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } public PageDataResult() { } public PageDataResult( Integer totals, List<?> list) { this.totals = totals; this.list = list; } public Integer getTotals() { return totals; } public void setTotals(Integer totals) { this.totals = totals; } public List<?> getList() { return list; } public void setList(List<?> list) { this.list = list; } public Integer getCode() { return code; } public void setCode(Integer code) { this.code = code; } @Override public String toString() { return "PageDataResult{" + "totals=" + totals + ", list=" + list + ", code=" + code + '}'; } }
3.分页实现
主要实现方法也比较简单,使用pagehelper进行分页,然后将结果设置到PageDataResult。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
@Override public PageDataResult getUsers(UserSearchDTO userSearch) { PageDataResult pdr = new PageDataResult(); PageHelper.startPage(userSearch.getPage(), userSearch.getLimit(),true); List<User> urList = userMapper.getUsers(userSearch); logger.debug("urList:"+urList.size()); // 获取分页查询后的数据 PageInfo<User> pageInfo = new PageInfo<>(urList); // 设置获取到的总记录数total: logger.debug("page:"+userSearch.getPage()+"limit:"+userSearch.getLimit()+"总行数:"+pageInfo.getTotal()); pdr.setTotals(Long.valueOf(pageInfo.getTotal()).intValue()); pdr.setList(urList); return pdr; }
4.替换固定数据
上一博客是将列表数据写成固定的,这里进行了替换,分页之后返回PageDataResult。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
@RequestMapping(value = "/getUsers", method = RequestMethod.GET) @ResponseBody public PageDataResult getUsers(@RequestParam("page") Integer page, @RequestParam("limit") Integer limit,@RequestParam(value="keyword",required=false) String keyword) { logger.debug("分页查询用户列表!,查询条件keyword:"+keyword+"page:" + page+",每页记录数量limit:" + limit); PageDataResult pdr = new PageDataResult(); try { if (null == page) { page = 1; } if (null == limit) { limit = 10; } UserSearchDTO userSearch=new UserSearchDTO(page,limit,keyword); // 获取用户和角色列表 pdr = userService.getUsers(userSearch); logger.debug("用户列表查询=pdr:" + pdr); logger.debug("用户列表查询数量:" + pdr.getList().size()); } catch (Exception e) { e.printStackTrace(); logger.error("用户列表查询异常!", e); } return pdr; }
五、优化
由于从数据库返回的user表的sex数据是0、1,所以需要转成男、女,使用了table列的templet,同时id列通过hide=true进行了隐藏,又由于PageDataResult返回结果的key的名字与table所要求的不一致,又使用了response进行映射。下面代码是目前最新的user.js代码,后续可能还会更新。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
var table; var layer; layui.use([ 'layer', 'table', 'element' ], function() { table = layui.table; layer = layui.layer; // 执行一个 table 实例 table.render({ elem : '#user', height:350, url : '/user/getUsers', method: 'get', //默认:get请求 page :true, // 开启分页 request: { pageName: 'page' //页码的参数名称,默认:page ,limitName: 'limit' //每页数据量的参数名,默认:limit },response:{ statusName: 'code' //数据状态的字段名称,默认:code ,statusCode: 200 //成功的状态码,默认:0 ,countName: 'totals' //数据总数的字段名称,默认:count ,dataName: 'list' //数据列表的字段名称,默认:data }, cols : [ [ // 表头 { fixed : 'left', type : 'checkbox' }, { field : 'id', title : 'ID', width : 80, fixed : 'left', hide:true }, { field : 'name', title : '姓名', width : 80 }, { field : 'age', title : '年龄', width : 80 }, { field : 'sex', title : '性别', width : 80, templet : function(d) { if (d.sex == 1) { return '男'; } else if (d.sex == 0) { return '女'; } } },{ title : '操作', width : 200, align : 'center', toolbar : '#tools' } ] ] }); // 监听工具条 table.on('tool(tools)', function(obj) { // 注:tool是工具条事件名,test是table原始容器的属性 var data = obj.data // 获得当前行数据 , layEvent = obj.event; // 获得 lay-event 对应的值 if ('edit' == layEvent) { addUser(data.id) } else if ('del' == layEvent) { del(data.id); } }); }); function queryUser(){ var keyword = $("#keyword").val(); table.reload('user', { where : { keyword : keyword }, page : { curr : 1 } }); } var index; function addUser(id) { index = parent.layer.open({ type : 2, title : "用户信息", area: ['550px', '400px'], content : '/user/edit?id=' + id }); layer.full(index); } function del(id) { parent.layer.open({ type : 1, content : '<div style="padding: 20px 80px;">确定删除记录?</div>', btn : [ '确定', '取消' ], yes : function(index, layero) { $.ajax({ url : "/user/delete", data : { "id" : id }, dataType : "text", success : function(data) { if(data==0){ layer.msg("删除成功!"); layer.close(index); queryUser(); }else{ layer.msg("删除失败!"); } }, error : function() { } }); } }); } /** * 获取选中数据 */ function getDatas(){ var checkStatus = table.checkStatus('user'); var data = checkStatus.data; var id = ""; for(var i=0;i<data.length;i++){ id += data[i].id; if(i<data.length-1){ id += ","; } } if(data.length != 0){ alert(id); // del(id); } }
六.小结
目前把java部分的项目框架搭建了起来,也集成了日志、mybatis、分页插件pagehelper,实现了table页面动态数据分页显示,后续就是将新增、编辑、删除几个功能实现,同时还要注意删除功能,删除用户后可能还要删除用户与角色关联表,会涉及到事务操作,后续也会加进来。
作者:社会主义接班人
出处:http://www.cnblogs.com/5ishare/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
如果文中有什么错误,欢迎指出。以免更多的人被误导。