话说:
各位读者朋友,中午好!我在12.27号再次“会了会”分页,当时是用Servlet做的,直接在Servlet里面传分页5要素,分页的效果我还是满意的 (样式有点丑),但是上面的做法有不少缺点,缺点如下:
1.复用率低。
场景:很多个页面都要分页,那么Servlet那种方式会搞死人的。
想当年,我们学习Java的时候,在封装板块,讲的最多的就是封装可以极大的提高复用率,今天当然也直接用自己写的工具类来提升复用率。以后直接new这个工具类,给必须的参数赋值即可。
2.页面代码逻辑过多。
当时为了实现(当前页 -n) ,(当前页+n)的功能,都是在页面做的控制,导致页面很庞杂!现在这个逻辑直接放到set() get()方法里面处理,页面只用控制 首页 第一页 ;末页 最后一页即可。
今日目标:分页封装为工具类
难度系数:★★☆☆☆
建议用时: 1H
目录
1.效果图
2.Pager类
3.Controller层
4.页面代码
5.总结
1.效果图
2.Pager类
package com.hmc.util;
import java.util.List;
/**
*
*2018年1月20日
*User:Meice
*下午4:08:25
*/
public class Pager {
/**
* 分页5要素 1条件
* 1.pageIndex 当前页-页面传过来
* 2.pageSize 每页显示数量 - 固定
* 3.offset 偏移量 -根据pageSize 和pageIndex计算 offset = (pageIndex-1)*pageSize 也就是limit ?,? 第一个问号
* 4.count 总数量-后台写方法查
* 5.totalPage 总页数 根据count pageSize得出 totalPage = (int)Math.ceil((double)count/pageSize)
* 6.list 存放集合数据
*/
//结论:调用此实体类给3个参数即可 pageIndex pageSize count
private int pageIndex;
private int pageSize;
private int offset;
private int count;
private int totalPage;
private List<?> list;//存放数据
private int begin;//处理每一页
private int end;
private int skipTo;//如果好玩点,可以加个跳转
public Pager() {}
public Pager(int pageIndex, int pageSize, int offset, int count, int totalPage, List<?> list, int begin, int end,
int skipTo) {
super();
this.pageIndex = pageIndex;
this.pageSize = pageSize;
this.offset = offset;
this.count = count;
this.totalPage = totalPage;
this.list = list;
this.begin = begin;
this.end = end;
this.skipTo = skipTo;
}
public int getPageIndex() {
return pageIndex;
}
public void setPageIndex(int pageIndex) {
//控制住首页
if(pageIndex<=0) {
pageIndex =1;
}
if(pageIndex<=5) {
begin = 1;
end = pageSize;
}else if(pageIndex<=(totalPage-pageSize)) {
begin = pageIndex - (int)Math.round(pageSize/2);
end = pageIndex + (pageSize-((int)Math.round(pageSize/2.0)));
}else {
begin = totalPage-(pageSize-1);
end = totalPage;
}
this.pageIndex = pageIndex;
}
public int getPageSize() {
return pageSize;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
public int getOffset() {
//使用此实体类的用户,不用为这个赋值
offset = (pageIndex -1)*pageSize;
return offset;
}
public void setOffset(int offset) {
this.offset = offset;
}
public int getCount() {
return count;
}
public void setCount(int count) {
totalPage = (int)Math.ceil((double)count/pageSize);
this.count = count;
}
public int getTotalPage() {
//这个写在get()方法里面,因为用户不用赋值,但是有不能直接写死,否则变为了常量,没发改变 不要写这里,因为还得认为调用
//totalPage = (int)Math.ceil((double)count/pageSize);
return totalPage;
}
public void setTotalPage(int totalPage) {
this.totalPage = totalPage;
}
public List<?> getList() {
return list;
}
public void setList(List<?> list) {
this.list = list;
}
public int getBegin() {
//这里赋值没用,因为方法没发调用!我们当前页赋值是通过setPageIndex()赋值的,框架底层也是这样 所以应该写在setPageIndex()
/*if(pageIndex<=pageSize) {
begin = 1;
}else if(pageIndex <totalPage -pageSize) {
begin = pageIndex - (int)Math.round(pageSize/2.0);
}*/
return begin;
}
public void setBegin(int begin) {
this.begin = begin;
}
public int getEnd() {
/*if(pageIndex<=pageSize) {
end = pageSize;
}else if(pageIndex <totalPage -pageSize) {
end = pageIndex + (pageSize-((int)Math.round(pageSize/2.0)));
}*/
return end;
}
public void setEnd(int end) {
this.end = end;
}
public int getSkipTo() {
return skipTo;
}
public void setSkipTo(int skipTo) {
this.skipTo = skipTo;
}
@Override
public String toString() {
return "Pager [pageIndex=" + pageIndex + ", pageSize=" + pageSize + ", offset=" + offset + ", count=" + count
+ ", totalPage=" + totalPage + ", list=" + list + ", begin=" + begin + ", end=" + end + ", skipTo="
+ skipTo + "]";
}
}
具体细节详见代码注释,博客结尾也会 来个小节!
3.Controller层+后端代码
1)Dao层
public interface LogDao {
//查询日志
List<Log> logList(int userId,int offset,int pageSize);
//查询总量
int getCount(int userId);
}
2)XML
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.hmc.dao.LogDao">
<!--1.查询所有日志列表 -->
<select id="logList" resultMap="Log">
select g.logId,g.doTime,g.event,g.eventDetail,u.userId,u.userName,u.userNick
from
log g,SysUser u
where g.userId = u.userId
and u.userId = #{arg0}
order by g.logId desc
limit #{arg1}, #{arg2}
</select>
<!-- 查询当前用户日志数量 -->
<select id="getCount" resultType="Integer" parameterType="Integer">
select count(logId) countAll from log where userId = #{userId}
</select>
<!-- 配置手动映射 -->
<resultMap type="com.hmc.pojo.Log" id="Log" autoMapping="true">
<association property="sysUser" javaType="com.hmc.pojo.SysUser">
<id column="userId" property="userId"/>
<result column="userNick" property="userNick"/>
<result column="userName" property="userName"/>
<!--获取这些信息基本就够了 -->
</association>
<collection property="sysUserList" ofType="com.hmc.pojo.SysUser">
<id column="userId" property="userId"/>
<result column="userNick" property="userNick"/>
<result column="userName" property="userName"/>
</collection>
</resultMap>
</mapper>
3)Service层就是调用一下方法即可,省略
4)Controller层
package com.hmc.controller;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import com.hmc.pojo.Log;
import com.hmc.pojo.SysUser;
import com.hmc.service.LogService;
import com.hmc.util.Pager;
/**
*
*2018年1月19日
*User:Meice
*下午3:08:51
*/
@Controller
@RequestMapping("log")
public class LogController {
@Autowired
private LogService logService;
//显示日志列表
@RequestMapping("logList")
public String logList(Model model,Integer userId,Integer pageIndex,Integer skipTo,HttpServletRequest req) {
//调用 查询日志方法
SysUser sysUserAndRole =(SysUser) req.getSession().getAttribute("sysUserAndRole");
if(sysUserAndRole != null) {
userId = sysUserAndRole.getUserId();
//超级管理员可以看到所有日志(包括自己) sql语句灵活判断 userId == 1即可!
}
System.out.println("session中用户id: "+userId);
//以下执行分页
Pager pager = new Pager();
System.out.println("从页面接收到的当前页: "+pageIndex);
if(pageIndex==null) {
pageIndex =1;
}
pager.setPageSize(5);
int countAll =0;
if(sysUserAndRole != null) {
countAll = logService.getCount(userId);
}
System.out.println("总条目数:"+countAll);
pager.setCount(countAll);
//一定要调用一下getTotalPage()否则没有值
//在setPageInde()之前,要确保有totalPage countAll pageSize
pager.setPageIndex(pageIndex);
if (skipTo != null) {
pager.setSkipTo(skipTo);
System.out.println("跳转页面:"+pager.getSkipTo());
//要改变当前页奥
pager.setPageIndex(skipTo);
}
System.out.println("此时此刻:偏移量offset:++++++++"+pager.getOffset()+"当前页:"+pager.getPageIndex()+"每页数量:"+pager.getPageSize());
System.out.println(pager.getBegin()+" "+pager.getEnd());
// System.out.println("begin:***************"+pager.getBegin()+"结束:end:"+pager.getEnd()+"总数量:"+pager.getCount()+" 总页数:"+pager.getTotalPage());
List<Log> logList = logService.logList(userId, pager.getOffset(), pager.getPageSize());
System.out.println("查出来的日志对象列表:"+logList);
pager.setList(logList);
model.addAttribute("logList", logList);
model.addAttribute("pager", pager);
return "log/log";
}
}
4.页面代码
现在的页面代码是这个样子:
<form action="log/logList?pageIndex=${pager.skipTo}" method="get">
<tr>
<td colspan="8" align="center">
<!--当前页>1在显示首页 上一页 末页道理类似 -->
<c:if test="${pager.pageIndex>1 }">
<button>
<a href="log/logList?pageIndex=1">首页</a>
</button>
<button>
<a href="log/logList?pageIndex=${pager.pageIndex-1 }">上一页</a>
</button>
</c:if>
<c:forEach begin="${pager.begin}" end="${pager.end}" var="i">
<!-- 如果是当前页,不能点击 -->
<c:if test="${pager.pageIndex == i}">
${i}
</c:if>
<c:if test="${pager.pageIndex != i}">
<button>
<a href="log/logList?pageIndex=${i}">${i}</a>
</button>
</c:if>
</c:forEach>
<c:if test="${pager.pageIndex<pager.totalPage}">
<button>
<a href="log/logList?pageIndex=${pager.pageIndex+1 }">下一页</a>
</button>
<button>
<a href="log/logList?pageIndex=${pager.totalPage}">末页</a>
</button>
</c:if>
<!-- 好玩点,可以随便去哪一页-->
<select name="skipTo">
<option value="10">10</option>
<option value="25">25</option>
<option value="35">35</option>
</select>
<!-- <input type="hidden" name="skipTo" value="25"> -->
<input type="submit" value="跳转">
${pager.pageIndex}/${pager.totalPage}
</td>
</tr>
</form>
这样就好了许多!
相对以前,现在这个包装类放哪里都可用!需要说明的是,这里分页代码是显示5页,刚好和pageSize相同,其实一般分页都是5 或者10 使用者可以灵活变动。
然鹅,以前的是这个样子:
<tr>
<td colspan="4" align="center" >
<c:if test="${pageIndex>1 }">
<button onclick="window.location.href='textShow?pageIndex=1&categoryId=${categoryId }&search=${search}'" style="width:50px;height:25px;" >首页</button>
<button onclick="window.location.href='textShow?pageIndex=${pageIndex-1}&categoryId=${categoryId }&search=${search}'">上一页</button>
</c:if>
<!--总页数要>10 才按照每页10条分页 -->
<c:if test="${totalPage>=10}">
<!--处理前10页 -->
<c:if test="${pageIndex<=10 }">
<c:forEach var="i" begin="1" end="10">
<c:if test="${pageIndex==i}">
${i}
</c:if>
<c:if test="${pageIndex!=i }">
<button onclick="window.location.href='textShow?pageIndex=${i}&categoryId=${categoryId }&search=${search}'" style="width:25px;height:25px;">${i}</button>
</c:if>
</c:forEach>
</c:if>
<!-- 处理大于10页 小于(totalPage-10)页 -->
<c:if test="${pageIndex>10 and pageIndex<(totalPage-4 )}">
<c:forEach var="i" begin="${pageIndex-4 }" end="${pageIndex+5}">
<c:if test="${pageIndex==i}">
${i}
</c:if>
<c:if test="${pageIndex!=i }">
<button onclick="window.location.href='textShow?pageIndex=${i}&categoryId=${categoryId }&search=${search}'" style="width:25px;height:25px;">${i}</button>
</c:if>
</c:forEach>
</c:if>
<!-- 处理最后几页 -->
<c:if test="${pageIndex>=(totalPage-4) }">
<c:forEach var="i" begin="${totalPage-9}" end="${totalPage}">
<c:if test="${pageIndex==i}">
${i}
</c:if>
<c:if test="${pageIndex!=i }">
<button onclick="window.location.href='textShow?pageIndex=${i}&categoryId=${categoryId }&search=${search}'" style="width:25px;height:25px;">${i}</button>
</c:if>
</c:forEach>
</c:if>
</c:if>
<!-- 总页数小于10 -->
<c:if test="${totalPage<10 }">
<c:forEach var="i" begin="1" end="${totalPage}">
<c:if test="${pageIndex==i}">
${i}
</c:if>
<c:if test="${pageIndex!=i }">
<button onclick="window.location.href='textShow?pageIndex=${i}&categoryId=${categoryId }&search=${search}'" style="width:25px;height:25px;">${i}</button>
</c:if>
</c:forEach>
</c:if>
<c:if test="${pageIndex<totalPage }">
<button onclick="window.location.href='textShow?pageIndex=${pageIndex+1}&categoryId=${categoryId }&search=${search}'">下一页</button>
<button onclick="window.location.href='textShow?pageIndex=${totalPage}&categoryId=${categoryId }&search=${search}'" style="width:50px;height:25px;" >末页</button>
</c:if>
<span style="color:orange;">${pageIndex }</span>/${totalPage}
<!-- <div style="float:right;">`
<form action="#" mehtod="get">
<select id="goto" name="goto" >
<option value="5">5</option>
<option value="10">10</option>
<option value="20">20</option>
<input type="submit" value="goto">
</form>
</div> -->
</td>
</tr>
之前在页面做了过多的判断,导致页面很臃肿!没有对比就没有伤害呢。
当然喽,分页有很多框架,也有更加简便的方式,但是,自己的永远是最好的。
5.总结
1)LogMapper.xml中SQL语句的写法
多个参数传递,必须这么传值:
select g.logId,g.doTime,g.event,g.eventDetail,u.userId,u.userName,u.userNick
from
log g,SysUser u
where g.userId = u.userId
and u.userId = #{arg0}
order by g.logId desc
limit offset= #{arg1},pageSize = #{arg2}
注意:这里还必须写成arg0 arg1 arg2 否则找不到 Parameter ‘0’ not found. Available parameters are [arg2, arg1, arg0, param3, param1, param2]
以下这么传值是错误的,谁让我们用的是SSM框架呢。
select g.logId,g.doTime,g.event,g.eventDetail,u.userId,u.userName,u.userNick
from
log g,SysUser u
where g.userId = u.userId
and u.userId = #{userId}
order by g.logId desc
limit offset= #{offset},pageSize = #{pageSize}
错误传参!
2)在Pager包装工具类里面,为每个参数赋值很有讲究:
public int getBegin() {
//这里赋值没用,因为方法没发调用!我们当前页赋值是通过setPageIndex()赋值的,框架底层也是这样 所以应该写在setPageIndex()
if(pageIndex<=pageSize) {
begin = 1;
}else if(pageIndex <totalPage -pageSize) {
begin = pageIndex - (int)Math.round(pageSize/2.0);
}
return begin;
}
不能想当然的赋值,要考虑方法是否会被调用! 当然你在Controller测试的时候会调用,这也算调用了!
分页赋值的时候,一定要注意,在set()还是get()方法赋值,参数之间的依赖关系,以及是否需要人为调用。
Controller一定要调用的方法里面赋值。
反正就是一句话:如果页面出现begin<0之类或者没有效果,就表明你赋值的方法有问题,因为set() get()方法
根本就没被调用!所以,十分清楚流程很重要!
1.一定会调用setPageIndex()方法给当前页赋值
而页面的begin end是根据pageIndex来变化的,所以要在setPageIndex()里面为begin end赋值,而不是在各自的
getBegin() getEnd()里面赋值,非要赋值也可以,需要在手动在Controller里面调用,岂不麻烦?
2.一定会调用setCount()方法为总条目数赋值。
有了总条目数,那么totalPage()就有值了,totalPage赋值要在setCount()方法里赋值,原理和上面讲的相同。
begin end 总共分为3个板块,之前是在页面做的控制,这次直接在包装类里面作控制,大大提高复用率!
板块1:
<a href="log/logList?pageIndex=${pager.pageIndex-1}" >
<button>上一页</button>
</a>
这样是没发传参滴! 你点击的实际是button,button只能通过window.location.href=”“来传参!无语!!!这个你是很早就知道的,你要明白嵌套本质在于最内层控制!!!
好啦!开饭!下期预告:bbs优化 与总结~ 敬请期待!
本文分享了一种分页功能的封装方法,通过创建Pager工具类来提高代码复用率,减少页面逻辑负担,并详细介绍了其实现过程及注意事项。
6443

被折叠的 条评论
为什么被折叠?



