• 权限管理系统之项目框架搭建并集成日志、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:loglogs,在该目录下可以看下日志文件。

    二、集成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页面动态数据分页显示,后续就是将新增、编辑、删除几个功能实现,同时还要注意删除功能,删除用户后可能还要删除用户与角色关联表,会涉及到事务操作,后续也会加进来。

  • 相关阅读:
    2019-02-08 Python学习之Scrapy的简单了解
    2019-02-07 selenium...
    2019-02-06 单链表的整表创建及增删插
    2019-02-05 Linux的一些常用命令学习2
    2019-02-04 Linux的一些常用命令学习
    2019-02-03 线性表的顺序储存结构C语言实现
    2019-02-03 多进程和多线程的区别【】
    python 多进程
    Tftp文件传输服务器(基于UDP协议)
    多线程实现tcp聊天服务器
  • 原文地址:https://www.cnblogs.com/5ishare/p/10434943.html
Copyright © 2020-2023  润新知