分页技术
2016/12/23
分页介绍
主要用在当页面上数据非常多的时候,不能在一个页面上全部显示。需要把页面上的数据分成好多子页面来显示。
例如:使用百度进行搜索,搜索的结果会很多,百度将所有的结果分成若干也进行显示。在每页的底部会有如下显示。
用户可以选择相应的数字,跳转到对应的页面查看搜索的信息。
本人编写的分页条使用的技术有:struts2框架,DButils,c3p0连接池
分页思路流程
页面 ----> servlet/action ----> service ----> dao
页面 <---- servlet/action <---- service <---- dao
-
思路:
1.页面传递给servlet/action 参数:pageCode
2.servlet/action获取到pageCode.再传递给Service, 最终servlet/action把PageBean传递给页面
3.Service通过dao层的方法获取总记录数和每页的记录数据进行处理,最终把封装好的PageBean返回给servlet/action
4.页面通过后台传过的数据用s标签或者EL表达式获取数据进行展示
分页最后的效果
第N页/共M页 首页 上一页 1 2 3 4 5 6 7 8 9 10 下一页 尾页 口—>下拉框
对页面进行分析
-
根据以上的效果分析出需要的条件:
1.当前页码 (pageCode)
pageCode是由page.jsp页面提供
2.总页数 (totalPage)
总页数是由总记录数和每页记录数计算得到的,公式:总页数=总记录数%每页记录数 ==0 ? 总记录数/每页记录数 : 总记录数/每页记录数 + 1
3.总记录数 (totalRecord)
总记录数是由查询数据库得到的 , select count(*) from user;
4.每页记录数 (pageSize)
每页记录数是由自己设定的
5.当前页记录 (datas)
当前页记录是由查数据库得到 ,select * from user limit (pageCode-1) * pageSize,pageSize;
1). 得到这些分页的数据把它们封装到一个javaBean中,命名为PageBean.java
PageBean.java
package fenye;
import java.util.List;
public class PageBean<T> {
private int pageCode;// 当前页码
// private int totalPage;// 总页数
private List<T> datas;// 当前页的记录
private int totalRecord;// 总记录
private int pageSize = 10;// 每页记录数
public PageBean() {
}
public PageBean(int pageCode, int totalRecord) {
this(pageCode, totalRecord, 10);
}
public PageBean(int pageCode, int totalRecord, int pageSize) {
this.pageCode = pageCode;
this.totalRecord = totalRecord;
this.pageSize = pageSize;
}
public int getPageCode() {
return pageCode;
}
public void setPageCode(int pageCode) {
this.pageCode = pageCode;
}
public List<T> getDatas() {
return datas;
}
public void setDatas(List<T> datas) {
this.datas = datas;
}
public int getTotalRecord() {
return totalRecord;
}
public void setTotalRecord(int totalRecord) {
this.totalRecord = totalRecord;
}
public int getPageSize() {
return pageSize;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
public int getTotalPage() {
// 计算totalPage
int totalPage = this.totalRecord / pageSize;
return totalRecord % pageSize == 0 ? totalPage : totalPage + 1;
}
}
2). servlet/action层给Service层传递pageCode,然后再Service层进行各种业务的处理完成对PageBean的创建与封装,最后返回给servlet/action
-
service层还要依赖dao层提供一些方法:
1.查询记录数的方法(count())
2.查询当前页的记录(queryByPage())
-
dao层使用c3p0连接池进行连接来操作数据库,
配置c3p0-config.xml
<c3p0-config>
<default-config>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/page</property>
<property name="user">root</property>
<property name="password">abc</property>
</default-config>
</c3p0-config>
- 提供数据库连接池 和数据库连接的工具类 JDBCUtils.java
JDBCUtils.java
package utils;
import java.sql.Connection;
import java.sql.SQLException;
import javax.sql.DataSource;
import com.mchange.v2.c3p0.ComboPooledDataSource;
/**
* 工具类 提供数据库连接池 和数据库连接
*
*/
public class JDBCUtils {
private static DataSource dataSource = new ComboPooledDataSource();
public static DataSource getDataSource() {
return dataSource;
}
/**
* 当DBUtil需要手动控制事务时,调用该方法获得一个连接
*
* @return
* @throws SQLException
*/
public static Connection getConnection() throws SQLException {
return dataSource.getConnection();
}
}
- dao层创建一个类 ,命名为:PageDao.java
PageDao.java
package fenye;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;
import org.apache.commons.lang3.StringUtils;
import utils.JDBCUtils;
public class PageDao {
private QueryRunner queryRunner = new QueryRunner(JDBCUtils.getDataSource());
/**
* 查询总记录数
*
*/
public int count(User user) {
String sql = "select count(*) from user where 1=1";
List<Object> list = new ArrayList<Object>();
if (StringUtils.isNotBlank(user.getUsername())) {
sql += " and username like ?";
list.add("%" + user.getUsername() + "%");
}
if (StringUtils.isNotBlank(user.getSex())) {
sql += " and sex = ?";
list.add(user.getSex());
}
// System.out.println(sql);
try {
Number number = (Number) queryRunner.query(sql, new ScalarHandler(), list.toArray());
return number.intValue();
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException("查询总记录数失败");
}
}
/**
* 分页查询
*
*/
public List<User> queryByPage(User user, int offset, int len) {
String sql = "select * from user where 1=1";
List<Object> list = new ArrayList<Object>();
if (StringUtils.isNotBlank(user.getUsername())) {
sql += " and username like ?";
list.add("%" + user.getUsername() + "%");
}
if (StringUtils.isNotBlank(user.getSex())) {
sql += " and sex = ?";
list.add(user.getSex());
}
sql += " limit ?, ?";
list.add(offset);
list.add(len);
// System.out.println(sql);
try {
return queryRunner.query(sql, new BeanListHandler<User>(User.class), list.toArray());
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException("分页查询失败");
}
}
}
3). service层接受servlet/action传过的User对象和pageCode参数来处理业务封装PageBean对象 然后返回给servlet/action
User.java
package fenye;
public class User {
private int id;
private String username;
private String password;
private String sex;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
@Override
public String toString() {
return "User [id=" + id + ", username=" + username + ", password=" + password + ", sex=" + sex + "]";
}
}
PageService.java
package fenye;
import java.util.List;
public class PageService {
private PageDao pageDao = new PageDao();
public PageBean<User> queryByBean(User user, int pageCode) {
// 获取总记录数
int totalRecord = pageDao.count(user);
// 使用当前页码和总记录数创建PageBean
PageBean<User> pageBean = new PageBean<User>(pageCode, totalRecord);
// 查询本页记录
List<User> datas = pageDao.queryByPage(user, (pageCode - 1) * pageBean.getPageSize(), pageBean.getPageSize());
// 保存pageBean中
pageBean.setDatas(datas);
// 返回pageBean
return pageBean;
}
}
4). servlet/action层接受service层返回的PageBean对象,将其保存在域中或值栈中反馈给page.jsp页面
UserACtion.java
package fenye;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
public class UserAction extends ActionSupport implements ModelDriven<User> {
private User user = new User();
@Override
public User getModel() {
return user;
}
public String page() throws Exception {
HttpServletRequest request = ServletActionContext.getRequest();
HttpServletResponse response = ServletActionContext.getResponse();
PageQuery pageQuery = new PageQuery();
pageQuery.query(request, response, user);
return "page";
}
}
PageQuery.java
package fenye;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.apache.struts2.ServletActionContext;
public class PageQuery {
public String query(HttpServletRequest request, HttpServletResponse response, User user) throws ServletException, IOException {
/*
* 创建超链接的条件
* 因为表单提交会请求本方法
* 因为在分页的导航条中的超链接,也要请求本方法
* 但在分页的超链接中没有条件,这会变成查询所有,而不是条件查询
* 所以必须把条件传递到页面上
*/
StringBuilder sb = new StringBuilder();
String username = user.getUsername();
if (StringUtils.isNotBlank(user.getUsername())) {
if (request.getMethod().equalsIgnoreCase("get")) {
username = new String(username.getBytes("iso-8859-1"), "utf-8");
user.setUsername(username);
}
sb.append("&username=").append(username);
}
String sex = user.getSex();
if (StringUtils.isNotBlank(user.getSex())) {
if (request.getMethod().equalsIgnoreCase("get")) {
sex = new String(sex.getBytes("iso-8859-1"), "utf-8");
user.setSex(sex);
}
sb.append("&sex=").append(sex);
}
// System.out.println(sb.toString());
ServletActionContext.getContext().put("url", sb.toString());
int pageCode = 1;
String s = request.getParameter("pageCode");
if (s != null && !s.trim().isEmpty()) {
pageCode = Integer.parseInt(s);
}
PageService pageService = new PageService();
PageBean<User> UserList = pageService.queryByBean(user, pageCode);
ServletActionContext.getContext().put("UserList", UserList);
return "true";
}
}
5). 在工程的src下配置struts2的配置文件struts.xml
配置struts.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<constant name="struts.enable.DynamicMethodInvocation" value="false" />
<constant name="struts.devMode" value="true" />
<constant name="struts.ui.theme" value="simple"/>
<package name="default" namespace="/" extends="struts-default">
<action name="user_*" class="fenye.UserAction" method="{1}">
<result name="page">/page.jsp</result>
</action>
</package>
</struts>
配置web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_9" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>Struts2</display-name>
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
</web-app>
6). 页面:
使用的是c标签:
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<c:set var="root" value="${pageContext.request.contextPath}"/>
page.jsp—分页条的代码
<!-- 主要完成根据指定的内容查询相应的联系人 -->
<div>
<form action="${pageContext.request.contextPath}/user_page" method="post">
<table>
<tr>
<td align="center">根据指定的信息查询</td>
</tr>
<tr>
<td>用户名</td>
<td><input type="text" name="username"/></td>
<td>性别</td>
<td><input type="text" name="sex"/></td>
</tr>
<tr>
<td>
<input type="submit" value="查询"/>
</td>
</tr>
</table>
</form>
</div>
<!-- 完成显示功能 -->
<div>
<table border="1" cellpadding="5" cellspacing="0" width="300px">
<tr>
<td>id</td>
<td>用户名</td>
<td>密码</td>
<td>性别</td>
</tr>
<s:iterator value="#UserList.datas" var="user">
<tr>
<td>
<s:property value="#user.id"/>
</td>
<td>
<s:property value="#user.username"/>
</td>
<td>
<s:property value="#user.password"/>
</td>
<td>
<s:property value="#user.sex"/>
</td>
</tr>
</s:iterator>
</table>
<!-- 分页的实现 -->
第${UserList.pageCode}页/共${UserList.totalPage}页
<a href="${root}/user_page?pageCode=1${url}">首页</a>
<c:if test="${UserList.pageCode > 1}">
<a href="${root}/user_page?pageCode=${UserList.pageCode - 1}${url}">上一页</a>
</c:if>
<!-- 页码列表 -->
<c:set var="begin" value="1"/>
<c:set var="end" value="10"/>
<!-- 定位begin和end -->
<c:choose>
<c:when test="${UserList.totalPage <= 10}">
<c:set var="begin" value="1"/>
<c:set var="end" value="${UserList.totalPage}"/>
</c:when>
<c:otherwise>
<c:choose>
<c:when test="${UserList.pageCode - 4 < 1}">
<c:set var="begin" value="1"/>
<c:set var="end" value="10"/>
</c:when>
<c:when test="${UserList.pageCode + 5 > UserList.totalPage}">
<c:set var="begin" value="${UserList.totalPage - 9}"/>
<c:set var="end" value="${UserList.totalPage }"/>
</c:when>
<c:otherwise>
<c:set var="begin" value="${UserList.pageCode - 4}"/>
<c:set var="end" value="${UserList.pageCode + 5 }"/>
</c:otherwise>
</c:choose>
</c:otherwise>
</c:choose>
<c:forEach begin="${begin}" end="${end}" var="i">
<c:choose>
<c:when test="${UserList.pageCode eq i}">${i}</c:when>
<c:otherwise>
<a href="${root}/user_page?pageCode=${i}${url}">[${i}]</a>
</c:otherwise>
</c:choose>
</c:forEach>
<c:if test="${UserList.pageCode < UserList.totalPage}">
<a href="${root}/user_page?pageCode=${UserList.pageCode + 1}${url}">下一页</a>
</c:if>
<a href="${root}/user_page?pageCode=${UserList.totalPage}${url}">尾页</a>
<!-- 下拉列表 -->
<select name="pageCode" onchange="_go(this)">
<c:forEach begin="1" end="${UserList.totalPage}" var="i">
<option value="${i}" <c:if test="${UserList.pageCode eq i}">selected='selected'</c:if>>${i}</option>
</c:forEach>
</select>
</div>
<!--分页条使用到的js-->
<script type="text/javascript">
function _go(select){
var index = select.selectedIndex;//选中的option的下标
var option = select.options[index];//通过下标得到option元素的对象
var value = option.value;//通过option元素对象得到value值
location="${root}/user_page?pageCode="+value+"${url}";
}
</script>
- 仅供参考,欢迎大家指出错误!!!