JSP整合Servlet实现信息分页功能

这篇博客演示了如何结合JSP和Servlet实现用户信息的分页功能,利用JDBC连接MySQL数据库,DBUtil封装数据库操作,User类和PageInfo类封装数据,UserDao和UserDaoImpl处理DAO层逻辑,UserService和UserServiceImpl处理业务逻辑,FindUsersLimitServlet负责Servlet层交互,最后在limituser.jsp展示分页结果,采用了Bootstrap美化前端页面。
摘要由CSDN通过智能技术生成

本期博客主要实现JSP整合Servlet实现用户信息的分页功能,采用JDBC连接数据库,简单应用了BootStrap作为前端页面模板,具体细节如下所示。

Util层

DBUtil类

该层主要用于对JDBC连接Mysql数据库进行方法的封装,方便其他类进行调用,代码如下:

package cn.chen.web2.util;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class DBUtil {
	
		//声明连接的时候,需要用的内容:驱动地址  连接地址  用户名  密码
		private static final String DRIVER = "com.mysql.jdbc.Driver";
		private static final String NAME = "root";
		private static final String PWD = "123456";
		private static final String URL = "jdbc:mysql://127.0.0.1:3306/db_ordermeal?characterEncoding=utf-8";
		//声明连接对象   预编译对象(进行SQL操作时使用)  结果集对象(查询时使用)
		private static Connection con = null;
		private static PreparedStatement ps = null;
		private static ResultSet rs = null;
		//1.使用静态代码块加载驱动,驱动只需要加载一次
		static{
			try {
				Class.forName(DRIVER);
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			}
		}
		//2.获取数据库连接的方法,使用 protected进行修饰,其他包中,只有子类可以使用这些方法,保护了当前类的方法
		protected static void getConnection(){
			try {
				con = DriverManager.getConnection(URL, NAME, PWD);
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		//3.关闭连接的方法,回收资源
		protected static void closeAll(){
			if(null!=rs){
				try {
					rs.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
			if(null!=ps){
				try {
					ps.close();
				} catch (SQLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			if(null!=con){
				try {
					con.close();
				} catch (SQLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
		//4.开启事务的方法
		protected static void beginTransacation(){
			//获取连接
			getConnection();
			//对于mysql数据库而言,只是将自动提交功能关闭
			try {
				con.setAutoCommit(false);
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		//5.提交事务
		protected static void commit(){
			try {
				con.commit();//提交
				con.setAutoCommit(true);//打开自动提交功能
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}	
		}
		//6.回滚事务
		protected static void rollback(){
			try {
				con.rollback();
				con.setAutoCommit(true);//打开自动提交功能
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}	
		}
		
		//7.公共的增,删,改的方法
		protected static int executeUpdate(String sql,Object[] obj){
			int count = 0;//用于统计  有多少条记录被操作了,最为返回值
			beginTransacation();//开启事务    包含了获取数据库连接及开启事务的功能
			try {
				ps = con.prepareStatement(sql);//将sql语句传递给预编译对象,让sql语句可以在预编译对象中进行重新组装
				/*
				 * 例如  :insert into student values (1,'刘',20,0,'2000-1-1','911')   数值会变化
				 * 我们会传入sql语句改为insert into student values (?,?,?,?,?,?)
				 * ?的值是从Object[]数组中取出来的进行组装
				 */
				//obj有内容进行sql语句拼装
				if(null!=obj){
					for(int i=0;i<obj.length;i++){
						ps.setObject(i+1, obj[i]);//将Object[]数组中  每个位置的内容  替换? 内容  
					}
				}
				//如果Object[]中没有内容,则认为sql文是完整的,可以直接使用 
				count = ps.executeUpdate();
				commit();//提交事务
			} catch (SQLException e) {
				// 如果操作失败,肯定会发生异常,这个时候进行回滚事务
				e.printStackTrace();
				System.out.println(e);
				rollback();//回滚事务
			}finally{//操作完成后,无论是否发生异常,都需要关闭资源进行回收
				closeAll();//调用关闭连接的方法
			}
			return count;
		}
		
		//8.公共的查询方法
		protected static ResultSet executeQuery(String sql,Object[] obj){
			beginTransacation();
			try {
				ps = con.prepareStatement(sql);
				//obj有内容,进行sql语句拼装
				if(null!=obj){
					for(int i=0;i<obj.length;i++){
						ps.setObject(i+1, obj[i]);//将Object[]数组中  每个位置的内容  替换? 内容  
					}
				}
				//如果Object[]中没有内容,则认为sql文是完整的,可以直接使用 
				rs = ps.executeQuery();
				commit();//提交事务
			} catch (SQLException e) {
				// 如果操作失败,肯定会发生异常,这个时候进行回滚事务
				e.printStackTrace();
				rollback();//回滚事务
			}//在这个公共方法里,不要使用finally,进行关闭资源操作,因为结果集rs对象需要处理,关闭后无法处理
			return rs;
		}
}

Entity层

实体层包含用户User类以及分页PageInfo类,具体代码如下:

User类
package cn.chen.web2.entity;

/**
 * 用户实体类
 * @author dell
 *
 */
public class User {
	
	private int uId;
	private String uName;
	private String uPwd;
	private String uPhone;
	private double uBalance;
	private int uState;
	private int uRole;
	private String uImage;//用户头像
	
	public int getuId() {
		return uId;
	}
	public void setuId(int uId) {
		this.uId = uId;
	}
	public String getuName() {
		return uName;
	}
	public void setuName(String uName) {
		this.uName = uName;
	}
	public String getuPwd() {
		return uPwd;
	}
	public void setuPwd(String uPwd) {
		this.uPwd = uPwd;
	}
	public String getuPhone() {
		return uPhone;
	}
	public void setuPhone(String uPhone) {
		this.uPhone = uPhone;
	}
	public double getuBalance() {
		return uBalance;
	}
	public void setuBalance(double uBalance) {
		this.uBalance = uBalance;
	}
	public int getuState() {
		return uState;
	}
	public void setuState(int uState) {
		this.uState = uState;
	}
	public int getuRole() {
		return uRole;
	}
	public void setuRole(int uRole) {
		this.uRole = uRole;
	}
	
	public String getuImage() {
		return uImage;
	}
	public void setuImage(String uImage) {
		this.uImage = uImage;
	}
	
	public User(int uId, String uName, String uPwd, String uPhone, double uBalance, int uState, int uRole,String uImage) {
		super();
		this.uId = uId;
		this.uName = uName;
		this.uPwd = uPwd;
		this.uPhone = uPhone;
		this.uBalance = uBalance;
		this.uState = uState;
		this.uRole = uRole;
		this.uImage = uImage;
	}
	public User() {
		super();
	}
	public User(String uName, String uPwd, String uPhone) {
		super();
		this.uName = uName;
		this.uPwd = uPwd;
		this.uPhone = uPhone;
	}
	
	public User(String uName, String uPwd, String uPhone, String uImage) {
		super();
		this.uName = uName;
		this.uPwd = uPwd;
		this.uPhone = uPhone;
		this.uImage = uImage;
	}
	
	public User(String uName, String uPwd) {
		super();
		this.uName = uName;
		this.uPwd = uPwd;
	}
	
	@Override
	public String toString() {
		return "User [uId=" + uId + ", uName=" + uName + ", uPwd=" + uPwd + ", uPhone=" + uPhone + ", uBalance="
				+ uBalance + ", uState=" + uState + ", uRole=" + uRole + ", uImage=" + uImage + "]";
	}
}

PageInfo类
package cn.chen.web2.entity;

import java.util.List;

/**
 * 分页实体类
 * 1.数据:(用户信息,商品信息等)
 * 2.当前页码
 * 3.最大页码
 * @author autumn_leaf
 *
 */
public class PageInfo<T> {
	private List<T> datas;
	private int currentPage;
	private int maxPage;
	public PageInfo(List<T> datas, int currentPage, int maxPage) {
		super();
		this.datas = datas;
		this.currentPage = currentPage;
		this.maxPage = maxPage;
	}
	public PageInfo() {
		super();
	}
	public List<T> getDatas() {
		return datas;
	}
	public void setDatas(List<T> datas) {
		this.datas = datas;
	}
	public int getCurrentPage() {
		return currentPage;
	}
	public void setCurrentPage(int currentPage) {
		this.currentPage = currentPage;
	}
	public int getMaxPage() {
		return maxPage;
	}
	public void setMaxPage(int maxPage) {
		this.maxPage = maxPage;
	}
	@Override
	public String toString() {
		return "PageInfo [datas=" + datas + ", currentPage=" + currentPage + ", maxPage=" + maxPage + "]";
	}
	
}

这里关于分页实体我们进行一次说明,通过定义泛型,传入的T可以是用户信息,也可以是其他信息,这样便利于使用多次PageInfo类,里面定义数据当前页码以及最大页码

Dao层

UserDao类

这里UserDao用作接口,代码如下:

package cn.chen.web2.dao;

import java.util.List;

import cn.chen.web2.entity.User;

public interface UserDao {
	/**
	 * 分页查询(不包含条件)
	 * @pageNo 当前页码
	 * @pageSize 每页显示条数 
	 */
	public List<User> findUsersByLimit(int pageNo,int pageSize);
	/**
	 * 查询总条数
	 */
	public int countUsers();

该接口层我们主要定义了两个方法,一个用于查询分页的用户信息,一个用于查询记录总条数。

UserDaoImpl类

该类用于UserDao的接口实现类,用于SQL语句的编写,实现查询功能,代码如下:

package cn.chen.web2.dao.impl;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import cn.chen.web2.dao.UserDao;
import cn.chen.web2.entity.User;
import cn.chen.web2.util.DBUtil;

public class UserDaoImpl extends DBUtil implements UserDao {

	private List<User> dealUsers(ResultSet rs,List<User> 	users) {
		try {
			while(rs.next()) {
				users.add(new User(rs.getInt(1),
						rs.getString(2),
						rs.getString(3),
						rs.getString(4),
						rs.getDouble(5),
						rs.getInt(6),
						rs.getInt(7),
						rs.getString(8)));
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return users;
	}
	
	@Override
	public List<User> findUsersByLimit(int pageNo, int pageSize) {
		String sql = "select * from tb_user limit "+(pageNo-1)*pageSize+","+pageSize;
		//例如:pageSize是3,pageNo为1,limit 0,3
		ResultSet rs = super.executeQuery(sql, null);
		List<User> users = new ArrayList<User>();
		dealUsers(rs,users);
		return users;
	}

	@Override
	public int countUsers() {
		int total = 0;
		String sql = "select count(*) from tb_user";
		ResultSet rs = super.executeQuery(sql, null);
		try {
			while(rs.next()) {
				total = rs.getInt("count(*)");//将结果赋值给total
			}
		}catch(Exception e) {
			e.printStackTrace();
		}
		return total;
	}

这里我们对代码简单解释一下,其中dealUsers方法进行了封装,findUsersByLimit实现了具体的分页查询功能,这里SQL语句中limit后面传入两个参数,一个是当前页的首条记录编号(从0开始计数),一个是每页条数,我们可以计算出第一个参数为(pageNo-1)*pageSize,第二个参数为pageSize;countUsers方法则是通过计算总的用户信息条数获取total的值,并作为返回值,这里计算总条数目的是计算出最大页码数,为Service层做准备。

Service层

该层主要通过调用Dao层的方法,实现具体的业务逻辑,详细代码如下:

UserService类

该类是一个接口,主要提供相应的方法,代码如下:

package cn.chen.web2.service;

import java.util.List;
import cn.chen.web2.entity.PageInfo;
import cn.chen.web2.entity.User;

public interface UserService {
	/**
	 * 分页业务逻辑
	 */
	public PageInfo<User> findUserByLimit(int pageNo,int pageSize);
}
UserServiceImpl类

该类主要用于实现UserService接口,具体实现如何进行分页记录用户信息,并把PageInfo类定义的三个属性求出来,具体代码如下:

package cn.chen.web2.service.impl;

import java.util.List;

import cn.chen.web2.dao.UserDao;
import cn.chen.web2.dao.impl.UserDaoImpl;
import cn.chen.web2.entity.PageInfo;
import cn.chen.web2.entity.User;
import cn.chen.web2.service.UserService;

public class UserServiceImpl implements UserService {
	private UserServiceImpl() {
		super();
	}
	
	private static UserServiceImpl userService = new UserServiceImpl();
	private UserDao userDao = new UserDaoImpl();
	
	public static UserServiceImpl getUserService() {
		return userService;
	}
	
	@Override
	public PageInfo<User> findUserByLimit(int pageNo, int pageSize) {
		PageInfo<User> pageInfo = new PageInfo<>();
		//查询数据
		List<User> users = userDao.findUsersByLimit(pageNo, pageSize);
		//将查询到的数据放入pageInfo中
		pageInfo.setDatas(users);
		//将页码放入当前页码
		pageInfo.setCurrentPage(pageNo);
		//最大页码处理
		//a.查询总条目数
		int count = userDao.countUsers();
		int maxPage = 0;
		//b.判断数据与每页显示条目的关系
		if(count%pageSize == 0) {
			maxPage = count/pageSize;
		}else {
			maxPage = count/pageSize+1;
		}
		//将最大页码放入pageInfo
		pageInfo.setMaxPage(maxPage);
		return pageInfo;
	}

以上代码具体实现了findUsersByLimit的方法,我们把查询到的用户信息users放入数据里,把pageNo放入当前页中,通过判断总条数与每页条目之间的关系,进而求出最大的页码数

Servlet层

该层主要与jsp界面进行交互,并调用Service层中已实现的方法,详细代码如下:

FindUsersLimitServlet类
package cn.chen.web2.action;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


import cn.chen.web2.entity.PageInfo;
import cn.chen.web2.entity.User;
import cn.chen.web2.service.UserService;
import cn.chen.web2.service.impl.UserServiceImpl;

/**
 * Servlet implementation class FindUsersLimitServlet
 */
@WebServlet("/FindUsersLimitServlet")
public class FindUsersLimitServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
	
	private UserService userService = UserServiceImpl.getUserService();

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//1.获取每页条目数
		//2.获取页码
		int pageSize = 2;
		int currentNo = 1;
		String getPageSize = request.getParameter("pageSize");
		String getPageNo = request.getParameter("pageNo");
		if(null!=getPageSize && !"".equals(getPageSize)) {
			pageSize = Integer.parseInt(getPageSize);
			request.getSession().setAttribute("sessionSize", pageSize);
		}
		String sessionSize = request.getSession().getAttribute("sessionSize").toString();
		if(null!=sessionSize && !"".equals(sessionSize)) {
			pageSize = Integer.parseInt(sessionSize);
		}
		if(null!=getPageNo && !"".equals(getPageNo)) {
			currentNo = Integer.parseInt(getPageNo);
		}
		PageInfo<User> pageInfo = userService.findUserByLimit(currentNo, pageSize);
		request.setAttribute("pageInfo", pageInfo);
		request.getRequestDispatcher("limituser.jsp").forward(request, response);
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}

}

我们从jsp界面中获取pageNo和pageSize两个参数值,并把查询到的信息保存在pageInfo对象中,然后放在request域中暂时存储,并跳转到limituser.jsp界面。

JSP界面

该界面主要用于展示用户具体信息及分页,通过引入BootStrap,使得样式相对美观一些。

limituser.jsp

该界面主要用于展示分页后的用户信息,代码如下:

<%@ page import="cn.chen.web2.entity.*"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>分页查询用户信息</title>
<link rel="stylesheet" href="css/bootstrap.min.css" />
<link rel="stylesheet" href="css/bootstrap-theme.min.css" />
<script src="js/jquery-1.11.0.min.js" type="text/javascript"></script>
<script src="js/bootstrap.min.js" type="text/javascript"></script>
<style type="text/css">
.box ul {
	display: flex;
	flex-direction: row;
	justify-content: center;
}
</style>
</head>
<body>
	<form action="FindUsersLimitServlet" method="post">
		<input type="submit" value="查询" /> <select name="pageSize"
			id="pageSize">
			<option value="1">1/</option>
			<option value="2" selected="selected">2/</option>
			<option value="3">3/</option>
		</select>
	</form>
	<!-- 页面 -->
	<c:if test="${null!=pageInfo.datas}">
		<table class="table table-condensed" border="1">
			<thead>
				<tr>
					<td>选择</td>
					<td>用户编号</td>
					<td>用户名</td>
					<td>密码</td>
					<td>手机号</td>
					<td>用户头像</td>
					<td>操作</td>
				</tr>
			</thead>
			<!-- 使用c:forEach结合EL表达式进行数据处理,items必须接收一个集合对象 -->
			<!-- uId是属性名 -->
			<c:forEach items="${pageInfo.datas}" var="u" varStatus="p">
				<form action="UpdateUserServlet" method="post">
					<tr>
						<td><input type="checkbox"></td>
						<!--<td><img src="image/${u.uName}" width="50px" height="30px"/>${u.uId}</td>-->
						<td><input type="text" id="uId" name="uId"
							readonly="readonly" value="${u.uId}"></td>
						<td><input type="text" id="uName" name="uName"
							value="${p.current.uName}"></td>
						<td><input type="text" id="uPwd" name="uPwd"
							value="${u.uPwd}"></td>
						<td>${u.uPhone}</td>
						<td><img src="upload/image/${u.uImage}" width="50px"
							height="30px"></td>
						<td><a href="uName=${u.uName}">修改</a> <!-- 一种是将修改内容在页面显示 另一种是当做一个form进行处理 -->
							<a
							href="http://localhost:8080/javaweb_2/DealUserServlet?uId=${u.uId}"
							onclick="return confirm('是否确认删除?')">删除</a> <input type="submit"
							value="修改" /></td>
					</tr>
				</form>
			</c:forEach>
		</table>
		<!-- <br/> -->
		<div class="box">
			<ul class="pagination">
				<li><a href="FindUsersLimitServlet?pageNo=1">首页</a></li>
				<li><c:if test="${pageInfo.currentPage!=1}">
						<a href="FindUsersLimitServlet?pageNo=${pageInfo.currentPage-1}">&laquo;</a>
					</c:if></li>
				<!-- 页码处理 -->
				<%
					PageInfo<User> pageInfo = (PageInfo<User>) request.getAttribute("pageInfo");
						for (int i = 1; i <= pageInfo.getMaxPage(); i++) {
							if (i == pageInfo.getCurrentPage()) {
								out.print("<li class='active'><a href='FindUsersLimitServlet?pageNo=" + i + "'>" + i
										+ "</a></li>");
							} else {
								out.print("<li><a href='FindUsersLimitServlet?pageNo=" + i + "'>" + i + "</a></li>");
							}
						}
				%>
				<li><c:if test="${pageInfo.currentPage!=pageInfo.maxPage}">
						<a href="FindUsersLimitServlet?pageNo=${pageInfo.currentPage+1}">&raquo;</a>
					</c:if></li>
				<li><a href="FindUsersLimitServlet?pageNo=${pageInfo.maxPage}">末页</a></li>
			</ul>
		</div>
	</c:if>
</body>
</html>

具体的效果展示图如下:
分页效果图
上述代码中,我们从Servlet中获取到pageInfo对象并进行调用,通过EL表达式获取datas并进行遍历,从select选择框中读取参数pageSize,从a标签中读取参数pageNo,分页样式我们选择了居中对齐,这样相对美观一些。
好了,本期的分页就介绍到这里了,如果有疑惑可以在下方进行评论哦!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值