关于SpringBoot和PageHelper,前篇博客已经介绍过Spring boot入门(二):Spring boot集成MySql,Mybatis和PageHelper插件,前篇博客大致讲述了SpringBoot如何集成Mybatis和Pagehelper,但是没有做出实际的范例,本篇博客是连接上一篇写的。通过AdminLTE前端框架,利用DataTable和PageHelper进行分页显示,通过对用户列表的增删改查操作,演示DataTable和PageHelper的使用。
(1)AdminLTE介绍
AdminLTE是一个完全响应管理模板。基于Bootstrap3框架,易定制模板。适合多种屏幕分辨率,从小型移动设备到大型台式机。内置了多个页面,包括仪表盘、邮箱、日历、锁屏、登录及注册、404错误、500错误等页面。具体介绍见官方网站:https://adminlte.io/,我们可以直接从此网站下载该模板,其外观如下:
(2)SpringBoot后台集成AdminLTE
首先在官网下载AdminLTE模板,然后将此模板的全部文件拷贝到项目下:
拷贝后,将AdminLTE文件进行了拆分,其中base里面是AdminLTE自带的所有js包和css文件,main中是AdminLTE主页面渲染页面,index是入口。这么做的目的:直接将base通过FreeMarker中宏的形式引入到index入口页面中,那么所有的js文件将一直曾在最底层的页面下,在后期的其它页面的开发中,不需要再次引入js包,避免js包混乱。
启动项目:
(3)配置generate
generate的介绍比较多,此处直接介绍配置的步骤及代码
增加依赖jar包,在build下增加
1 <plugin> 2 <groupId>org.mybatis.generatorgroupId> 3 <artifactId>mybatis-generator-maven-pluginartifactId> 4 <version>1.3.7version> 5 <dependencies> 6 <dependency> 7 <groupId>mysqlgroupId> 8 <artifactId>mysql-connector-javaartifactId> 9 <version>${mysql-connector-java.version}version> 10 dependency> 11 <dependency> 12 <groupId>org.mybatis.generatorgroupId> 13 <artifactId>mybatis-generator-coreartifactId> 14 <version>1.3.7version> 15 dependency> 16 <dependency> 17 <groupId>tk.mybatisgroupId> 18 <artifactId>mapperartifactId> 19 <version>${mapper.version}version> 20 dependency> 21 dependencies> 22 <executions> 23 <execution> 24 <id>Generate MyBatis Artifactsid> 25 <phase>packagephase> 26 <goals> 27 <goal>generategoal> 28 goals> 29 execution> 30 executions> 31 <configuration> 32 33 <verbose>trueverbose> 34 35 <overwrite>trueoverwrite> 36 37 38 configuration> 39 plugin>
编写generatorConfig.xml文件,并放在templates根目录下,若放在其它目录中,则需要在pom.xml中配置路径,否则,编译的时候无法通过。具体错误:
1 [ERROR] Failed to execute goal org.mybatis.generator:mybatis-generator-maven-plugin:1.3.5:generate (default-cli) on project edu: configfile D:\8_Project\learn\edu\src\main\resources\generatorConfig.xml does not exist -> [Help 1] 2 [ERROR] 3 [ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch. 4 [ERROR] Re-run Maven using the -X switch to enable full debug logging. 5 [ERROR] 6 [ERROR] For more information about the errors and possible solutions, please read the following articles: 7 [ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException
generatorConfig.xml的脚本如下,其中targetProject的路径需要曾在,否则会报错,参考https://blog.csdn.net/hh680821/article/details/79051870
1 xml version="1.0" encoding="UTF-8"?> 2 DOCTYPE generatorConfiguration 3 PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" 4 "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd"> 5 6 <generatorConfiguration> 7 8 9 <context id="Mysql" targetRuntime="MyBatis3Simple" defaultModelType="flat"> 10 11 <property name="beginningDelimiter" value="`"/> 12 <property name="endingDelimiter" value="`"/> 13 14 <commentGenerator> 15 <property name="suppressAllComments" value="true" /> 16 commentGenerator> 17 18 <plugin type="tk.mybatis.mapper.generator.MapperPlugin"> 19 <property name="mappers" value="com.tswc.edu.utils.MyMapper"/> 20 plugin> 21 22 <commentGenerator> 23 <property name="suppressAllComments" value="true" /> 24 commentGenerator> 25 26 <jdbcConnection driverClass="com.mysql.jdbc.Driver" 27 connectionURL="jdbc:mysql://localhost:3306/edu" 28 userId="root" 29 password="123456"> 30 jdbcConnection> 31 32 <javaModelGenerator targetPackage="generator" targetProject="src/main/java"/> 33 34 <sqlMapGenerator targetPackage="generator" targetProject="src/main/java"/> 35 36 <javaClientGenerator targetPackage="generator" targetProject="src/main/java" 37 type="XMLMAPPER"/> 38 39 55 <table tableName="t_user"> 56 <generatedKey column="id" sqlStatement="Mysql" identity="true"/> 57 table> 58 59 context> 60 generatorConfiguration>
假设产生此错误:
1 [ERROR] Failed to execute goal org.mybatis.generator:mybatis-generator-maven-plugin:1.3.5:generate (default-cli) on project edu: XML Parser Error on line 60: 元素类型为 "context" 的内容必须匹配 "(property*,plugin*,commentGenerator?,(connectionFactory|jdbcConnection),javaTypeResolver?,javaModelGenerator,sqlMapGenerator?,javaClientGenerator?,table+)"。 -> [Help 1] 2 [ERROR] 3 [ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch. 4 [ERROR] Re-run Maven using the -X switch to enable full debug logging. 5 [ERROR] 6 [ERROR] For more information about the errors and possible solutions, please read the following articles: 7 [ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException
原因就是:generate中,标签都是有顺序的,此类错误就是标签的顺序存在问题
此时,xml文件以及配置结束,需要在idea中配置启动操作:mybatis-generator:generate,如图
(4)DataTable的使用
DataTable是一款简单易用的分页插件,基于JQuery写的,里面提供了丰富的分页参数,主要通过Ajax实现数据的前后端传输
首先引入js和css包:
其外,还需要格式化相关提示文字,一般命名为:language.json
1 { 2 "sEmptyTable": "没有相关数据", 3 "sInfo": "从 _START_ 到 _END_ 条记录 总记录数为 _TOTAL_ 条", 4 "sInfoEmpty": "记录数为0", 5 "sInfoFiltered": "(全部记录数 _MAX_ 条)", 6 "sInfoPostFix": "", 7 "sInfoThousands": ",", 8 "sLengthMenu": "显示 _MENU_ 条", 9 "sLoadingRecords": "正在加载...", 10 "sProcessing": "正在获取数据,请稍候...", 11 "sSearch": "搜索", 12 "sZeroRecords": "没有您要搜索的内容", 13 "oPaginate": { 14 "sFirst": "首页", 15 "sPrevious": "上一页", 16 "sNext": "下一页", 17 "sLast": "尾页", 18 "sJump": "跳转" 19 }, 20 "oAria": { 21 "sSortAscending": ": 以升序排序", 22 "sSortDescending": ": 以降序排序" 23 } 24 }
具体的实现方式如下代码:
1 var user_tab; 2 var user_list_param; 3 $(function () { 4 var url="/admin/user/listPage"; 5 user_list_setParm(); 6 user_tab = $('#user_tab').DataTable({ 7 "fnDrawCallback": function () { 8 }, 9 "dom": '<"top"i>rt<"bottom"flp><"clear">', 10 //"ordering":false,//是否排序 11 "processing": true, 12 "searching": false, 13 "serverSide": true, //启用服务器端分页 14 "order": [[ 5, "asc" ]],//默认排序字段 15 "bInfo": true, 16 "bAutoWidth": false, 17 "scrollX": true, 18 "scrollCollapse": false, 19 /*fixedColumns: { 20 leftColumns: 0, 21 rightColumns: 1 22 },*/ 23 "language":{"url":"/plugins/datatables/language.json"}, 24 "ajax":{"url":url,"data":user_list_param,"type":"post"}, 25 "columns":[ 26 {"data":"id"}, 27 {"data":null}, 28 {"data":"userName"}, 29 {"data":"password"}, 30 {"data":"trueName"}, 31 {"data":"createTime"}, 32 {"data":"id"} 33 ], 34 "columnDefs" : [ 35 { 36 targets: 0, 37 data: null, 38 orderable:false, 39 render: function (data) { 40 return '<input type="checkbox" class="userCheckbox" value="'+data+'"/>'; 41 } 42 }, 43 { 44 targets: 1, 45 data: null, 46 orderable:false, 47 render: function (data) { 48 No=No+1; 49 return No; 50 } 51 }, 52 { 53 "targets" : -1, 54 "data" : null, 55 orderable:false, 56 "render" : function(data) { 57 var data = "'"+data+"'"; 58 var btn1='<a class="btn btn-xs btn-warning" target="modal" modal="hg" href=""><i class="fa fa-edit">i>修改a> '; 59 var btn2 = '<a class="btn btn-xs btn-danger" target="modal" modal="hg" onclick="user_list_delete('+data+')"><i class="fa fa-remove">i>删除a> '; 60 return btn1+btn2; 61 } 62 } 63 ] 64 }).on('preXhr.dt', function ( e, settings, data ) { 65 No=0; 66 }).on('xhr.dt', function(e, settings, json, xhr) { 67 }); 68 });
这里面需要说明的:
a.如果开启排序,那么后端接受参数的方式:
@RequestParam(value = "order[0][column]", required = false) Integer orderIndex
@RequestParam(value = "order[0][dir]", required = false) String orderDir
其中orderIndex为排序的字段,而orderDir为排序的方式(升序或者降序)。orderIndex中是前端table中字段的列号,所以通畅,还需要在后台初始化一个数组,然后再数组中取实际需要排序的字段,例如:
1 String[] cols = {"", "", "user_name", "password", "true_name", "create_time"}; 2 Result> result = userService.listPage((start / pageSize) + 1, pageSize, cols[orderIndex], orderDir);
b.一般在对列表进行了增删改查后,需要重新刷新列表,而此时,大多数情况下,想列表保持当前页面刷新,那么需要使用函数
user_tab.draw(false);
其中user_tab为table的JQuery对象,如果不需要保持此页面,去掉false即可。
c.需要冻结某列的时候,需要使用到fixedColumns函数,可以使用on进行函数回调,使用dom,进行页面统计文字的显示位置"dom": '<"top"i>rt<"bottom"flp><"clear">',
(5)PageHelper后台分页的编写
1 public Result> listPage(int pageCurrent, int pageSize, String userName, String trueName, String cols, String orderDir) { 2 Example example = new Example(TUser.class); 3 Criteria criteria = example.createCriteria(); 4 ExampleUtils.getLikeExample(criteria, "userName", userName); 5 ExampleUtils.getLikeExample(criteria, "trueName", trueName); 6 example.setOrderByClause(cols + " " + orderDir); 7 //example.orderBy(cols+" "+orderDir); 8 Result > result = new Result >(); 9 PageHelper.startPage(pageCurrent, pageSize); 10 List tUsers = userMapper.selectByExample(example); 11 PageInfo pageInfo = new PageInfo (tUsers, pageSize); 12 Page resultData = new Page ((int) pageInfo.getTotal(), pageInfo.getPages(), pageCurrent, pageSize, tUsers); 13 result.setResultData(resultData); 14 result.setErrCode(0); 15 result.setStatus(true); 16 return result; 17 }
由于,需要配个DataTable,所以需要重新编写page类,保证字段的一致性,这里就放弃了PageHelper自带的PageInfo,实际上,这2个类中,字段类型基本一致,区别不大。
(6).其它具体的代码
前端ftl:
1 DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>用户列表title> 6 head> 7 <body> 8 <div class="box-body"> 9 <div class="clearfix"> 10 <form class="form-horizontal"> 11 <input id="user_list_repeatApply" name="user_list_repeatApply" type="reset" style="display:none;"/> 12 <div class="form-group clearfix"> 13 <label class="col-md-1 control-label">登录名称label> 14 <div class="col-md-2"> 15 <input type="text" class="input-sm form-control" id="user_list_user_name" name="user_list_user_name" placeholder="请输入登录名称..."> 16 div> 17 <label class="col-md-1 control-label">用户名label> 18 <div class="col-md-2"> 19 <input type="text" class="input-sm form-control" id="user_list_true_name" name="user_list_true_name" placeholder="请输入用户名..."> 20 div> 21 <button type="button" onclick="user_list_query();" class="btn btn-sm btn-primary" ><i class="fa fa-search">i>搜索button> 22 <button type="button" onclick="user_list_add();" class="btn btn-sm btn-success" ><i class="fa fa-square-o">i>增加button> 23 <button type="button" onclick="user_list_delete('1');" class="btn btn-sm btn-danger" ><i class="fa fa-remove">i>删除button> 24 <button type="button" onclick="user_list_reset();" class="btn btn-sm btn-default">重置button> 25 div> 26 form> 27 div> 28 <table id="user_tab" class="table table-striped table-bordered table-hover"> 29 <thead> 30 <tr> 31 <th><input type="checkbox" title="全选" />th> 32 <th>序号th> 33 <th>登录名称th> 34 <th>登录密码th> 35 <th>用户名th> 36 <th>加入时间th> 37 <th>操作th> 38 tr> 39 thead> 40 table> 41 div> 42 <script type="text/javascript"> 43 var user_tab; 44 var user_list_param; 45 $(function () { 46 var url="/admin/user/listPage"; 47 user_list_setParm(); 48 user_tab = $('#user_tab').DataTable({ 49 "fnDrawCallback": function () { 50 }, 51 "dom": '<"top"i>rt<"bottom"flp><"clear">', 52 //"ordering":false,//是否排序 53 "processing": true, 54 "searching": false, 55 "serverSide": true, //启用服务器端分页 56 "order": [[ 5, "asc" ]],//默认排序字段 57 "bInfo": true, 58 "bAutoWidth": false, 59 "scrollX": true, 60 "scrollCollapse": false, 61 /*fixedColumns: { 62 leftColumns: 0, 63 rightColumns: 1 64 },*/ 65 "language":{"url":"/plugins/datatables/language.json"}, 66 "ajax":{"url":url,"data":user_list_param,"type":"post"}, 67 "columns":[ 68 {"data":"id"}, 69 {"data":null}, 70 {"data":"userName"}, 71 {"data":"password"}, 72 {"data":"trueName"}, 73 {"data":"createTime"}, 74 {"data":"id"} 75 ], 76 "columnDefs" : [ 77 { 78 targets: 0, 79 data: null, 80 orderable:false, 81 render: function (data) { 82 return ''+data+'"/>'; 83 } 84 }, 85 { 86 targets: 1, 87 data: null, 88 orderable:false, 89 render: function (data) { 90 No=No+1; 91 return No; 92 } 93 }, 94 { 95 "targets" : -1, 96 "data" : null, 97 orderable:false, 98 "render" : function(data) { 99 var data = "'"+data+"'"; 100 var btn1='修改 '; 101 var btn2 = ''+data+')">删除 '; 102 return btn1+btn2; 103 } 104 } 105 ] 106 }).on('preXhr.dt', function ( e, settings, data ) { 107 No=0; 108 }).on('xhr.dt', function(e, settings, json, xhr) { 109 }); 110 }); 111 //搜索框内容重置 112 function user_list_reset() { 113 $("input[name='user_list_repeatApply']").click(); 114 } 115 //增加 116 function user_list_add() { 117 118 } 119 //删除 120 function user_list_delete(param) { 121 var href = "/"; 122 var title = "警告! 所选取的数据将会被删除!
"; 123 var cb; 124 if(param=="1") { 125 var checkNum = $('input:checkbox[class="userCheckbox"]:checked').length; 126 var checkVal =[]; 127 if(checkNum==0) { 128 alertMsg("请选择数据
","warning"); 129 return; 130 } 131 $.each($('input:checkbox[class="userCheckbox"]:checked'),function(){ 132 checkVal.push($(this).val()); 133 }); 134 cb = "user_list_delete_data('"+checkVal+"');"; 135 } else { 136 cb = "user_list_delete_one_data('"+param+"');"; 137 } 138 $("#smModal").attr("action",href).attr("callback", cb).find(".modal-body").html(title).end().modal("show"); 139 //$("#smModal").modal("show"); 140 } 141 function user_list_delete_data(checkVal) { 142 143 var options = { 144 url: '/admin/user/delete?checkVal='+checkVal, 145 type: 'get', 146 dataType: 'text', 147 success: function (data) { 148 if(data>0) { 149 user_tab.draw(false); 150 alertMsg("成功删除
"+data+"条记录","success"); 151 } else { 152 alertMsg("删除失败
","danger"); 153 } 154 } 155 }; 156 $.ajax(options); 157 } 158 function user_list_delete_one_data(id) { 159 var options = { 160 url: '/admin/user/deleteOne?id='+id, 161 type: 'get', 162 dataType: 'text', 163 success: function (data) { 164 user_tab.draw(false); 165 alertMsg("删除成功
","success"); 166 } 167 }; 168 $.ajax(options); 169 } 170 //搜索 171 function user_list_query() { 172 user_list_setParm(); 173 user_tab.settings()[0].ajax.data = user_list_param; 174 user_tab.ajax.reload(); 175 } 176 //动态拼接参数 177 function user_list_setParm() { 178 var user_list_user_name = $("#user_list_user_name").val(); 179 var user_list_true_name = $("#user_list_true_name").val(); 180 user_list_param = { 181 "user_list_user_name" : user_list_user_name, 182 "user_list_true_name" : user_list_true_name 183 }; 184 } 185 script> 186 body> 187 html>
后台类:
控制层
1 package com.tswc.edu.controller; 2 /** 3 * @ProjectName: edu 4 * @Package: com.tswc.edu.controller 5 * @ClassName: UserContraller 6 * @Author: DengZeng 7 * @Description: ${description} 8 * @Date: 2018/12/15 15:37 9 * @Version: 1.0 10 */ 11 12 import com.tswc.edu.entity.TUser; 13 import com.tswc.edu.service.UserService; 14 import com.tswc.edu.utils.Page; 15 import com.tswc.edu.utils.PageBean; 16 import com.tswc.edu.utils.Result; 17 import org.springframework.beans.factory.annotation.Autowired; 18 import org.springframework.stereotype.Controller; 19 import org.springframework.web.bind.annotation.RequestMapping; 20 import org.springframework.web.bind.annotation.RequestMethod; 21 import org.springframework.web.bind.annotation.RequestParam; 22 import org.springframework.web.bind.annotation.ResponseBody; 23 24 /** 25 * 用户管理 26 * 27 * @author UserContraller 28 * @create 2018-12-15 15:37 29 **/ 30 @RequestMapping(value = "/admin/user") 31 @Controller 32 class UserContraller { 33 @Autowired 34 private UserService userService; 35 36 @RequestMapping(value = "/list") 37 public void list() { 38 } 39 40 //用户列表 41 @ResponseBody 42 @RequestMapping(value = "/listPage", method = RequestMethod.POST) 43 public PageBeanlistPage(@RequestParam(value = "start", defaultValue = "1") int start, 44 @RequestParam(value = "length", defaultValue = "10") int pageSize, 45 @RequestParam(value = "user_list_user_name") String userName, 46 @RequestParam(value = "user_list_true_name") String trueName, 47 @RequestParam(value = "order[0][column]", required = false) Integer orderIndex, 48 @RequestParam(value = "order[0][dir]", required = false) String orderDir) { 49 String[] cols = {"", "", "user_name", "password", "true_name", "create_time"}; 50 Result > result = userService.listPage((start / pageSize) + 1, pageSize, userName, trueName, cols[orderIndex], orderDir); 51 if (result.isStatus()) { 52 return new PageBean (result.getResultData()); 53 } 54 return new PageBean (); 55 } 56 57 //删除所选择的的数据 58 @ResponseBody 59 @RequestMapping(value = "/delete", method = RequestMethod.GET) 60 public int delete(@RequestParam(value = "checkVal") String[] ids) { 61 int result = 0; 62 result = userService.delete(ids); 63 return result; 64 } 65 66 //删除一条数据 67 @ResponseBody 68 @RequestMapping(value = "/deleteOne", method = RequestMethod.GET) 69 public void deleteOne(@RequestParam(value = "id") String id) { 70 userService.deleteOne(id); 71 } 72 73 }
服务层
1 package com.tswc.edu.service; 2 /** 3 * @ProjectName: edu 4 * @Package: com.tswc.edu.service 5 * @ClassName: UserService 6 * @Author: DengZeng 7 * @Description: ${description} 8 * @Date: 2018/12/15 21:25 9 * @Version: 1.0 10 */ 11 12 import com.github.pagehelper.PageHelper; 13 import com.github.pagehelper.PageInfo; 14 import com.tswc.edu.entity.TUser; 15 import com.tswc.edu.mapper.UserMapper; 16 import com.tswc.edu.utils.ExampleUtils; 17 import com.tswc.edu.utils.Page; 18 import com.tswc.edu.utils.Result; 19 import org.springframework.beans.factory.annotation.Autowired; 20 import org.springframework.stereotype.Service; 21 import tk.mybatis.mapper.entity.Example; 22 import tk.mybatis.mapper.entity.Example.Criteria; 23 24 import java.util.Arrays; 25 import java.util.List; 26 27 /** 28 * 用户管理服务层 29 * 30 * @author UserService 31 * @create 2018-12-15 21:25 32 **/ 33 @Service 34 public class UserService { 35 @Autowired 36 private UserMapper userMapper; 37 38 public Result> listPage(int pageCurrent, int pageSize, String userName, String trueName, String cols, String orderDir) { 39 Example example = new Example(TUser.class); 40 Criteria criteria = example.createCriteria(); 41 ExampleUtils.getLikeExample(criteria, "userName", userName); 42 ExampleUtils.getLikeExample(criteria, "trueName", trueName); 43 example.setOrderByClause(cols + " " + orderDir); 44 //example.orderBy(cols+" "+orderDir); 45 Result > result = new Result >(); 46 PageHelper.startPage(pageCurrent, pageSize); 47 List tUsers = userMapper.selectByExample(example); 48 PageInfo pageInfo = new PageInfo (tUsers, pageSize); 49 Page resultData = new Page ((int) pageInfo.getTotal(), pageInfo.getPages(), pageCurrent, pageSize, tUsers); 50 result.setResultData(resultData); 51 result.setErrCode(0); 52 result.setStatus(true); 53 return result; 54 } 55 56 public int delete(String[] ids) { 57 List idList = Arrays.asList(ids); 58 Example example = new Example(TUser.class); 59 Criteria criteria = example.createCriteria(); 60 criteria.andIn("id", idList); 61 return userMapper.deleteByExample(example); 62 } 63 64 public void deleteOne(String id) { 65 userMapper.deleteByPrimaryKey(id); 66 } 67 }
Mapper接口
1 package com.tswc.edu.mapper; 2 3 import com.tswc.edu.entity.TUser; 4 import com.tswc.edu.utils.MyMapper; 5 6 public interface UserMapper extends MyMapper{ 7 }
(7).最终效果