本期博客主要实现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}">«</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}">»</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,分页样式我们选择了居中对齐,这样相对美观一些。
好了,本期的分页就介绍到这里了,如果有疑惑可以在下方进行评论哦!