springBoot整合myBatis後臺分頁+bootstrapTable展示
阿新 • • 發佈:2019-01-06
1.配置mybatis後臺分頁外掛
後臺sql當包含List語句自動進行後臺分頁攔截操作
2.PagePlugin編寫
package com.javon.boot.util; import java.lang.reflect.Field; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.List; import java.util.Properties; import javax.xml.bind.PropertyException; import com.javon.boot.vo.Page; import org.apache.commons.lang3.StringUtils; import org.apache.ibatis.executor.ErrorContext; import org.apache.ibatis.executor.ExecutorException; import org.apache.ibatis.executor.statement.BaseStatementHandler; import org.apache.ibatis.executor.statement.RoutingStatementHandler; import org.apache.ibatis.executor.statement.StatementHandler; import org.apache.ibatis.mapping.BoundSql; import org.apache.ibatis.mapping.MappedStatement; import org.apache.ibatis.mapping.ParameterMapping; import org.apache.ibatis.mapping.ParameterMode; import org.apache.ibatis.plugin.Interceptor; import org.apache.ibatis.plugin.Intercepts; import org.apache.ibatis.plugin.Invocation; import org.apache.ibatis.plugin.Plugin; import org.apache.ibatis.plugin.Signature; import org.apache.ibatis.reflection.MetaObject; import org.apache.ibatis.reflection.property.PropertyTokenizer; import org.apache.ibatis.scripting.xmltags.ForEachSqlNode; import org.apache.ibatis.session.Configuration; import org.apache.ibatis.type.TypeHandler; import org.apache.ibatis.type.TypeHandlerRegistry; /** * * @ClassName: PagePlugin * @Description: TODO(這裡用一句話描述這個類的作用) * @author * @date 2015年8月6日 下午8:21:28 * */ @Intercepts({ @Signature(type = StatementHandler.class, method = "prepare", args = { Connection.class, Integer.class }) }) public class PagePlugin implements Interceptor { private static String dialect = ""; //資料庫方言 private static String pageSqlId = ""; //mapper.xml中需要攔截的ID(正則匹配) public Object intercept(Invocation ivk) throws Throwable { // TODO Auto-generated method stub if(ivk.getTarget() instanceof RoutingStatementHandler){ RoutingStatementHandler statementHandler = (RoutingStatementHandler)ivk.getTarget(); BaseStatementHandler delegate = (BaseStatementHandler) ReflectHelper.getValueByFieldName(statementHandler, "delegate"); MappedStatement mappedStatement = (MappedStatement) ReflectHelper.getValueByFieldName(delegate, "mappedStatement"); if(mappedStatement.getId().matches(pageSqlId)){ //攔截需要分頁的SQL BoundSql boundSql = delegate.getBoundSql(); Object parameterObject = boundSql.getParameterObject();//分頁SQL<select>中parameterType屬性對應的實體引數,即Mapper介面中執行分頁方法的引數,該引數不得為空 if(parameterObject==null){ throw new NullPointerException("parameterObject尚未例項化!"); }else{ Connection connection = (Connection) ivk.getArgs()[0]; String sql = boundSql.getSql(); //String countSql = "select count(0) from (" + sql+ ") as tmp_count"; //記錄統計 String countSql = "select count(0) from (" + sql+ ") tmp_count"; //記錄統計 == oracle 加 as 報錯(SQL command not properly ended) PreparedStatement countStmt = connection.prepareStatement(countSql); BoundSql countBS = new BoundSql(mappedStatement.getConfiguration(),countSql,boundSql.getParameterMappings(),parameterObject); setParameters(countStmt,mappedStatement,countBS,parameterObject); ResultSet rs = countStmt.executeQuery(); int count = 0; if (rs.next()) { count = rs.getInt(1); } rs.close(); countStmt.close(); //System.out.println(count); Page page = null; if(parameterObject instanceof Page){ //引數就是Page實體 page = (Page) parameterObject; //見com.jalan.entity.Page.entityOrField 註釋 page.setTotalResult(count); }else{ //引數為某個實體,該實體擁有Page屬性 Field pageField = ReflectHelper.getFieldByFieldName(parameterObject,"page"); if(pageField!=null){ page = (Page) ReflectHelper.getValueByFieldName(parameterObject,"page"); if(page==null) page = new Page(); //見com.jalan.entity.Page.entityOrField 註釋 page.setTotalResult(count); ReflectHelper.setValueByFieldName(parameterObject,"page", page); //通過反射,對實體物件設定分頁物件 }else{ throw new NoSuchFieldException(parameterObject.getClass().getName()+"不存在 page 屬性!"); } } String pageSql = generatePageSql(sql,page); ReflectHelper.setValueByFieldName(boundSql, "sql", pageSql); //將分頁sql語句反射回BoundSql. } } } return ivk.proceed(); } /** * 對SQL引數(?)設值,參考org.apache.ibatis.executor.parameter.DefaultParameterHandler * @param ps * @param mappedStatement * @param boundSql * @param parameterObject * @throws SQLException */ private void setParameters(PreparedStatement ps,MappedStatement mappedStatement,BoundSql boundSql,Object parameterObject) throws SQLException { ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId()); List<ParameterMapping> parameterMappings = boundSql.getParameterMappings(); if (parameterMappings != null) { Configuration configuration = mappedStatement.getConfiguration(); TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry(); MetaObject metaObject = parameterObject == null ? null: configuration.newMetaObject(parameterObject); for (int i = 0; i < parameterMappings.size(); i++) { ParameterMapping parameterMapping = parameterMappings.get(i); if (parameterMapping.getMode() != ParameterMode.OUT) { Object value; String propertyName = parameterMapping.getProperty(); PropertyTokenizer prop = new PropertyTokenizer(propertyName); if (parameterObject == null) { value = null; } else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) { value = parameterObject; } else if (boundSql.hasAdditionalParameter(propertyName)) { value = boundSql.getAdditionalParameter(propertyName); } else if (propertyName.startsWith(ForEachSqlNode.ITEM_PREFIX)&& boundSql.hasAdditionalParameter(prop.getName())) { value = boundSql.getAdditionalParameter(prop.getName()); if (value != null) { value = configuration.newMetaObject(value).getValue(propertyName.substring(prop.getName().length())); } } else { value = metaObject == null ? null : metaObject.getValue(propertyName); } TypeHandler typeHandler = parameterMapping.getTypeHandler(); if (typeHandler == null) { throw new ExecutorException("There was no TypeHandler found for parameter "+ propertyName + " of statement "+ mappedStatement.getId()); } typeHandler.setParameter(ps, i + 1, value, parameterMapping.getJdbcType()); } } } } /** * 根據資料庫方言,生成特定的分頁sql * @param sql * @param page * @return */ private String generatePageSql(String sql,Page page){ if(page!=null && StringUtils.isNotEmpty(dialect)){ StringBuffer pageSql = new StringBuffer(); if("mysql".equals(dialect)){ pageSql.append(sql); pageSql.append(" limit "+page.getCurrentResult()+","+page.getShowCount()); }else if("oracle".equals(dialect)){ pageSql.append("select * from (select tmp_tb.*,ROWNUM row_id from ("); pageSql.append(sql); //pageSql.append(") as tmp_tb where ROWNUM<="); pageSql.append(") tmp_tb where ROWNUM<="); pageSql.append(page.getCurrentResult()+page.getShowCount()); pageSql.append(") where row_id>"); pageSql.append(page.getCurrentResult()); } return pageSql.toString(); }else{ return sql; } } public Object plugin(Object arg0) { // TODO Auto-generated method stub return Plugin.wrap(arg0, this); } public void setProperties(Properties p) { dialect = p.getProperty("dialect"); if (StringUtils.isEmpty(dialect)) { try { throw new PropertyException("dialect property is not found!"); } catch (PropertyException e) { // TODO Auto-generated catch block e.printStackTrace(); } } pageSqlId = p.getProperty("pageSqlId"); if (StringUtils.isEmpty(pageSqlId)) { try { throw new PropertyException("pageSqlId property is not found!"); } catch (PropertyException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
3.page實體編寫,可以自定義改造
package com.javon.boot.vo; import java.util.HashMap; import java.util.Map; public class Page { private int showCount; //每頁顯示記錄數 private int totalPage; //總頁數 private int totalResult; //總記錄數 private int currentPage; //當前頁 private int currentResult; //當前記錄起始索引 private Map<String, Object> params = new HashMap<String, Object>();// 傳入查詢引數 public Map<String, Object> getParams() { return params; } public void setParams(Map<String, Object> params) { this.params = params; } public Page() { try { this.showCount = 10; } catch (Exception e) { this.showCount = 20; } } public int getTotalPage() { if (totalResult % showCount == 0) totalPage = totalResult / showCount; else totalPage = totalResult / showCount + 1; return totalPage; } public void setTotalPage(int totalPage) { this.totalPage = totalPage; } public int getTotalResult() { return totalResult; } public void setTotalResult(int totalResult) { this.totalResult = totalResult; } public int getCurrentPage() { if (currentPage <= 0) currentPage = 1; if (currentPage > getTotalPage()) currentPage = getTotalPage(); return currentPage; } public void setCurrentPage(int currentPage) { this.currentPage = currentPage; } public int getShowCount() { return showCount; } public void setShowCount(int showCount) { this.showCount = showCount; } public int getCurrentResult() { currentResult = (getCurrentPage() - 1) * getShowCount(); if (currentResult < 0) currentResult = 0; return currentResult; } public void setCurrentResult(int currentResult) { this.currentResult = currentResult; } }
4.mybatis.xml檔案使用分頁page物件
4.dao層編寫<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//ibatis.apache.org//DTD Mapper 3.0//EN" "http://ibatis.apache.org/dtd/ibatis-3-mapper.dtd"> <mapper namespace="com.javon.boot.dao.SysLogDao"> <resultMap id="rm" type="SysLog"> <result property="id" jdbcType="INTEGER" column="id"/> <result property="userName" jdbcType="VARCHAR" column="user_name"/> <result property="userId" jdbcType="INTEGER" column="user_id"/> <result property="description" jdbcType="VARCHAR" column="description"/> <result property="method" jdbcType="VARCHAR" column="method"/> <result property="params" jdbcType="VARCHAR" column="params"/> <result property="ip" jdbcType="VARCHAR" column="ip"/> <result property="createTime" jdbcType="TIMESTAMP" column="create_time"/> </resultMap> <sql id="Base_Column_List"> id, user_name, user_id, description, method, params, ip, create_time </sql> <!-- 插入 --> <insert id="insert"> INSERT INTO sys_log ( user_name, user_id, description, method, params, ip, create_time ) VALUES ( #{userName}, #{userId}, #{description}, #{method}, #{params}, #{ip}, now() ) </insert> <!-- 集合查詢 --> <select id="queryList" resultMap="rm" parameterType="Page"> SELECT <include refid="Base_Column_List"/> FROM sys_log <where> <if test="params['name'] !=null and params['name'] !=''"> and (user_name like '%${params.name}%' or description like '%${params.name}%' or method like '%${params.name}%' or ip like '%${params.name}%') </if> </where> ORDER BY create_time desc </select> </mapper>
package com.javon.boot.dao;
import com.javon.boot.vo.Page;
import com.javon.boot.vo.SysLog;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
* Created by admin on 2018/3/30.
*/
@Mapper
public interface SysLogDao {
void insert(SysLog sysLog);
List<SysLog> queryList(Page page);
}
5.service層
package com.javon.boot.service.impl;
import com.javon.boot.dao.SysLogDao;
import com.javon.boot.service.SysLogService;
import com.javon.boot.vo.Page;
import com.javon.boot.vo.SysLog;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
/**
* Created by admin on 2018/3/30.
*/
@Service
public class SysLogServiceImpl implements SysLogService {
@Resource
private SysLogDao sysLogDao;
@Override
public void insert(SysLog sysLog) {
sysLogDao.insert(sysLog);
}
@Override
public List<SysLog> queryList(Page page) {
return sysLogDao.queryList(page);
}
}
5.controller層
package com.javon.boot.controller.sys;
import com.javon.boot.service.SysLogService;
import com.javon.boot.util.PageUtils;
import com.javon.boot.vo.Page;
import com.javon.boot.vo.SysLog;
import com.javon.boot.vo.SysUser;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Created by admin on 2018/3/30.
*/
@RequestMapping("/sys/log")
@Controller
public class SysLogController {
private static final String SYSUSERPREFIX = "system/log";
@Resource
private SysLogService sysLogService;
@RequiresPermissions("sys:log:log")
@RequestMapping(value = "", method = RequestMethod.GET)
String log(Model model) {
return SYSUSERPREFIX + "/log";
}
@RequiresPermissions("sys:log:log")
@RequestMapping(value = "/list", method = RequestMethod.GET)
@ResponseBody
public PageUtils list(String name, String date, String pageNumber, String pageSize) {
if (!StringUtils.isNotBlank(pageNumber) & !StringUtils.isNotBlank(pageSize)) {
pageNumber = "1";
pageSize = "15";
}
Map<String, Object> params = new HashMap<String, Object>();
params.put("name", name);
// params.put("deptId", date);
Page page = new Page();
page.setParams(params);
page.setCurrentPage(Integer.valueOf(pageNumber));
page.setShowCount(Integer.valueOf(pageSize));
List<SysLog> logList = sysLogService.queryList(page);
return new PageUtils(logList, page.getTotalResult());//組裝成前端所需格式資料
}
}
6.
PageUtils+js+html
package com.javon.boot.util;
import java.io.Serializable;
import java.util.List;
/**
* 構造出前端需要分頁顯示資訊
*/
public class PageUtils implements Serializable {
private static final long serialVersionUID = 1L;
private int total;
private List<?> rows;
public PageUtils(List<?> list, int total) {
this.rows = list;
this.total = total;
}
public int getTotal() {
return total;
}
public void setTotal(int total) {
this.total = total;
}
public List<?> getRows() {
return rows;
}
public void setRows(List<?> rows) {
this.rows = rows;
}
}
var prefix = "/sys/log"
$(function() {
load();
});
function load() {
$('#exampleTable')
.bootstrapTable(
{
method : 'get', // 伺服器資料的請求方式 get or post
url : prefix + "/list", // 伺服器資料的載入地址
iconSize : 'outline',
toolbar : '#exampleToolbar',
striped : true, // 設定為true會有隔行變色效果
dataType : "json", // 伺服器返回的資料型別
singleSelect : false, // 設定為true將禁止多選
queryParamsType:'',
pageSize : 10, // 如果設定了分頁,每頁資料條數
pageNumber : 1, // 如果設定了分佈,首頁頁碼
sidePagination : "server", // 設定在哪裡進行分頁,可選值為"client" 或者
pagination: true,//是否開啟分頁(*)啟動分頁,必須設為true
pageList: [10,20],//可供選擇的每頁的行數(*)
queryParams : function(params) {
return {
// 說明:傳入後臺的引數包括offset開始索引,limit步長,sort排序列,order:desc或者,以及所有列的鍵值
pageSize : params.pageSize,
pageNumber : params.pageNumber,
name : $('#searchName').val(),
date : $('#createTime').val()
};
},
columns : [
{
field : 'userName',
title : '操作人'
},
{
field : 'description',
title : '描述'
},
{
field : 'method', // 列欄位名
title : '請求方法' // 列標題
},
{
field : 'params', // 列欄位名
title : '請求引數' // 列標題
},
{
field : 'ip',
title : '操作IP'
},
{
field : 'createTime',
title : '操作時間',
//獲取日期列的值進行轉換
formatter: function (value, row, index) {
return changeDateFormat(value)
}
}
]
});
}
function reLoad() {
$('#exampleTable').bootstrapTable('refresh');
}
<!DOCTYPE html>
<html lang="zh_CN" xmlns:th="http://www.thymeleaf.org">
<meta charset="utf-8"/>
<head th:include="include::header"></head>
<body class="gray-bg">
<div class="wrapper wrapper-content ">
<div class="col-sm-12">
<div class="ibox">
<div class="ibox-body">
<div class="fixed-table-toolbar">
<div class="columns pull-right">
<button class="btn btn-success" onclick="reLoad()">查詢</button>
</div>
<div class="columns pull-right col-md-2 nopadding">
<input id="searchName" type="text" class="form-control" placeholder=" 內容 "
/>
</div>
<div class="layui-inline columns pull-right col-md-4 nopadding">
<div class="layui-input-inline">
<input type="text" class="layui-input form-control" id="createTime" placeholder=" 時間範圍 " lay-key="11"/>
</div>
</div>
</div>
<table id="exampleTable" data-mobile-responsive="true">
</table>
</div>
</div>
</div>
</div>
<div th:include="include::footer"></div>
<script type="text/javascript" src="/js/appjs/sys/log/log.js"></script>
<script>
laydate.render({
elem: '#createTime'
,type: 'datetime'
,range: true
});
</script>
</body>
</html>