权限管理系统之项目框架搭建并集成日志、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://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>
View Code

项目是使用的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>
<?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>
View Code

四、数据分页实现

1.首先数据库准备数据

这里在数据表中插入了12条数据。

2.分页

layui的table填充的数据有4个字段,code、msg、count、data,所以在PageDataResult中定义也定义了4个属性。

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 + '}';
        }
}
View Code

3.分页实现

主要实现方法也比较简单,使用pagehelper进行分页,然后将结果设置到PageDataResult。

    @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;
                
    }
View Code

4.替换固定数据

上一博客是将列表数据写成固定的,这里进行了替换,分页之后返回PageDataResult。

    @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;
    }
View Code

五、优化

由于从数据库返回的user表的sex数据是0、1,所以需要转成男、女,使用了table列的templet,同时id列通过hide=true进行了隐藏,又由于PageDataResult返回结果的key的名字与table所要求的不一致,又使用了response进行映射。下面代码是目前最新的user.js代码,后续可能还会更新。

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);
    }
}
View Code

六.小结

目前把java部分的项目框架搭建了起来,也集成了日志、mybatis、分页插件pagehelper,实现了table页面动态数据分页显示,后续就是将新增、编辑、删除几个功能实现,同时还要注意删除功能,删除用户后可能还要删除用户与角色关联表,会涉及到事务操作,后续也会加进来。

posted @ 2019-02-26 02:19  社会主义接班人  阅读(1233)  评论(6编辑  收藏  举报