Mybatis plugin pagination + Spring MVC

In this post we will write a pagination using mybatis and Spring MVC 4.

《Mybatis plugin pagination + Spring MVC》

Create Controller

package com.npf.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import com.npf.model.entity.Student;
import com.npf.model.vo.PageParams;
import com.npf.service.StudentService;

@Controller
public class StudentController {

	@Autowired
	private StudentService studentService;
	
	@RequestMapping("/student/find")
	public ModelAndView findStudentPagination(ModelAndView modelAndView,PageParams pageParams){
		List<Student> stuList = studentService.fetchStudentPagination(pageParams);
		modelAndView.addObject("stuList", stuList);
		modelAndView.addObject("pageParams", pageParams);
		modelAndView.setViewName("list");
		return modelAndView;
	}
	
}

Configuration

sqlMapConfig.xml

<?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>

	<plugins>
		<plugin interceptor="com.npf.plugin.PaginationPlugin">
			<property name="defaultPage" value="1"/>
			<property name="defaultPageSize" value="5"/>
			<property name="defaultUseFlag" value="true"/>
			<property name="defaultCheckFlag" value="true"/>
		</plugin>
	</plugins>


	<mappers>
		<package name="com.npf.dao"/>
	</mappers>

</configuration>


mybatis plugin:

package com.npf.plugin;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import org.apache.ibatis.executor.parameter.ParameterHandler;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
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.SystemMetaObject;
import org.apache.ibatis.scripting.defaults.DefaultParameterHandler;
import org.apache.ibatis.session.Configuration;

import com.npf.model.vo.PageParams;

/**
 * 
 * @author Jack
 *
 */
@Intercepts({@Signature(
		type = StatementHandler.class,
		method="prepare",
		args={Connection.class,Integer.class}
)})
public class PaginationPlugin implements Interceptor {
	
	/**
	 * 默认页码
	 */
	private Integer defaultPage;
	
	/**
	 * 默认每页条数
	 */
	private Integer defaultPageSize;
	
	/**
	 * 默认是否启用插件
	 */
	private Boolean defaultUseFlag;
	
	/**
	 * 默认是否检测当前页码的正确性
	 */
	private Boolean defaultCheckFlag;

	@Override
	public Object intercept(Invocation invocation) throws Throwable {
		StatementHandler stmtHandler = getUnProxyObject(invocation);
		MetaObject metaStatementHandler = SystemMetaObject.forObject(stmtHandler);
		String sql = (String) metaStatementHandler.getValue("delegate.boundSql.sql");
		if(!checkSelect(sql)){
			return invocation.proceed();
		}
		BoundSql boundSql = (BoundSql) metaStatementHandler.getValue("delegate.boundSql");
		Object parameterObject = boundSql.getParameterObject();
		PageParams pageParams = getPageParams(parameterObject);
		if(pageParams == null){
			return invocation.proceed();
		}
		Integer pageNum = pageParams.getPage() == null ? this.defaultPage : pageParams.getPage();
		Integer pageSize = pageParams.getPageSize() == null ? this.defaultPageSize : pageParams.getPageSize();
		Boolean useFlag = pageParams.getUseFlag() == null ? this.defaultUseFlag : pageParams.getUseFlag();
		Boolean checkFlag = pageParams.getCheckFlag() == null ? this.defaultCheckFlag : pageParams.getCheckFlag();
		
		if(!useFlag){
			return invocation.proceed();
		}
		
		int total = getTotal(invocation,metaStatementHandler,boundSql);
		setTotalToPageParams(pageParams,total,pageSize);
		checkPage(checkFlag,pageNum,pageParams.getTotalPage());
		return changeSQL(invocation,metaStatementHandler,boundSql,pageNum,pageSize);
	}

	private Object changeSQL(Invocation invocation,MetaObject metaStatementHandler, BoundSql boundSql,Integer pageNum, Integer pageSize) throws Exception {
		String sql = (String) metaStatementHandler.getValue("delegate.boundSql.sql");
		String newSql = "select * from ("+sql+") $paging_table limit ?,?";
		metaStatementHandler.setValue("delegate.boundSql.sql", newSql);
		java.sql.PreparedStatement ps = (java.sql.PreparedStatement) invocation.proceed();
		int count = ps.getParameterMetaData().getParameterCount();
		ps.setInt(count-1, (pageNum-1)*pageSize);
		ps.setInt(count, pageSize);
		return ps;
	}

	private void checkPage(Boolean checkFlag, Integer pageNum, Integer totalPage) throws Exception {
		if(checkFlag){
			if(pageNum > totalPage){
				throw new Exception("fauil");
			}
		}
	}

	private void setTotalToPageParams(PageParams pageParams, int total,Integer pageSize) {
		pageParams.setTotal(total);
		int totalPage = total % pageSize == 0 ? total / pageSize : total / pageSize + 1;
		pageParams.setTotalPage(totalPage);
	}

