JavaWeb分页了解一下
Posted weolwy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaWeb分页了解一下相关的知识,希望对你有一定的参考价值。
虽然现在有很多框架可以很简单的实现分页这个功能,但是我觉的对于初学者来说,还是很有必要学习自己手动实现分页这个功能,更好的理解分页的原理,编程最重要的就是思想.
1 思路分析
在写代码之前我们得分析怎样实现分页,把思路分析清楚了,写起代码来才能游刃有余.我们来看看分页的效果.
![image]
这就是我们要实现的效果从效果图中我们可以看到,要把数据按照我们希望的方式展示,我么能的到的数据有
totalPage 总页数
currentPage 当前页数
pageSize 每页显示的数据条数
totalSize 总的数据条数
还有就是每页显示的数据条数,是需要我们从后台时时传过来的,那我们可以把这些每页显示的数据封装到一个JavaBean中,然后把它存到域对象中,最后展示到前端页面.
如果上面的这些数据我们一个一个的从后台去取的话,操作起来太麻烦了,于是我们想,前台不就是需要这些数据吗?那我们可以把这些数据有封装到一个PageBean对象身上,到时候把它页存到域对象中,然后到jsp页面展示出来不就行了吗,对吧?
List<T> 用于存放每页要显示的数据的list
创建Product Bean用来封装从数据库中的到的数据
package bean;
?
import java.io.Serializable;
import java.util.Date;
?
public class Product implements Serializable{
private static final long serialVersionUID = 2078432725470146037L;
//商品pid
private String pid;
//商品名称
private String pname;
//市场价格
private Double market_price;
//商城价格
private Double shop_price;
//商品图片
private String pimage;
//商品上架时间
private String pdate;
//商品描述
private String pdesc;
public String getPid() {
return pid;
}
public void setPid(String pid) {
this.pid = pid;
}
public String getPname() {
return pname;
}
public void setPname(String pname) {
this.pname = pname;
}
public Double getMarket_price() {
return market_price;
}
public void setMarket_price(Double market_price) {
this.market_price = market_price;
}
public Double getShop_price() {
return shop_price;
}
public void setShop_price(Double shop_price) {
this.shop_price = shop_price;
}
public String getPimage() {
return pimage;
}
public void setPimage(String pimage) {
this.pimage = pimage;
}
public String getPdate() {
return pdate;
}
public void setPdate(String pdate) {
this.pdate = pdate;
}
public String getPdesc() {
return pdesc;
}
public void setPdesc(String pdesc) {
this.pdesc = pdesc;
}
public static long getSerialversionuid() {
return serialVersionUID;
}
@Override
public String toString() {
return "Product [pid=" + pid + ", pname=" + pname + ", market_price=" + market_price + ", shop_price="
+ shop_price + ", pimage=" + pimage + ", pdate=" + pdate + ", pdesc=" + pdesc + "]";
}
}
创建PageBean用来封装前台页面需要的数据
package bean;
?
import java.io.Serializable;
import java.util.List;
?
public class PageBean implements Serializable{
private static final long serialVersionUID = 1L;
//当页要显示的商品集合
private List<Product> list;
//当前页数
private int currentPage;
//每页显示数据条数
private int pageSize;
//总页数
private int totalPage;
//总条数
private Long totalSize;
//每页要显示的数据
public List<Product> getList() {
return list;
}
?
public void setList(List<Product> list) {
this.list = list;
}
?
public int getCurrentPage() {
return currentPage;
}
?
public void setCurrentPage(int currentPage) {
this.currentPage = currentPage;
}
?
public int getPageSize() {
return pageSize;
}
?
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
?
public int getTotalPage() {
return totalPage;
}
?
public void setTotalPage(int totalPage) {
this.totalPage = totalPage;
}
?
public Long getTotalSize() {
return totalSize;
}
?
public void setTotalSize(Long totalSize) {
this.totalSize = totalSize;
}
?
@Override
public String toString() {
return "PageBean [list=" + list + ", currentPage=" + currentPage + ", pageSize=" + pageSize + ", totalPage="
+ totalPage + ", totalSize=" + totalSize + "]";
}
}
在Dao层操作数据库,完成数据的封装
package dao;
?
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
?
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;
?
import com.sun.org.apache.bcel.internal.generic.NEW;
?
import bean.Product;
import utils.C3P0Utils;
import utils.DBUtils;
import utils.TransctionManager;
?
public class ProductDao {
?
/**
* 每页显示的商品集合
*
* @param pageSize
* @param currentPage
* @throws SQLException
*/
public List<Product> pageProduct(int currentPage, int pageSize) throws SQLException {
int a = (currentPage - 1) * pageSize;
QueryRunner runner = new QueryRunner(C3P0Utils.getDataSource());
String sql = "select * from product limit ?,?";
List<Product> list = runner.query(sql, new BeanListHandler<>(Product.class),a,pageSize);
return list;
}
/**
* 查询总记录数
*/
public Long queryProductCount() throws SQLException {
QueryRunner runner = new QueryRunner(C3P0Utils.getDataSource());
String sql = "select count(*) from product";
Long count = (Long) runner.query(sql, new ScalarHandler());
return count;
}
?
}
在Service层完成业务逻辑
package service;
?
import java.sql.SQLException;
import java.util.List;
?
import bean.PageBean;
import bean.Product;
import dao.ProductDao;
import utils.TransctionManager;
?
public class ProductService {
/**
* 分页查询所有商品
*/
public PageBean pageQuery(int currentPage) {
// 封装PageBean
/**
* 分别获取到: 当前页 每页显示数据条数 每页要显示的商品集合 总页数 总数据条数
*/
PageBean bean = new PageBean();
// 当前页
bean.setCurrentPage(currentPage);
// 每页显示数据条数
int pageSize = 5;
bean.setPageSize(pageSize);
// 每页要显示的商品集合
ProductDao dao = new ProductDao();
try {
List<Product> products = dao.pageProduct(currentPage, pageSize);
bean.setList(products);
?
// 总数据条数
Long totalSize = dao.queryProductCount();
bean.setTotalSize(totalSize);
// 总页数
int totalPage = 0;
totalPage = (int) (totalSize / pageSize);
if (totalSize % pageSize != 0) {
?
totalPage++;
}
bean.setTotalPage(totalPage);
} catch (SQLException e) {
e.printStackTrace();
}
return bean;
}
?
}
在Servlet中编写控制代码
package servlet;
?
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Writer;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
import java.util.UUID;
?
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
?
import org.apache.commons.beanutils.BeanUtils;
?
import bean.PageBean;
import bean.Product;
import service.ProductService;
import utils.DateUtil;
?
/**
* 用来处理分页的Servlet,利用反射技术实现动态获取前台调用的方法,这里使用反射技术是为了增 强代码的可维护性.
如果不使用反射技术,那么我们要么只能时针对前台的每个请求我们都写一个Servlet,或者使用if{}else if 来判断前台传过来的方法名
*/
public class BigServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
?
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 解决中文乱码问题
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
?
String methods = request.getParameter("method");
//通过反射技术获取servlet字节码文件对象,创建对象然后调用方法,注意:一个servlet只有只有一个对象
Class<? extends BigServlet> clazz = this.getClass();
try {
Method method = clazz.getMethod(methods, HttpServletRequest.class,HttpServletResponse.class);
method.invoke(this,request,response);
} catch (Exception e) {
e.printStackTrace();
}
?
}
?
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
/**
* 分页查询
*/
public void page(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
//获取请求参数
int currentPage = Integer.parseInt(request.getParameter("currentPage"));
//调用业务层的方法获取pageBean
ProductService service=new ProductService();
PageBean bean=service.pageQuery(currentPage);
//把数据存入域对象中
HttpSession session = request.getSession();
session.setAttribute("page",bean);
response.sendRedirect(request.getContextPath()+"/page.jsp");
}
}
C3P0连接池工具类
package utils;
?
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
?
import javax.sql.DataSource;
?
import com.mchange.v2.c3p0.ComboPooledDataSource;
?
public class C3P0Utils {
/**
* c3p0连接池工具类
*/
private static ComboPooledDataSource dataSource;
static {
dataSource=new ComboPooledDataSource();
}
public static DataSource getDataSource() {
return dataSource;
}
public static Connection getConnection() {
Connection con=null;
try {
con= dataSource.getConnection();
} catch (SQLException e) {
System.out.println(e);
throw new RuntimeException("数据库链接异常,请联系技术人员");
}
return con;
}
public static void close(ResultSet resultSet,PreparedStatement ps,Connection con) {
if (resultSet!=null) {
try {
resultSet.close();
} catch (Exception e) {
System.out.println(e);
}
}
if (ps!=null) {
try {
ps.close();
} catch (Exception e) {
System.out.println(e);
}
}
if (con!=null) {
try {
con.close();
} catch (Exception e) {
System.out.println(e);
}
}
}
}
用于封装数据的工具类(这个可以用commons-dbutils-1.4.jar代替),这个工具类可以自己封装,新手建议自己封装一下
package utils;
?
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
?
import javax.management.RuntimeErrorException;
import javax.sql.DataSource;
?
public class DBUtils {
/**
* 操作数据库的工具类
*/
private DataSource dataSource;
?
public DBUtils(DataSource dataSource) {
?
this.dataSource = dataSource;
}
?
// 增删改方法
public int update(String sql, Object[] params) {
PreparedStatement ps = null;
int num = 0;
// 注册驱动,获得链接
Connection con = C3P0Utils.getConnection();
// 获取执行对象
try {
ps = con.prepareStatement(sql);
// 设置?处参数
if (params != null) {
for (int i = 1; i <= params.length; i++) {
?
ps.setObject(i, params[i - 1]);
}
}
num = ps.executeUpdate();
} catch (SQLException e) {
?
System.out.println(e);
?
throw new RuntimeException("数据库链接异常,请联系技术人员");
}
// 关闭资源
C3P0Utils.close(null, ps, con);
return num;
}
?
// 操作数据实现查询多条数据功能
public <E> List<E> query(String sql, Object[] params, Class<E> clazz) {
PreparedStatement ps = null;
List<E> list = null;
ResultSet set = null;
// 1注册驱动,获取链接
Connection con = C3P0Utils.getConnection();
try {
// 2后去执行对象
ps = con.prepareStatement(sql);
// 设置?处参数
if (params != null) {
for (int i = 1; i <= params.length; i++) {
?
ps.setObject(i, params[i - 1]);
}
}
// 利用ps动态获取所有字段名
ResultSetMetaData metaData = ps.getMetaData();
// 利用字节码文件对象获取clazz对象中所有的方法
Method[] methods = clazz.getMethods();
// 3执行sql语句,处理结果集
set = ps.executeQuery();
// 遍历结果集,并把结果集封装到对象中,再把每对象封装到集合中
// 创建一个集合用于封装每个对象
list = new ArrayList<>();
while (set.next()) {
// 创建对象用于封装每条数据
E e = clazz.newInstance();
// 遍历metaData获取每一个字段名
for (int i = 1; i <= metaData.getColumnCount(); i++) {
String columnName = metaData.getColumnName(i);
// 根据列明,获取每一列数据
Object object = set.getObject(columnName);
// 遍历所有方法,找出setxx()的方法
for (Method method : methods) {
String name = method.getName();
if (name.equalsIgnoreCase("set" + columnName)) {
?
method.invoke(e, object);
}
}
}
list.add(e);
}
} catch (Exception e) {
?
System.out.println(e);
?
throw new RuntimeException("数据库链接异常,请联系技术人员");
}
// 关闭资源
C3P0Utils.close(set, ps, con);
return list;
}
?
// 操作数据实现查询一条数据
public <E> E queryBean(String sql, Object[] params, Class clazz) {
PreparedStatement ps = null;
ResultSet resultSet = null;
E e = null;
// 1注册驱动,获得链接