内容简介:Spring boot入门(三):SpringBoot集成结合AdminLTE(Freemarker),利用generate自动生成代码,利用DataTable和PageHelper进行分页显示标题太长,本博客在博客园中位置:
Spring boot入门(三):SpringBoot集成结合AdminLTE(Freemarker),利用generate自动生成代码,利用DataTable和PageHelper进行分页显示
标题太长,本博客在博客园中位置:
关于SpringBoot和PageHelper,前篇博客已经介绍过, Spring boot入门(二):Spring boot集成MySql,Mybatis和PageHelper插件 ,前篇博客大致讲述了SpringBoot如何集成Mybatis和Pagehelper,但是没有做出实际的范例,本篇博客是连接上一篇写的。通过AdminLTE前端框架,利用DataTable和PageHelper进行分页显示,通过对用户列表的增删改查操作,演示DataTable和PageHelper的使用。
1. AdminLTE介绍
AdminLTE 是一个完全响应管理模板。基于 Bootstrap3 框架,易定制模板。适合多种屏幕分辨率,从小型移动设备到大型台式机。内置了多个页面,包括仪表盘、邮箱、日历、锁屏、登录及注册、404 错误、500 错误等页面。具体介绍见官方网站:adminlte.io/,我们可以直接从此网站下载该模板,其外观如下:
2. SpringBoot后台集成AdminLTE
首先在官网下载AdminLTE模板,然后将此模板的全部文件拷贝到项目下:
拷贝后,将 AdminLTE 文件进行了拆分,其中 base 里面是AdminLTE自带的所有 JS 包和 css 文件,main中是AdminLTE主页面渲染页面,index 是入口。这么做的目的:直接将 base 通过 FreeMarker 中宏的形式引入到index 入口页面中,那么所有的 JS 文件将一直曾在最底层的页面下,在后期的其它页面的开发中,不需要再次引入 JS 包,避免 JS 包混乱。
启动项目:
3.配置代码生成器generate
generate 的介绍比较多,此处直接介绍配置的步骤及代码
编写 generatorConfig.xml 文件,并放在 templates 根目录下,若放在其它目录中,则需要在 pom.xml 中配置路径,否则,编译的时候无法通过。具体错误:
[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] [ERROR] [ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch. [ERROR] Re-run Maven using the -X switch to enable full debug logging. [ERROR] [ERROR] For more information about the errors and possible solutions, please read the following articles: [ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException 复制代码
generatorConfig.xml 的脚本如下,其中 targetProject 的路径需要曾在,否则会报错,参考 blog.csdn.net/hh680821/ar…
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd"> <generatorConfiguration> <!-- <properties resource="application.properties"/>--> <context id="Mysql" targetRuntime="MyBatis3Simple" defaultModelType="flat"> <!--属性配置 --> <property name="beginningDelimiter" value="`"/> <property name="endingDelimiter" value="`"/> <!--去除注释 --> <commentGenerator> <property name="suppressAllComments" value="true" /> </commentGenerator> <!--如果mapper接口需要实现其它接口,那么需要配置MapperPlugin,value中是实现的接口或类名 --> <plugin type="tk.mybatis.mapper.generator.MapperPlugin"> <property name="mappers" value="com.tswc.edu.utils.MyMapper"/> </plugin> <!--一定要放在plugin下面,否则报错 --> <commentGenerator> <property name="suppressAllComments" value="true" /> </commentGenerator> <!--数据库连接池--> <jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://localhost:3306/edu" userId="root" password="123456"> </jdbcConnection> <!--自动生成实体类--> <javaModelGenerator targetPackage="generator" targetProject="src/main/java"/> <!--自动生成map接口--> <sqlMapGenerator targetPackage="generator" targetProject="src/main/java"/> <!--自动生成mybatis的xml文件--> <javaClientGenerator targetPackage="generator" targetProject="src/main/java" type="XMLMAPPER"/> <!--数据库表名,此处如果需要去掉某个自带函数,需要添加参数--> <!--1,schema:数据库的schema; 2,catalog:数据库的catalog; 3,alias:为数据表设置的别名,如果设置了alias,那么生成的所有的SELECT SQL语句中,列名会变成:alias_actualColumnName 4,domainObjectName:生成的domain类的名字,如果不设置,直接使用表名作为domain类的名字;可以设置为somepck.domainName,那么会自动把domainName类再放到somepck包里面; 5,enableInsert(默认true):指定是否生成insert语句; 6,enableSelectByPrimaryKey(默认true):指定是否生成按照主键查询对象的语句(就是getById或get); 7,enableSelectByExample(默认true):MyBatis3Simple为false,指定是否生成动态查询语句; 8,enableUpdateByPrimaryKey(默认true):指定是否生成按照主键修改对象的语句(即update); 9,enableDeleteByPrimaryKey(默认true):指定是否生成按照主键删除对象的语句(即delete); 10,enableDeleteByExample(默认true):MyBatis3Simple为false,指定是否生成动态删除语句; 11,enableCountByExample(默认true):MyBatis3Simple为false,指定是否生成动态查询总条数语句(用于分页的总条数查询); 12,enableUpdateByExample(默认true):MyBatis3Simple为false,指定是否生成动态修改语句(只修改对象中不为空的属性); 13,modelType:参考context元素的defaultModelType,相当于覆盖; 14,delimitIdentifiers:参考tableName的解释,注意,默认的delimitIdentifiers是双引号,如果类似 MYSQL 这样的数据库,使用的是`(反引号,那么还需要设置context的beginningDelimiter和endingDelimiter属性) 15,delimitAllColumns:设置是否所有生成的 SQL 中的列名都使用标识符引起来。默认为false,delimitIdentifiers参考context的属性 注意,table里面很多参数都是对javaModelGenerator,context等元素的默认属性的一个复写;--> <table tableName="t_user"> <generatedKey column="id" sqlStatement="Mysql" identity="true"/> </table> </context> </generatorConfiguration> 复制代码
假设产生此错误:
[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] [ERROR] [ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch. [ERROR] Re-run Maven using the -X switch to enable full debug logging. [ERROR] [ERROR] For more information about the errors and possible solutions, please read the following articles: [ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException 复制代码
原因就是:generate 中,标签都是有顺序的,此类错误就是标签的顺序存在问题
此时,xml 文件以及配置结束,需要在 idea 中配置启动操作:mybatis-generator:generate,如图
4.DataTable 的使用
DataTable 是一款简单易用的分页插件,基于 JQuery 写的,里面提供了丰富的分页参数,主要通过 Ajax 实现数据的前后端传输
首先引入 JS 和 CSS 包:
<link rel="stylesheet" href="https://cdn.datatables.net/1.10.16/css/jquery.dataTables.min.css" /> <script src="https://cdn.datatables.net/1.10.16/js/jquery.dataTables.min.js"></script> 复制代码
其外,还需要格式化相关提示文字,一般命名为:language.json
{ "sEmptyTable": "没有相关数据", "sInfo": "从 _START_ 到 _END_ 条记录 总记录数为 _TOTAL_ 条", "sInfoEmpty": "记录数为0", "sInfoFiltered": "(全部记录数 _MAX_ 条)", "sInfoPostFix": "", "sInfoThousands": ",", "sLengthMenu": "显示 _MENU_ 条", "sLoadingRecords": "正在加载...", "sProcessing": "正在获取数据,请稍候...", "sSearch": "搜索", "sZeroRecords": "没有您要搜索的内容", "oPaginate": { "sFirst": "首页", "sPrevious": "上一页", "sNext": "下一页", "sLast": "尾页", "sJump": "跳转" }, "oAria": { "sSortAscending": ": 以升序排序", "sSortDescending": ": 以降序排序" } } 复制代码
具体的实现方式如下代码:
var user_tab; var user_list_param; $(function () { var url="/admin/user/listPage"; user_list_setParm(); user_tab = $('#user_tab').DataTable({ "fnDrawCallback": function () { }, "dom": '<"top"i>rt<"bottom"flp><"clear">', //"ordering":false,//是否排序 "processing": true, "searching": false, "serverSide": true, //启用服务器端分页 "order": [[ 5, "asc" ]],//默认 排序 字段 "bInfo": true, "bAutoWidth": false, "scrollX": true, "scrollCollapse": false, /*fixedColumns: { leftColumns: 0, rightColumns: 1 },*/ "language":{"url":"/plugins/datatables/language.json"}, "ajax":{"url":url,"data":user_list_param,"type":"post"}, "columns":[ {"data":"id"}, {"data":null}, {"data":"userName"}, {"data":"password"}, {"data":"trueName"}, {"data":"createTime"}, {"data":"id"} ], "columnDefs" : [ { targets: 0, data: null, orderable:false, render: function (data) { return '<input type="checkbox" class="userCheckbox" value="'+data+'"/>'; } }, { targets: 1, data: null, orderable:false, render: function (data) { No=No+1; return No; } }, { "targets" : -1, "data" : null, orderable:false, "render" : function(data) { var data = "'"+data+"'"; var btn1='<a class="btn btn-xs btn-warning" target="modal" modal="hg" href=""><i class="fa fa-edit"></i>修改</a> '; 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> '; return btn1+btn2; } } ] }).on('preXhr.dt', function ( e, settings, data ) { No=0; }).on('xhr.dt', function(e, settings, json, xhr) { }); }); 复制代码
这里面需要说明的:
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<Page<TUser>> 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后台分页的编写
public Result<Page<TUser>> listPage(int pageCurrent, int pageSize, String userName, String trueName, String cols, String orderDir) { Example example = new Example(TUser.class); Criteria criteria = example.createCriteria(); ExampleUtils.getLikeExample(criteria, "userName", userName); ExampleUtils.getLikeExample(criteria, "trueName", trueName); example.setOrderByClause(cols + " " + orderDir); //example.orderBy(cols+" "+orderDir); Result<Page<TUser>> result = new Result<Page<TUser>>(); PageHelper.startPage(pageCurrent, pageSize); List<TUser> tUsers = userMapper.selectByExample(example); PageInfo<TUser> pageInfo = new PageInfo<TUser>(tUsers, pageSize); Page<TUser> resultData = new Page<TUser>((int) pageInfo.getTotal(), pageInfo.getPages(), pageCurrent, pageSize, tUsers); result.setResultData(resultData); result.setErrCode(0); result.setStatus(true); return result; } 复制代码
由于,需要配个DataTable,所以需要重新编写page类,保证字段的一致性,这里就放弃了PageHelper自带的PageInfo,实际上,这2个类中,字段类型基本一致,区别不大。
6.其它具体的代码
前端ftl:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>用户列表</title> </head> <body> <div class="box-body"> <div class="clearfix"> <form class="form-horizontal"> <input id="user_list_repeatApply" name="user_list_repeatApply" type="reset" style="display:none;"/> <div class="form-group clearfix"> <label class="col-md-1 control-label">登录名称</label> <div class="col-md-2"> <input type="text" class="input-sm form-control" id="user_list_user_name" name="user_list_user_name" placeholder="请输入登录名称..."> </div> <label class="col-md-1 control-label">用户名</label> <div class="col-md-2"> <input type="text" class="input-sm form-control" id="user_list_true_name" name="user_list_true_name" placeholder="请输入用户名..."> </div> <button type="button" onclick="user_list_query();" class="btn btn-sm btn-primary" ><i class="fa fa-search"></i>搜索</button> <button type="button" onclick="user_list_add();" class="btn btn-sm btn-success" ><i class="fa fa-square-o"></i>增加</button> <button type="button" onclick="user_list_delete('1');" class="btn btn-sm btn-danger" ><i class="fa fa-remove"></i>删除</button> <button type="button" onclick="user_list_reset();" class="btn btn-sm btn-default">重置</button> </div> </form> </div> <table id="user_tab" class="table table-striped table-bordered table-hover"> <thead> <tr> <th><input type="checkbox" title="全选" /></th> <th>序号</th> <th>登录名称</th> <th>登录密码</th> <th>用户名</th> <th>加入时间</th> <th>操作</th> </tr> </thead> </table> </div> <script type="text/javascript"> var user_tab; var user_list_param; $(function () { var url="/admin/user/listPage"; user_list_setParm(); user_tab = $('#user_tab').DataTable({ "fnDrawCallback": function () { }, "dom": '<"top"i>rt<"bottom"flp><"clear">', //"ordering":false,//是否排序 "processing": true, "searching": false, "serverSide": true, //启用服务器端分页 "order": [[ 5, "asc" ]],//默认排序字段 "bInfo": true, "bAutoWidth": false, "scrollX": true, "scrollCollapse": false, /*fixedColumns: { leftColumns: 0, rightColumns: 1 },*/ "language":{"url":"/plugins/datatables/language.json"}, "ajax":{"url":url,"data":user_list_param,"type":"post"}, "columns":[ {"data":"id"}, {"data":null}, {"data":"userName"}, {"data":"password"}, {"data":"trueName"}, {"data":"createTime"}, {"data":"id"} ], "columnDefs" : [ { targets: 0, data: null, orderable:false, render: function (data) { return '<input type="checkbox" class="userCheckbox" value="'+data+'"/>'; } }, { targets: 1, data: null, orderable:false, render: function (data) { No=No+1; return No; } }, { "targets" : -1, "data" : null, orderable:false, "render" : function(data) { var data = "'"+data+"'"; var btn1='<a class="btn btn-xs btn-warning" target="modal" modal="hg" href=""><i class="fa fa-edit"></i>修改</a> '; 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> '; return btn1+btn2; } } ] }).on('preXhr.dt', function ( e, settings, data ) { No=0; }).on('xhr.dt', function(e, settings, json, xhr) { }); }); //搜索框内容重置 function user_list_reset() { $("input[name='user_list_repeatApply']").click(); } //增加 function user_list_add() { } //删除 function user_list_delete(param) { var href = "/"; var title = "<p>警告! 所选取的数据将会被删除!</p>"; var cb; if(param=="1") { var checkNum = $('input:checkbox[class="userCheckbox"]:checked').length; var checkVal =[]; if(checkNum==0) { alertMsg("<p>请选择数据</p>","warning"); return; } $.each($('input:checkbox[class="userCheckbox"]:checked'),function(){ checkVal.push($(this).val()); }); cb = "user_list_delete_data('"+checkVal+"');"; } else { cb = "user_list_delete_one_data('"+param+"');"; } $("#smModal").attr("action",href).attr("callback", cb).find(".modal-body").html(title).end().modal("show"); //$("#smModal").modal("show"); } function user_list_delete_data(checkVal) { var options = { url: '/admin/user/delete?checkVal='+checkVal, type: 'get', dataType: 'text', success: function (data) { if(data>0) { user_tab.draw(false); alertMsg("<p>成功删除"+data+"条记录</p>","success"); } else { alertMsg("<p>删除失败</p>","danger"); } } }; $.ajax(options); } function user_list_delete_one_data(id) { var options = { url: '/admin/user/deleteOne?id='+id, type: 'get', dataType: 'text', success: function (data) { user_tab.draw(false); alertMsg("<p>删除成功</p>","success"); } }; $.ajax(options); } //搜索 function user_list_query() { user_list_setParm(); user_tab.settings()[0].ajax.data = user_list_param; user_tab.ajax.reload(); } //动态拼接参数 function user_list_setParm() { var user_list_user_name = $("#user_list_user_name").val(); var user_list_true_name = $("#user_list_true_name").val(); user_list_param = { "user_list_user_name" : user_list_user_name, "user_list_true_name" : user_list_true_name }; } </script> </body> </html> 复制代码
后台类:
控制层
package com.tswc.edu.controller; /** * @ProjectName: edu * @Package: com.tswc.edu.controller * @ClassName: UserContraller * @Author: DengZeng * @Description: ${description} * @Date: 2018/12/15 15:37 * @Version: 1.0 */ import com.tswc.edu.entity.TUser; import com.tswc.edu.service.UserService; import com.tswc.edu.utils.Page; import com.tswc.edu.utils.PageBean; import com.tswc.edu.utils.Result; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; /** * 用户管理 * * @author UserContraller * @create 2018-12-15 15:37 **/ @RequestMapping(value = "/admin/user") @Controller class UserContraller { @Autowired private UserService userService; @RequestMapping(value = "/list") public void list() { } //用户列表 @ResponseBody @RequestMapping(value = "/listPage", method = RequestMethod.POST) public PageBean<TUser> listPage(@RequestParam(value = "start", defaultValue = "1") int start, @RequestParam(value = "length", defaultValue = "10") int pageSize, @RequestParam(value = "user_list_user_name") String userName, @RequestParam(value = "user_list_true_name") String trueName, @RequestParam(value = "order[0][column]", required = false) Integer orderIndex, @RequestParam(value = "order[0][dir]", required = false) String orderDir) { String[] cols = {"", "", "user_name", "password", "true_name", "create_time"}; Result<Page<TUser>> result = userService.listPage((start / pageSize) + 1, pageSize, userName, trueName, cols[orderIndex], orderDir); if (result.isStatus()) { return new PageBean<TUser>(result.getResultData()); } return new PageBean<TUser>(); } //删除所选择的的数据 @ResponseBody @RequestMapping(value = "/delete", method = RequestMethod.GET) public int delete(@RequestParam(value = "checkVal") String[] ids) { int result = 0; result = userService.delete(ids); return result; } //删除一条数据 @ResponseBody @RequestMapping(value = "/deleteOne", method = RequestMethod.GET) public void deleteOne(@RequestParam(value = "id") String id) { userService.deleteOne(id); } } 复制代码
服务层
package com.tswc.edu.service; /** * @ProjectName: edu * @Package: com.tswc.edu.service * @ClassName: UserService * @Author: DengZeng * @Description: ${description} * @Date: 2018/12/15 21:25 * @Version: 1.0 */ import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageInfo; import com.tswc.edu.entity.TUser; import com.tswc.edu.mapper.UserMapper; import com.tswc.edu.utils.ExampleUtils; import com.tswc.edu.utils.Page; import com.tswc.edu.utils.Result; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import tk.mybatis.mapper.entity.Example; import tk.mybatis.mapper.entity.Example.Criteria; import java.util.Arrays; import java.util.List; /** * 用户管理服务层 * * @author UserService * @create 2018-12-15 21:25 **/ @Service public class UserService { @Autowired private UserMapper userMapper; public Result<Page<TUser>> listPage(int pageCurrent, int pageSize, String userName, String trueName, String cols, String orderDir) { Example example = new Example(TUser.class); Criteria criteria = example.createCriteria(); ExampleUtils.getLikeExample(criteria, "userName", userName); ExampleUtils.getLikeExample(criteria, "trueName", trueName); example.setOrderByClause(cols + " " + orderDir); //example.orderBy(cols+" "+orderDir); Result<Page<TUser>> result = new Result<Page<TUser>>(); PageHelper.startPage(pageCurrent, pageSize); List<TUser> tUsers = userMapper.selectByExample(example); PageInfo<TUser> pageInfo = new PageInfo<TUser>(tUsers, pageSize); Page<TUser> resultData = new Page<TUser>((int) pageInfo.getTotal(), pageInfo.getPages(), pageCurrent, pageSize, tUsers); result.setResultData(resultData); result.setErrCode(0); result.setStatus(true); return result; } public int delete(String[] ids) { List<String> idList = Arrays.asList(ids); Example example = new Example(TUser.class); Criteria criteria = example.createCriteria(); criteria.andIn("id", idList); return userMapper.deleteByExample(example); } public void deleteOne(String id) { userMapper.deleteByPrimaryKey(id); } } 复制代码
Mapper 接口
package com.tswc.edu.mapper; import com.tswc.edu.entity.TUser; import com.tswc.edu.utils.MyMapper; public interface UserMapper extends MyMapper<TUser> { } 复制代码
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。