MyBatis实现拦截器分页功能
1.原理
- 在mybatis使用拦截器(interceptor),截获所执行方法的sql语句与参数。
(1)修改sql的查询结果:将原sql改为查询count(*) 也就是条数
(2)将语句sql进行拼接 limit(MySql)或rownum(Oracle)语句达到分页效果 - 制作分页Page类,需要分页的bean继承分页Page类。
- jsp界面通过Page类的属性参数实现对页数控制。
2.具体步骤
(1)首先创建PageBean
(2)配置分页使用的拦截器实现Interceptor接口,重写其抽象方法
@Intercepts({ @Signature(type = StatementHandler.class, method = "prepare", args = { Connection.class }),
@Signature(type = ResultSetHandler.class, method = "handleResultSets", args = { Statement.class }) })
public class PageInterceptor implements Interceptor {
@Intercepts注解表示被会被拦截的类和方法参数
//SELECT_ID 根据被捕获的方法判断是否需要进行分页 如果方法名含有Page则进行分页
private static final String SELECT_ID = "Page";
//在intercept方法中获取mybatis.xml中的property属性值为PageCount赋值
private Properties properties;
//通过PageBean对象获取Count值的where条件后参数
private PageBean pageBean;
1. 拦截器的主方法则是具体功能的实现,主要做的事:
判断被拦截的方法是否需要进行分页
需要分页则截取sql语句,截取条件并拼接成查询条数,也就是将
select * from user ----> select count(*) from user
- 获取数据库连接对象,并执行拼接好的count(*)获取条数Sql语句获取数据库条数 ,并将值存到设计好的PageBean对象中
//获取数据库连接对象
Connection connection = (Connection) invocation.getArgs()[0];
//执行countSql语句 并获得Count值 为PageBean的totalCount赋值
PreparedStatement countStmt = null;
ResultSet rs = null;
int totalCount = 0;
try {
countStmt = connection.prepareStatement(countSql);
rs = countStmt.executeQuery();
if (rs.next()) {
totalCount = rs.getInt(1);
}
} catch (SQLException e) {
System.out.println("Ignore this exception" + e);
} finally {
try {
rs.close();
countStmt.close();
} catch (SQLException e) {
System.out.println("Ignore this exception" + e);
}
}
- 将原sql语句增加limit a,b a为查询结果第一条,b为所查询的条数
public String concatPageSql(String sql, PageBean pageBean) {
StringBuffer sb = new StringBuffer();
sb.append(sql);
sb.append(" limit ").append(pageBean.getPageLimit()).append(" ,").append(pageBean.getPageCount());
return sb.toString();
}
- 将拦截修改好的sql语句传递给dao层执行的方法 并返回对应的结果
//将处理好的SQL语句绑定
String pageSql = concatPageSql(sql, pageBean);
//将修改好的sql语句返回给方法
metaStatementHandler.setValue("delegate.boundSql.sql", pageSql);
- 退出拦截器,开始执行dao层方法,执行sql语句进行数据处理
//执行dao层方法
return invocation.proceed();
Controller中配置 接收参数与返回参数
- 参数为PageBean的子类对象–接收由JSP中传入的分页数据信息–模糊查询的参数等等
- 而参数在dao层方法完成后,会在拦截器中对其分页数据进行赋值–也就是经过拦截器处理后,对象的数据增加了
- 以User类为例
@RequestMapping("/selectLikeUser.do")
//参数为user 而mav.addObject("pageBean", user); 也是user,这是拦截器有对user进行分页信息赋值
public ModelAndView selectPageLikeAllUser(User user){
//执行的顺序Service-->拦截器(修改sql语句,注入分页参数)-->Dao方法-->返回结果
//所以有两个值 ① 分页的数据(当前页,总页数等数据)在user对象中
// ② 保存数据的集合userList
List<User> userList=this.userService.selectPageLikeAllUser(user);
ModelAndView mav=new ModelAndView();
mav.addObject("userList", userList);
//对应的前台Jsp界面
mav.setViewName("userList");
//将分页数据保存
mav.addObject("pageBean", user);
return mav;
}
前台Jsp界面
- 翻页需要的button模块
<div class="div_input">
//分页需要用到的参数有JS对应的方法进行表单提交时传递参数 而limtr 从0开始,后台执行sql语句 limit 0,每页的条数
//每次点击下一页 变化的都是limit 前面的参数 limit 参数*条数,条数
//第一页 limit 0*2,2
//第二页 limit 1*2,2
//第三页 limit 2*2,2 …………
<input type="button" class="input_scan" value="首页" onclick="page(0)"/>
//判断上一页的方法,当表单无上一页是 当前input会被隐藏
<c:if test="${pageBean.previous}">
<input type="button" class="input_scan" value="上页" onclick="page(${pageBean.pageNo - 1})"/>
</c:if>
//判断下一页的方法,当前为最大页时,input隐藏
<c:if test="${pageBean.next}">
<input type="button" class="input_scan" value="下页" onclick="nextPage(${pageBean.pageNo + 1},${pageBean.totalPage})"/>
</c:if>
<input type="button" class="input_scan" value="末页" onclick="page(${pageBean.totalPage -1})"/>
<span class="span_text">跳到第</span>
<input type="text" class="input_text" name="pageNo" id="pageID"/>
<span class="span_text">页</span>
<input type="button" class="input_scan" value="跳转" onclick="pageSubmit(${pageBean.totalPage})"/>
</div>
- 对应的JS方法
//每一次表单的提交,在controller中捕获的都是pageID的那个type='text'的那个文本框
//方法中的逻辑判断则是为了避免一些提交bug,保证pageID的文本框中数值显示正常以及跳转按钮等等
<script type="text/javascript">
function page(pageArg){
var myform = document.getElementById("myform");
var pageNo = document.getElementById("pageID");
pageNo.value = pageArg;
if(pageArg!=-1){
myform.submit();
}else{
pageNo.value ="";
}
}
function pageSubmit(pageArg){
var myform = document.getElementById("myform");
var pageNo = document.getElementById("pageID");
if(pageNo.value-1 < pageArg){
pageNo.value=Number(pageNo.value)-1;
if(pageNo.value>-1){
myform.submit();
}else{
pageNo.value="";
}
}
}
function nextPage(pageArg,totalPage){
var myform = document.getElementById("myform");
var pageNo = document.getElementById("pageID");
pageNo.value = pageArg;
if(pageArg<totalPage)
myform.submit();
}
</script>
**
下面为完整代码
**
拦截器中,因为模糊查询,所以多了一些判断参数的方法,以及为sql语句的参数赋值的过程,仅供参考
PageBean为对应的分页model类,而selectInfo为模糊查询参数,在拦截器中会使用此参数在查询count条数时,修改参数
**
PageBean
**
package com.chinasofti.lexian.bean;
import java.util.HashMap;
public class PageBean {
private int totalCount;//总的条数
private int pageNo;//当前的页数
private int pageCount;//每页的条数
private int pageLimit;//下一页的条件 等于pageNo*pageCount
private String storename;
private String starttime;
private String closetime;
private String selectInfo;
private int state;
private static HashMap<String, String> infoHashMap;//模糊查询配置参数
static{
infoHashMap = new HashMap<String, String>();
}
//无参构造方法
public PageBean() {
super();
// TODO Auto-generated constructor stub
}
//全参构造方法
public PageBean(int totalCount, int pageNo, int pageCount) {
this.totalCount = totalCount;
this.pageNo = pageNo;
this.pageCount = pageCount;
}
//属性的set,get 方法
public int getPageCount() {
return pageCount;
}
public void setPageCount(int pageCount) {
this.pageCount = pageCount;
}
public void setPageNo(int pageNo) {
this.pageNo = pageNo;
}
public int getPageNo() {
return pageNo;
}
public int getPageLimit() {
return pageLimit;
}
public void setPageLimit(int pageLimit) {
this.pageLimit = pageLimit;
}
public int getTotalCount() {
return totalCount;
}
public void setTotalCount(int totalCount) {
this.totalCount = totalCount;
}
//获取总页数
public int getTotalPage(){
if(totalCount % pageCount == 0){
return totalCount/pageCount;
}else{
return totalCount/pageCount+1;
}
}
//多写一个判断下一页的方法
public boolean isNext(){
return pageNo + 1 < getTotalPage();
}
//上一页的方法
public boolean isPrevious(){
return pageNo > 0;
}
public String getInfoHashMap(String key) {
return infoHashMap.get(key);
}
public void setInfoHashMap(String key, String value) {
PageBean.infoHashMap.put(key, value);
}
public String getSelectInfo() {
return selectInfo;
}
public void setSelectInfo(String selectInfo) {
this.selectInfo = selectInfo;
}
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
}
public String getStorename() {
return storename;
}
public void setStorename(String storename) {
this.storename = storename;
}
public String getStarttime() {
return starttime;
}
public void setStarttime(String starttime) {
this.starttime = starttime;
}
public String getClosetime() {
return closetime;
}
public void setClosetime(String closetime) {
this.closetime = closetime;
}
}
**
拦截器Interceptor
**
package com.chinasofti.lexian.interceptor;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
import org.apache.ibatis.executor.resultset.ResultSetHandler;
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 com.chinasofti.lexian.bean.PageBean;
/**
* args 对应方法的参数
* method 想要拦截的方法
* type 想要拦截的类
*/
@Intercepts({ @Signature(type = StatementHandler.class, method = "prepare", args = { Connection.class }),
@Signature(type = ResultSetHandler.class, method = "handleResultSets", args = { Statement.class }) })
public class PageInterceptor implements Interceptor {
/**
* SELECT * FROM USER ORDER BY ID LIMIT 0,2
*/
private static final String SELECT_ID = "Page";
//在intercept方法中获取mybatis.xml中的property属性值为PageCount赋值
private Properties properties;
//通过PageBean对象获取Count值的where条件后参数
private PageBean pageBean;
@Override
public Object intercept(Invocation invocation) throws Throwable {
if (invocation.getTarget() instanceof StatementHandler) {
//获取mappedStatement对象 通过mappedStatement,metaStatementHandler获取对SQL语句和参数进行操作
StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
MetaObject metaStatementHandler = SystemMetaObject.forObject(statementHandler);
MappedStatement mappedStatement = (MappedStatement) metaStatementHandler
.getValue("delegate.mappedStatement");
//mappedStatement.getId() 获取被截取的方法名字 输出的方法名为 包名.类名.方法名
String selectId = mappedStatement.getId();
//判断如果方法名字中出现Page 则为需要进行分页操作的方法
if (selectId.indexOf(SELECT_ID) != -1) {
//boundSql.getSql() 获取当前方法执行的Sql语句
BoundSql boundSql = (BoundSql) metaStatementHandler.getValue("delegate.boundSql");
String sql = boundSql.getSql();
sql = sql.replaceAll("\n", " ").replaceAll("\t", "");
/*
* boundSql.getParameterObject() 获取被截获方法的参数 需要强转
* PageBean 需要分页的Bean数据的父类
* User Controller方法中的参数类 获取User为了给Count的Where后条件 赋值
* 被拦截的方法中未赋值
*/
pageBean = (PageBean) (boundSql.getParameterObject());
//获取mybatis.xml中的值(每页的条数) 为 PageCount赋值
pageBean.setPageCount(Integer.parseInt(this.properties.getProperty("pageCount")));
//concatCountSql()方法 截取sql查询方法 获取需要分页的表名 计算共有多少条数据
String countSql="";
if(pageBean.getState()==2){
countSql ="select count(*) from (" + concatCountSql(sql) + ") as name";
}else if(pageBean.getState()==3){
countSql = concatCountSql_ji(sql);
}else{
countSql = concatCountSql(sql);
}
//获取数据库连接对象
Connection connection = (Connection) invocation.getArgs()[0];
//执行countSql语句 并获得Count值 为PageBean的totalCount赋值
PreparedStatement countStmt = null;
ResultSet rs = null;
int totalCount = 0;
try {
countStmt = connection.prepareStatement(countSql);
rs = countStmt.executeQuery();
if (rs.next()) {
totalCount = rs.getInt(1);
}
} catch (SQLException e) {
// System.out.println("Ignore this exception" + e);
} finally {
try {
rs.close();
countStmt.close();
} catch (SQLException e) {
System.out.println("Ignore this exception" + e);
}
}
//判断若下一页条数大于最大数 则按最大数取值
pageBean.setTotalCount(totalCount);
pageBean.setPageLimit(pageBean.getPageNo() * pageBean.getPageCount());
if (pageBean.getPageLimit() > totalCount) {
pageBean.setPageLimit(totalCount);
}
//将处理好的SQL语句绑定
String pageSql = concatPageSql(sql, pageBean);
metaStatementHandler.setValue("delegate.boundSql.sql", pageSql);
}
}
return invocation.proceed();
}
/**
* 如果类型为StatementHandler则返回他本身
* 用于封装目标对象,通过该方法可以返回目标对象本身
*/
@Override
public Object plugin(Object target) {
if (target instanceof StatementHandler) {
return Plugin.wrap(target, this);
} else {
return target;
}
}
/**
* setProperties方法在intercept方法之前调用
* 需要在mybatis-config.xml中的<plugins>中配置property
* 能获取xml文件中对应的property值
*/
@Override
public void setProperties(Properties properties) {
this.properties = properties;
}
/**
*
* @param sql 根据Sql 截取出获得查询数据条数的Sql语句
* @return 返回select count(*) from 表名 (where name = 值)
*/
public String concatCountSql_ji(String sql) {
StringBuffer sb = new StringBuffer("select count(*) from ");
//select count(*) from user
//转小写
sql = sql.toLowerCase();
// System.out.println("-------------原sql文:"+sql);
//sql.lastIndexOf("order") > sql.lastIndexOf(")") 如果有order by 则不截取order后 不需要排序
if (sql.lastIndexOf("order by") > sql.lastIndexOf(")")) {
sb.append(sql.substring(sql.indexOf("from") + 4, sql.lastIndexOf("order by")));
} else {
//截取from 后所有条件
sb.append(sql.substring(sql.indexOf("from") + 4));
}
//StringBuffer转成String
String newSql = sb.toString().replaceAll("\n", " ").replaceAll("\t", "");
// System.out.println("去空格后的sql文:"+newSql);
//判断 如果 sql语句为有参查询 则替换参数
/**
* select count(*) from orders o,store s,commodity c
where o.store_no = s.store_no
and o.commodity_no = c.commodity_no
and o.states = ?
and o.createtime >= ?
and o.createtime <= ?
and order_no like "%"?"%"
*/
//循环替换sql文中的?
//只有一个?
if(newSql.indexOf("?") > 0 && newSql.indexOf("?") == newSql.lastIndexOf("?")){
return newSql.replaceAll("\\?", "'"+this.pageBean.getSelectInfo()+"'");
}
//有多个?
while(newSql.indexOf("?") > 0) {
String condition = newSql.substring(0, newSql.indexOf("?"));
/**
* condition =
* select count(*) from orders o,store s,commodity c
where o.store_no = s.store_no
and o.commodity_no = c.commodity_no
and o.states =
*/
condition = condition.substring(condition.lastIndexOf("and")+3);
/**
* condition =
* o.states =
*/
/**
* 判断condition中的逻辑运算符
* >=、<=、>、<,需要保留,以便判断需要的是哪个参数
*/
if(condition.indexOf(">=") > 0 || condition.indexOf("<=") > 0){
condition = condition.substring(condition.indexOf(".") > 0 ? condition.indexOf(".")+1 : 0, condition.indexOf("=")+1).trim();
}else if(condition.indexOf(">") > 0){
condition = condition.substring(condition.indexOf(".") > 0 ? condition.indexOf(".")+1 : 0, condition.indexOf(">")+1).trim();
}else if(condition.indexOf("<") > 0){
condition = condition.substring(condition.indexOf(".") > 0 ? condition.indexOf(".")+1 : 0, condition.indexOf("<")+1).trim();
}else if(condition.indexOf("=") > 0){
condition = condition.substring(condition.indexOf(".") > 0 ? condition.indexOf(".")+1 : 0, condition.indexOf("=")).trim();
}else {
condition = condition.substring(condition.indexOf(".") > 0 ? condition.indexOf(".")+1 : 0, condition.indexOf("like")).trim();
}
//去参数中的空格
condition = condition.replace(" ", "");
//去掉参数中的"_"并将后一字母大写
while (condition.indexOf("_") > 0) { //order_no
int location = condition.indexOf("_"); //5
String upCase = condition.substring(location+1, location+2).toUpperCase();//N
String target = condition.substring(location, location+2);//_n
condition = condition.replaceFirst(target, upCase); //orderNo
}
//调用pageBean的getSelectInfo方法根据参数名获取对应的参数值
String strInfo = "'" + this.pageBean.getInfoHashMap(condition) + "'";
newSql = newSql.replaceFirst("\\?", strInfo);// ?需要转义-->\?,\也需要转义-->\\,\?就要写成\\?
}
return newSql;
}
public String concatCountSql(String sql) {
StringBuffer sb = new StringBuffer("select count(*) from ");
//select count(*) from user
//转小写
sql = sql.toLowerCase();
//sql.lastIndexOf("order") > sql.lastIndexOf(")") 如果有order by 则不截取order后 不需要排序
if (sql.lastIndexOf("order") > sql.lastIndexOf(")")) {
sb.append(sql.substring(sql.indexOf("from") + 4, sql.lastIndexOf("order")));
} else {
//截取form 后所有条件
sb.append(sql.substring(sql.indexOf("from") + 4));
}
//StringBuffer转成String
String newSql = sb.toString();
//判断 如果 sql语句为有参查询 则替换参数
if (sb.indexOf("?") > 0) {
if(pageBean.getState()!=2){
String strInfo = "'" + this.pageBean.getSelectInfo() + "'";
newSql = newSql.replace("?", strInfo);
}else{
String [] arr = newSql.split("\\?");
String storename=pageBean.getStorename();
String starttime=pageBean.getStarttime();
String closetime=pageBean.getClosetime();
String selectInfo = pageBean.getSelectInfo();
switch (arr.length) {
case 2:
if(storename != null&&(!storename.equals(""))){
// System.out.println("a1");
newSql=arr[0]+"'"+storename+"'"+arr[1];
}else if(starttime!=null&&(!starttime.equals(""))){
// System.out.println("a2");
newSql=arr[0]+"'"+starttime+"'"+arr[1];
}else if(closetime!=null&&(!closetime.equals(""))){
// System.out.println("a3");
newSql=arr[0]+"'"+closetime+"'"+arr[1];
}else{
newSql=arr[0]+"'"+selectInfo+"'"+arr[1];
}
break;
case 3:
if((storename==null||storename.equals(""))&&(starttime==null||starttime.equals(""))){
newSql=arr[0]+"'"+closetime+"'"+arr[1]+"'"+selectInfo+"'"+arr[2];
}else if((storename==null||storename.equals(""))&&(closetime==null||closetime.equals(""))){
newSql=arr[0]+"'"+starttime+"'"+arr[1]+"'"+selectInfo+"'"+arr[2];
}else if((storename==null||storename.equals(""))&&(selectInfo==null||selectInfo.equals(""))){
newSql=arr[0]+"'"+starttime+"'"+arr[1]+"'"+closetime+"'"+arr[2];
}else if((starttime==null||starttime.equals(""))&&(closetime==null||closetime.equals(""))){
newSql=arr[0]+"'"+storename+"'"+arr[1]+"'"+selectInfo+"'"+arr[2];
}else if((selectInfo==null||selectInfo.equals(""))&&(closetime==null||closetime.equals(""))){
newSql=arr[0]+"'"+storename+"'"+arr[1]+"'"+starttime+"'"+arr[2];
}else{
newSql=arr[0]+"'"+storename+"'"+arr[1]+"'"+closetime+"'"+arr[2];
}
break;
case 4:
if(storename==null||storename.equals("")){
newSql=arr[0]+"'"+starttime+"'"+arr[1]+"'"+closetime+"'"+arr[2]+"'"+selectInfo+"'"+arr[3];
}else if(starttime==null||starttime.equals("")){
newSql=arr[0]+"'"+storename+"'"+arr[1]+"'"+closetime+"'"+arr[2]+"'"+selectInfo+"'"+arr[3];
}else if(closetime==null||closetime.equals("")){
newSql=arr[0]+"'"+storename+"'"+arr[1]+"'"+starttime+"'"+arr[2]+"'"+selectInfo+"'"+arr[3];
}else{
newSql=arr[0]+"'"+storename+"'"+arr[1]+"'"+starttime+"'"+arr[2]+"'"+closetime+"'"+arr[3];
}
break;
case 5:
newSql=arr[0]+"'"+storename+"'"+arr[1]+"'"+starttime+"'"+arr[2]+"'"+closetime+"'"+arr[3]+"'"+selectInfo+"'"+arr[4];
break;
default:
break;
}
}
}
return newSql;
}
/**
*
* @param sql 为截取到的Sql语句
* @param pageBean 分页model类 为limit 添加参数
* @return 拼接好的Sql语句
* limit(初始从0开始,条数)
*/
public String concatPageSql(String sql, PageBean pageBean) {
StringBuffer sb = new StringBuffer();
sb.append(sql);
sb.append(" limit ").append(pageBean.getPageLimit()).append(" ,").append(pageBean.getPageCount());
return sb.toString();
}
}
**
JSP界面
**
<%@page import="com.chinasofti.lexian.manager.user.vo.User"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<!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>
<style type="text/css">
a{
text-decoration: none;
}
#div_right {
width: 100%;
height: 640px;
margin: 0 auto;
}
#div_login {
width: 100%;
height: 25px;
padding-top: 4px;
font-family: "微软雅黑";
font-size: 13px;
}
.table_txt {
font-family: "微软雅黑";
font-size: 12px;
height: 20px;
border: 0.1px solid gray;
text-align: center;
width: 100%
}
.div_info_all {
float: left;
width: 100%;
height: 24px;
font-family: "微软雅黑";
}
.div_info_all_text {
font-size: 12px;
margin-top: 7px;
float: right;
}
.span_txt {
font-weight: bold;
margin-left: -3px;
}
.div_input {
float: left;
margin-right: 5px;
}
.input_scan {
border: 1px solid black;
margin-left: -1px;
margin-right: -1px;
}
.input_text {
width: 25px;
height: 13px;
}
.span_text {
font-family: "微软雅黑";
font-size: 12px;
}
#div_select {
float: right;
margin-right: 5px;
margin-top: -5px;
}
#td_text1{
color:blue;
}
#td_text2{
color:red;
}
tr:hover{
background-color: white;
}
</style>
<script type="text/javascript">
function page(pageArg){
var myform = document.getElementById("myform");
var pageNo = document.getElementById("pageID");
pageNo.value = pageArg;
if(pageArg!=-1){
myform.submit();
}else{
pageNo.value ="";
}
}
function pageSubmit(pageArg){
var myform = document.getElementById("myform");
var pageNo = document.getElementById("pageID");
if(pageNo.value-1 < pageArg){
pageNo.value=Number(pageNo.value)-1;
if(pageNo.value>-1){
myform.submit();
}else{
pageNo.value="";
}
}
}
function nextPage(pageArg,totalPage){
var myform = document.getElementById("myform");
var pageNo = document.getElementById("pageID");
pageNo.value = pageArg;
if(pageArg<totalPage)
myform.submit();
}
</script>
</head>
<body background="#F3F3F3">
<form action="selectLikeUser.do" method="post" id="myform">
<div id="div_right">
<div id="div_login">
会员管理 > 查看会员信息
<div id="div_select">
<select name="selectType">
<option value="username" ${pageBean.selectType=='username' ? 'selected' : ""}>会员名</option>
<option value="phone" ${pageBean.selectType=='phone' ? 'selected' : ""}>手机号</option>
</select>
<input type="text" name="selectInfo" value="${pageBean.selectInfo}"/>
<input type="button" value="查找" onclick="page(0)"/>
</div>
</div>
<table border="1px" cellspacing="0px" cellpadding="5px"
class="table_txt">
<tr style="background-color: #c3dde0;">
<th></th>
<th>会员名</th>
<th>手机号</th>
<th>最后登陆时间</th>
<th>状态</th>
<th>操作</th>
</tr>
<c:forEach items="${userList}" var="key" varStatus="state">
<tr>
<td>${state.count}</td>
<td>${key.username}</td>
<td>${key.phone}</td>
<%-- <td>${key.lastlogintime}</td> --%>
<td><spring:eval expression="key.lastlogintime" /></td>
<td><span id="td_text1">${key.status==1 ? "启用" :"禁用"}</span></td>
<%-- <td>${key.statusInfo}</td> --%>
<%-- <td><a href="changeStatus.do?id=${key.id}&status=${key.status}">${key.checkStatus}</a></td> --%>
<td><a href="changeStatus.do?selectType=${pageBean.selectType}&id=${key.id}&status=${key.status}&selectInfo=${pageBean.selectInfo}&pageNo=${pageBean.pageNo}"><span id="td_text2">${key.status==1 ? "禁用" :"启用"}</span></a></td>
</tr>
</c:forEach>
</table>
<div class="div_info_all">
<div class="div_info_all_text">
共 <span class="span_txt">${pageBean.totalCount}</span> 条结果,分成 <span class="span_txt">${pageBean.totalPage}</span>页显示,当前第
<span class="span_txt">${pageBean.pageNo+1}</span>页
</div>
<div class="div_input">
<input type="button" class="input_scan" value="首页" onclick="page(0)"/>
<c:if test="${pageBean.previous}">
<input type="button" class="input_scan" value="上页" onclick="page(${pageBean.pageNo - 1})"/>
</c:if>
<c:if test="${pageBean.next}">
<input type="button" class="input_scan" value="下页" onclick="nextPage(${pageBean.pageNo + 1},${pageBean.totalPage})"/>
</c:if>
<input type="button" class="input_scan" value="末页" onclick="page(${pageBean.totalPage -1})"/>
<span class="span_text">跳到第</span>
<input type="text" class="input_text" name="pageNo" id="pageID"/>
<span class="span_text">页</span>
<input type="button" class="input_scan" value="跳转" onclick="pageSubmit(${pageBean.totalPage})"/>
</div>
</div>
</div>
</form>
</body>
</html>
MyBatis实现拦截器分页功能的更多相关文章
- Mybatis利用拦截器做统一分页
mybatis利用拦截器做统一分页 查询传递Page参数,或者传递继承Page的对象参数.拦截器查询记录之后,通过改造查询sql获取总记录数.赋值Page对象,返回. 示例项目:https://git ...
- mybatis Interceptor拦截器代码详解
mybatis官方定义:MyBatis 是一款优秀的持久层框架,它支持定制化 SQL.存储过程以及高级映射.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis ...
- Mybatis Interceptor 拦截器原理 源码分析
Mybatis采用责任链模式,通过动态代理组织多个拦截器(插件),通过这些拦截器可以改变Mybatis的默认行为(诸如SQL重写之类的),由于插件会深入到Mybatis的核心,因此在编写自己的插件前最 ...
- Mybatis之拦截器原理(jdk动态代理优化版本)
在介绍Mybatis拦截器代码之前,我们先研究下jdk自带的动态代理及优化 其实动态代理也是一种设计模式...优于静态代理,同时动态代理我知道的有两种,一种是面向接口的jdk的代理,第二种是基于第三方 ...
- mybatis定义拦截器
applicationContext.xml <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlS ...
- MyBatis原理-拦截器
一.MyBatis拦截器介绍 MyBatis提供了一种插件(plugin)的功能,虽然叫做插件,但其实这是拦截器功能. MyBatis 允许你在已映射语句执行过程中的某一点进行拦截调用.默认情况下,M ...
- Mybatis自定义拦截器与插件开发
在Spring中我们经常会使用到拦截器,在登录验证.日志记录.性能监控等场景中,通过使用拦截器允许我们在不改动业务代码的情况下,执行拦截器的方法来增强现有的逻辑.在mybatis中,同样也有这样的业务 ...
- mybatis - 基于拦截器修改执行语句中的ResultMap映射关系
拦截器介绍 mybatis提供了@Intercepts注解允许开发者对mybatis的执行器Executor进行拦截. Executor接口方法主要有update.query.commit.rollb ...
- mybatis - 基于拦截器修改执行中的SQL语句
拦截器介绍 mybatis提供了@Intercepts注解允许开发者对mybatis的执行器Executor进行拦截. Executor接口方法主要有update.query.commit.rollb ...
随机推荐
- IOS Google语音识别更新啦!!!
旧版本的API: —Google提供了一个在线语音识别的API接口,通过该API可以进行中文.英文等语言的识别. API地址:http://www.google.com/speech-api ...
- Spring MVC工程 无法拦截到url请求
一直没有办法拦截到url的请求,tomcat启动也没有看到Springmvc容器启动的任何说明.所以就建立了一个普通的servlet工程,可以访问url.再重新发布springmvc项目,访问url, ...
- Flask入门flask-script 蓝本 钩子函数(三)
1 flask-script扩展库 概念: 是一个flask终端运行的解析器 ,因为项目完成以后,代码改动会有风险,所以借助终端完成不同启动项的配置 安装 pip3 install flask-scr ...
- React学习笔记 - 元素渲染
React Learn Note 3 React学习笔记(三) 标签(空格分隔): React JavaScript 二.元素渲染 元素是构成react应用的最小单位. 元素是普通的对象. 元素是构成 ...
- js常用函数汇总(不定期更新)
1.图片按比例压缩 function setImgSize(){ var outbox_w=imgbox.width(), outbox_h=imgbox.height(); imgbox.find( ...
- vue-cli3 项目从搭建优化到docker部署
项目地址 vue-cli3-project 欢迎 star 原文地址 https://www.ccode.live/lentoo/list/9?from=art 1. 创建一个vue项目 相信大部分人 ...
- Android(java)学习笔记11:生产者和消费者之等待唤醒机制
1. 首先我们根据梳理我们之前Android(java)学习笔记70中,关于生产者和消费者程序思路: 2. 下面我们就要重点介绍这个等待唤醒机制: (1)第一步:还是先通过代码体现出等待唤醒机制 下面 ...
- Android(java)学习笔记38:Android 短信发送
1.第一种可以调用系统内部的短信程序. 之前我曾经出现过一个bug就是报错: android.content.ActivityNotFoundException: No Activity found ...
- SiteMesh配置下载使用(简单介绍)
简单介绍 SiteMesh 是一个网页布局和修饰的框架,利用它可以将网页的内容和页面结构分离,以达到页面结构共享的目的. Sitemesh是由一个基于Web页面布局.装饰以及与现存Web应用整合的框架 ...
- Windows下同时安装Anaconda2与Anaconda3
1. 安装一个作为主版本,比如先安装Anaconda2,安装时选择[添加path环境变量].我的安装地址为:E:\ProgramData\Anaconda3 2. 安装另一个版本python,安装时注 ...