在数据库的查询中,经常会用到分页展示,这时候需要使用sql的limit来查出部分数据,然后通过java和前端进行下一页,或者前一页或者其它页码的操作。在用java进行分页的过程中,首先使用到Java代码
1、Java代码部分
(1)首先编辑Pager.java,在包com.lxp.model中,主要是维护分页的大小(分成多少页)、第几页、起始页、总记录数、每页上获取的数据,由于该java代码直接维护搜出来的数据,所以使用泛型Pager<T>,方便不同数据类型数据的存储
public class Pager<E> {
//第几页
private int pageIndex;
//每页显示多少条
private int pageSize;
//分页的开始值
private int pageOffset;
//总共多少条记录
private int totalRecord;
//总共多少页
private int totalPage;
//放置具体数据的列表
private List<E> datas;
public int getPageIndex() {
return pageIndex;
}
public void setPageIndex(int pageIndex) {
this.pageIndex = pageIndex;
}
public int getPageSize() {
return pageSize;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
public int getPageOffset() {
return pageOffset;
}
public void setPageOffset(int pageOffset) {
this.pageOffset = pageOffset;
}
public int getTotalRecord() {
return totalRecord;
}
public void setTotalRecord(int totalRecord) {
this.totalRecord = totalRecord;
}
public int getTotalPage() {
return totalPage;
}
public void setTotalPage(int totalPage) {
this.totalPage = totalPage;
}
public List<E> getDatas() {
return datas;
}
public void setDatas(List<E> datas) {
this.datas = datas;
}
}
(2)SystemContext.java,全文对象的java,该java文件中使用ThreadLocal对象维护各个线程的独立性,也就是每个人进来使用的分页都是和自身对象相关的,不受其它人的影响,首先,ThreadLocal 不是用来解决共享对象的多线程访问问题的,一般情况下,通过ThreadLocal.set() 到线程中的对象是该线程自己使用的对象,其他线程是不需要访问的,也访问不到的。各个线程中访问的是不同的对象。
1、每个线程中都有一个自己的ThreadLocalMap类对象,可以将线程自己的对象保持到其中,各管各的,线程可以正确的访问到自己的对象。
2、 将一个共用的ThreadLocal静态实例作为key,将不同对象的引用保存到不同线程的ThreadLocalMap中,然后在线程执行的各处通过这 个静态ThreadLocal实例的get()方法取得自己线程保存的那个对象,避免了将这个对象作为参数传递的麻烦。
具体的ThreadLocal介绍可以百度搜索
注:前面的Pager.java是对分页所有的相关属性进行维护,而本SystemContext.java则是用来维护一次搜索得到数据所需要的属性信息,如:每页显示多少条pageSize,第几页pageIndex、页码的开始值pageOffset、升序还是降序order、用来进行排序的字段sort,每个属性都是ThreadLocal对象维护
package com.lxp.model;
//与分页有关
public class SystemContext {
private static ThreadLocal<Integer> pageSize = new ThreadLocal<Integer>();
private static ThreadLocal<Integer> pageIndex = new ThreadLocal<Integer>();
private static ThreadLocal<Integer> pageOffset = new ThreadLocal<Integer>();
private static ThreadLocal<String> order = new ThreadLocal<String>();//升序还是降序
private static ThreadLocal<String> sort = new ThreadLocal<String>();//根据哪一个字段来
public static int getPageSize() {
return pageSize.get();
}
public static void setPageSize(int _pageSize) {
pageSize.set(_pageSize);
}
public static void removePageSize() {
pageSize.remove();
}
public static int getPageIndex() {
return pageIndex.get();
}
public static void setPageIndex(int _pageIndex) {
pageIndex.set(_pageIndex);
}
public static void removePageIndex() {
pageIndex.remove();
}
public static int getPageOffset() {
return pageOffset.get();
}
public static void setPageOffset(int _pageOffset) {
pageOffset.set(_pageOffset);
}
public static void removePageOffset() {
pageOffset.remove();
}
public static String getOrder() {
return order.get();
}
public static void setOrder(String _order) {
order.set(_order);
}
public static void removeOrder() {
order.remove();
}
public static String getSort() {
return sort.get();
}
public static void setSort(String _sort) {
sort.set(_sort);
}
public static void removeSort() {
sort.remove();
}
}
(3)java代码操作数据库并且对页码进行后台的java设置,以便前端的代码能够直接使用根据分页信息从数据库获取到的数据信息
public Pager<T> find(String sqlId,Map<String,Object> para) {
int pageSize = SystemContext.getPageSize();
int pageOffset = SystemContext.getPageOffset();
String order = SystemContext.getOrder();
String sort = SystemContext.getSort();
Pager<T> pages = new Pager<T>();
SqlSession session = null;
try {
session = MyBatisUtil.createSession();
if(para==null)
para = new HashMap<String, Object>();
para.put("pageSize", pageSize);
para.put("pageOffset", pageOffset);
para.put("order", order);
para.put("sort", sort);
List<T> datas = session.selectList(sqlId,para);
pages.setDatas(datas);
pages.setPageOffset(pageOffset);
pages.setPageSize(pageSize);
int totalRecord = session.selectOne(sqlId+"_count",para);//总数约定为查询一个+ _count
pages.setTotalRecord(totalRecord);
} finally {
MyBatisUtil.close(session);
}
return pages;
}
上述代码使用mybatis进行数据库的操作的
首先(1)通过SystemContext获取每页大小pageSize,起始pageOffset、排序信息、排序字段
然后(2)将这些获取到的信息保存到map中,这些信息保存起来是为了mybatis中通过map对这写信息进行获取,然后使用sql从数据库查询数据使用的,List<T> datas = session.selectList(sqlId,para);就是根据这个map信息从数据库获取查到的数据,、
最后(3)对pages进行重新赋值,如查询到的数据setDatas,分页起始值,每页大小,总记录数,之后返回Pager对象即可
(4)后台java代码进行测试,主要是首先对需要的如分页大小,分页起始、排序信息等信息进行设置,然后查询
@Test
public void testFind() {
// for(int i=0;i<3;i++) {
/* Thread t = new Thread(new Runnable() {
public void run() {
}
});
t.start();*/
/* if(i%3==0) {
System.out.println("i==:"+i);
new Thread(){
public void run() {
SystemContext.setPageOffset(5);
System.out.println("run1;");
SystemContext.setPageSize(15);
SystemContext.setOrder("asc");
SystemContext.setSort("id");
Pager<User> ps = ud.find(null);
System.out.println(ps.getTotalRecord());
for(User u:ps.getDatas()) {
System.out.println("other:"+u);
}
System.out.println("");
}
}.start();
} else {
new Thread(){
public void run() {
SystemContext.setPageOffset(1);
SystemContext.setPageSize(10);
SystemContext.setOrder("desc");
SystemContext.setSort("id");
Pager<User> ps = ud.find(null);
System.out.println(ps.getTotalRecord());
for(User u:ps.getDatas()) {
System.out.println(u);
}
System.out.println("");
}
}.start();
}
}*/
SystemContext.setPageOffset(0);
SystemContext.setPageSize(15);
SystemContext.setOrder("asc");
SystemContext.setSort("id");
Pager<User> ps = ud.find("白");
System.out.println("所有:"+ps.getTotalRecord());
for(User u:ps.getDatas()) {
System.out.println("main:"+u);
}
}
(5)在真正的web应用中,可以将分页信息放到filter中,这样再前端进行查询时,首先通过该filter获取相关的分页信息,保存起来,这样就可以提前完成上面(4)中测试需要的数据传递了,前端提交查询->filter过滤处理获取分页信息->到action->service->dao调用相应的如(3)中处理即可
public class SystemContextFilter implements Filter{
public void destroy() {}
public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain chain) throws IOException, ServletException {
int pageOffset = 0;//默认起始
int pageSize = 15;//默认分页大小
String sort = req.getParameter("sort");
String order = req.getParameter("order");
try {
try {
if(req.getParameter("pager.offset")==null){
pageOffset=0;
} else
pageOffset = Integer.parseInt(req.getParameter("pager.offset"));
} catch(NumberFormatException e) {
e.printStackTrace();
}
SystemContext.setPageOffset(pageOffset);
SystemContext.setPageSize(pageSize);
SystemContext.setSort(sort);
SystemContext.setOrder(order);
chain.doFilter(req, resp);
} finally {
SystemContext.removePageOffset();
SystemContext.removePageSize();
SystemContext.removeSort();
SystemContext.removeOrder();
}
}
public void init(FilterConfig arg0) throws ServletException {}
}
web.xml
<filter>
<filter-name>SystemContextFilter</filter-name>
<filter-class>com.lxp.web.SystemContextFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>SystemContextFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
2、前端处理页面
(1)list.jsp,改页面中有通过action中获取到的数据信息,并且包含了一个pager.jsp分页的页面,该pager.jsp页面中调用使用pager-taglib标签已经集成好的pager标签,需要导入pager-taglib.jar这个包以及jstl.jar这个包
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>用户列表</title>
</head>
<body>
<jsp:include page="inc.jsp"></jsp:include>
<table width="800" align="center" cellPaddign="0" cellspacing="0" class="thin-border">
<tr>
<td>用户标志</td>
<td>用户名</td>
<td>密码</td>
<td>昵称</td>
<td>类型</td>
<td>操作</td>
</tr>
<c:forEach items="${users.datas}" var="u" varStatus="num">
<tr>
<td>${u.id }</td>
<td>${u.username }</td>
<td>${u.password }</td>
<td><a href="user.do?method=show&id=${u.id }">${u.nickname }</a></td>
<td>
<c:if test="${u.type eq 0}">普通类型</c:if>
<c:if test="${u.type eq 1}">管理员</c:if>
<a href="user.do?method=changeType&id=${u.id }">变更</a>
</td>
<td>
<a href="user.do?method=updateInput&id=${u.id }">修改</a>
<a href="user.do?method=delete&id=${u.id }">删除</a>
</td>
</tr>
</c:forEach>
<c:if test="${empty users}">
<tr>
<td colspan="3">没有用户信息</td>
</tr>
</c:if>
<tr>
<td colspan="6">
<jsp:include page="/inc/pager.jsp">
<jsp:param value="${users.totalRecord}" name="items"/>
<jsp:param value="user.do" name="url"/>
<jsp:param value="method,name" name="params"/>
</jsp:include>
</td>
</tr>
</table>
</body>
</html>
(2)pager.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@taglib prefix="pg" uri="http://jsptags.com/tags/navigation/pager" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<pg:pager maxPageItems="15" items="${param.items }" export="curPage=pageNumber" url="${param.url}">
<c:forEach items="${param.params}" var="p">
<pg:param name="${p}"/>
</c:forEach>
<pg:last>
共${param.items}记录,共${pageNumber }页,
</pg:last>
当前第${curPage }页
<pg:first>
<a href="${pageUrl }">首页</a>
</pg:first>
<pg:prev>
<a href="${pageUrl }">上一页</a>
</pg:prev>
<pg:pages>
<c:if test="${curPage eq pageNumber}">
[${pageNumber }]
</c:if>
<c:if test="${curPage ne pageNumber }">
<a href="${pageUrl }">${pageNumber }</a>
</c:if>
</pg:pages>
<pg:next>
<a href="${pageUrl }">下一页</a>
</pg:next>
<pg:last>
<a href="${pageUrl }">尾页</a>
</pg:last>
</pg:pager>
(3)Action中的处理方式如下:
public class UserAction {
public String list(HttpServletRequest req,HttpServletResponse resp) {
Pager<User> users = userDao.find("");
req.setAttribute("users", users);
return "user/list.jsp";
}
}
补充:
编码过滤器
public class CharacterFilter implements Filter{
private String encoding;
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain chain) throws IOException, ServletException {
req.setCharacterEncoding(encoding);
chain.doFilter(req, resp);
}
public void init(FilterConfig cfg) throws ServletException {
encoding = cfg.getInitParameter("encoding");
if(encoding==null||"".equals(encoding.trim())) {
encoding = "UTF-8";
}
}
}