	private int getTotal(Invocation invocation,MetaObject metaStatementHandler, BoundSql boundSql) throws SQLException {
		MappedStatement mappedStatement = (MappedStatement) metaStatementHandler.getValue("delegate.mappedStatement");
		Configuration configuration = mappedStatement.getConfiguration();
		String sql = (String) metaStatementHandler.getValue("delegate.boundSql.sql");
		String countSql = "select count(*) as total from ("+sql+") $_paging";
		Connection connection = (Connection) invocation.getArgs()[0];
		java.sql.PreparedStatement ps = null;
		int total = 0;
		try {
			ps = connection.prepareStatement(countSql);
			BoundSql countBoundSql = new BoundSql(configuration,countSql,boundSql.getParameterMappings(),boundSql.getParameterObject());
			ParameterHandler handler = new DefaultParameterHandler(mappedStatement, boundSql.getParameterObject(), countBoundSql);
			handler .setParameters(ps);
			ResultSet rs = ps.executeQuery();
			while(rs.next()){
				total = rs.getInt("total");
			}
		} finally{
			if(ps != null){
				ps.close();
			}
		}
		return total;
	}

	@SuppressWarnings("unchecked")
	private PageParams getPageParams(Object parameterObject) {
		if(parameterObject == null){
			return null;
		}
		PageParams pageParams = null;
		if(parameterObject instanceof Map){
			Map<String,Object> paramMap = (Map<String,Object>)parameterObject;
			Set<String> keySet = paramMap.keySet();
			Iterator<String> iterator = keySet.iterator();
			while(iterator.hasNext()){
				String key = iterator.next();
				Object value = paramMap.get(key);
				if(value instanceof PageParams){
					return (PageParams) value;
				}
			}
		}else if(parameterObject instanceof PageParams){
			pageParams = (PageParams)parameterObject;
		}
		return pageParams;
	}

	private boolean checkSelect(String sql) {
		String trimSql = sql.trim();
		int idx = trimSql.toLowerCase().indexOf("select");
		return idx == 0;
	}

	/**
	 * 从代理对象中分离出真实对象
	 * @param invocation
	 * @return
	 */
	private StatementHandler getUnProxyObject(Invocation invocation) {
		StatementHandler stmtHandler = (StatementHandler) invocation.getTarget();
		MetaObject metaStatementHandler = SystemMetaObject.forObject(stmtHandler);
		Object object = null;
		//分离代理对象链,由于目标类可能被对个拦截器拦截,从而形成多次代理
		//通过循环可以分离出最原始的目标类
		while(metaStatementHandler.hasGetter("h")){
			object = metaStatementHandler.getValue("h");
		}
		if(object == null){
			return stmtHandler;
		}
		return (StatementHandler) object;
	}

	@Override
	public Object plugin(Object statementHandler) {
		return Plugin.wrap(statementHandler, this);
	}

	@Override
	public void setProperties(Properties properties) {
		String defaultPage = properties.getProperty("defaultPage", "1");
		String defaultPageSize = properties.getProperty("defaultPageSize", "5");
		String defaultUseFlag = properties.getProperty("defaultUseFlag", "false");
		String defaultCheckFlag = properties.getProperty("defaultCheckFlag", "false");
		this.defaultPage = Integer.valueOf(defaultPage);
		this.defaultPageSize = Integer.valueOf(defaultPageSize);
		this.defaultUseFlag = Boolean.valueOf(defaultUseFlag);
		this.defaultCheckFlag = Boolean.valueOf(defaultCheckFlag);
	}

	public Integer getDefaultPage() {
		return defaultPage;
	}

	public void setDefaultPage(Integer defaultPage) {
		this.defaultPage = defaultPage;
	}

	public Integer getDefaultPageSize() {
		return defaultPageSize;
	}

	public void setDefaultPageSize(Integer defaultPageSize) {
		this.defaultPageSize = defaultPageSize;
	}

	public Boolean getDefaultUseFlag() {
		return defaultUseFlag;
	}

	public void setDefaultUseFlag(Boolean defaultUseFlag) {
		this.defaultUseFlag = defaultUseFlag;
	}

	public Boolean getDefaultCheckFlag() {
		return defaultCheckFlag;
	}

	public void setDefaultCheckFlag(Boolean defaultCheckFlag) {
		this.defaultCheckFlag = defaultCheckFlag;
	}
}


Add View

list.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>

	<table align="left" border="1">
		<tr>
			<td>id</td>
			<td>userName</td>
			<td>password</td>
		</tr>
		<c:forEach var="stu" items="${stuList}">
			<tr>
				<td>${stu.id}</td>
				<td>${stu.name}</td>
				<td>${stu.password}</td>
			</tr>
		</c:forEach>
	</table>
	<br/><br/><br/><br/><br/><br/><br/><br/><br/>
	<table>
		<tr>
			<c:if test="${pageParams.page > 1}">
				<a href="${pageContext.request.contextPath}/student/find?page=${pageParams.page - 1}">上一页</a>
			</c:if>
		</tr>
		<tr>
			<c:if test="${pageParams.page < pageParams.totalPage}">
				<a href="${pageContext.request.contextPath}/student/find?page=${pageParams.page + 1}">下一页</a>
			</c:if>
		</tr>
	</table>
</body>
</html>

Open browser and browse: http://localhost:8080/mybatispagination/student/find
《Mybatis plugin pagination + Spring MVC》

click the next button:
《Mybatis plugin pagination + Spring MVC》



the source code link : mybatispagination

    原文作者:Spring MVC
    原文地址: https://blog.csdn.net/pfnie/article/details/52504908
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