目录
1.使用 ajax 技术(无刷新)实现分页的好处
改善 web 应用的用户体验,避免用户在页面上不停的提交和刷新,而大多数的刷新是没有必要的。
2.准备工作
-
2.1.需要引入的库和包
jQuery 库,放在 js 文件夹内
jar 包,放在 lib 文件夹内
1.使用 jstl 和 EL 表达式的包
2.连接数据库的包
3.使用 json 语法的包
-
2.2.包的建立和数据库表建立
1.包
dao 包和 biz 包是用三层架构的原理实现
2.表
从 Oracle 数据库中建立表,我使用的是 tb_goods 商品表
create table tb_goods(
gid int primary key, --商品编号
gname varchar(30) not null, --商品名称
gprice float default(0) not null, --商品单价
ginfo varchar(1000), --商品描述信息
gpath varchar(100), --商品图片路径
gstatus number(2) default(0) not null --商品状态(默认是0)
)
准备数据
insert into tb_goods(gname,gprice,ginfo,gpath)
values('mp31',100,'mp31','images/1.jpg');
insert into tb_goods(gname,gprice,ginfo,gpath)
values('mp32',1200,'mp32','images/2.jpg');
insert into tb_goods(gname,gprice,ginfo,gpath)
values('mp33',100,'mp33','images/3.jpg');
insert into tb_goods(gname,gprice,ginfo,gpath)
values('mp34',1600,'mp34','images/4.jpg');
insert into tb_goods(gname,gprice,ginfo,gpath)
values('mp35',1500,'mp35','images/5.jpg');
insert into tb_goods(gname,gprice,ginfo,gpath)
values('mp36',1400,'mp36','images/6.jpg');
insert into tb_goods(gname,gprice,ginfo,gpath)
values('mp37',1700,'mp37','images/7.jpg');
insert into tb_goods(gname,gprice,ginfo,gpath)
values('mp38',1300,'mp38','images/8.jpg');
insert into tb_goods(gname,gprice,ginfo,gpath)
values('mp39',1500,'mp39','images/9.jpg');
insert into tb_goods(gname,gprice,ginfo,gpath)
values('mp310',1600,'mp310','images/10.jpg');
insert into tb_goods(gname,gprice,ginfo,gpath)
values('mp311',1600,'mp311','images/11.jpg');
首先,在 util 包中建 DBhelper 类用来连接数据库
public class DBhelper {
//1.定义连接字符串
private static final String URL = "jdbc:oracle:thin:@localhost:1521:orcl";
private static final String CLASS_NAME = "oracle.jdbc.driver.OracleDriver";
//2.加载/注册驱动
static {
try {
Class.forName(CLASS_NAME);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 3.得到连接对象的方法
* @return
* @throws SQLException
*/
public static Connection getCon() throws SQLException{
return DriverManager.getConnection(URL, "scott", "123");
}
/**
* 4.关闭/释放资源
* @param con 连接对象
* @param ps 执行对象
* @param rs 结果集对象
* @throws SQLException
*/
public static void closeObj(Connection con,PreparedStatement ps,ResultSet rs) throws SQLException{
if(con != null && con.isClosed())
con.close();
if(ps != null)
ps.close();
if(rs != null)
rs.close();
}
public static void main(String[] args) throws SQLException {
System.out.println(DBhelper.getCon());
}
}
运行出这行字样证明连接成功(@后面的内容随机):
在 entity 包中建一个 Goods 实体类,实现对象序列化的接口 Serializable,分别实现他的 Set 和 Get 方法、无参构造方法和 toString 方法。
public class Goods implements Serializable{
private static final long serialVersionUID = 1L;
private int gid;//商品编号
private String gname;//商品名称
private Double gprice;//商品单价
private String ginfo;//商品描述信息
private String gpath;//商品图片路径
private int gstatus;//商品状态
public int getGid() {
return gid;
}
public void setGid(int gid) {
this.gid = gid;
}
public String getGname() {
return gname;
}
public void setGname(String gname) {
this.gname = gname;
}
public Double getGprice() {
return gprice;
}
public void setGprice(Double gprice) {
this.gprice = gprice;
}
public String getGinfo() {
return ginfo;
}
public void setGinfo(String ginfo) {
this.ginfo = ginfo;
}
public String getGpath() {
return gpath;
}
public void setGpath(String gpath) {
this.gpath = gpath;
}
public int getGstatus() {
return gstatus;
}
public void setGstatus(int gstatus) {
this.gstatus = gstatus;
}
public static long getSerialversionuid() {
return serialVersionUID;
}
public Goods() {
// TODO Auto-generated constructor stub
}
public Goods(int gid, String gname, Double gprice, String ginfo, String gpath, int gstatus) {
super();
this.gid = gid;
this.gname = gname;
this.gprice = gprice;
this.ginfo = ginfo;
this.gpath = gpath;
this.gstatus = gstatus;
}
public Goods(int gid, String gname, Double gprice, String ginfo, String gpath) {
super();
this.gid = gid;
this.gname = gname;
this.gprice = gprice;
this.ginfo = ginfo;
this.gpath = gpath;
}
@Override
public String toString() {
return "Goods [gid=" + gid + ", gname=" + gname + ", gprice=" + gprice + ", ginfo=" + ginfo + ", gpath=" + gpath
+ ", gstatus=" + gstatus + "]";
}
}
-
2.3.方法
需要的方法(带有模糊查询的分页和获取最大页码的方法),因为是使用三层架构,所以方法不能只写在一个类里面。
在 dao 包在 IGoodsDao 接口中
public interface IGoodsDao {
/**
* 查询所有(分页/模糊)
* @param pageIndex
* @param str
* @return
* @throws SQLException
*/
List<Goods> query(Integer pageIndex, String str) throws SQLException;
/**
* 获取最大页码(模糊查询)
* @param str
* @return
* @throws SQLException
*/
int getMaxPage(String str) throws SQLException;
}
在实现包 impl 中的 GoodsDao 类中(实现 IGoodsDao 接口)
@SuppressWarnings("all")
public class GoodsDao implements IGoodsDao{
private Connection con;// 连接对象
private PreparedStatement ps;// 执行对象
private ResultSet rs;// 结果集对象
private Goods goods;
private List<Goods> listGoods;
private Integer n;// 受影响的行数
private String sql;// 保存sql语句
private Integer maxPage;// 最大页码
@Override
public List<Goods> query(Integer pageIndex,String str) throws SQLException{
Integer pageSize = 3;
int start = (pageIndex - 1) * pageSize + 1;
int end = pageIndex * pageSize;
listGoods = new ArrayList<Goods>();
con = DBhelper.getCon();
sql = "select * from (select rownum myid,a.* from tb_goods a where gname like ?) b"
+ " where myid between ? and ?";
ps = con.prepareStatement(sql);
ps.setString(1, "%"+str+"%");
ps.setInt(2, start);
ps.setInt(3, end);
rs = ps.executeQuery();
while(rs.next()) {
goods = new Goods(rs.getInt("gid"), rs.getString("gname"), rs.getDouble("gprice"),
rs.getString("ginfo"), rs.getString("gpath"));
listGoods.add(goods);
}
DBhelper.closeObj(con, ps, rs);
return listGoods;
}
@Override
public int getMaxPage(String str) throws SQLException{
con = DBhelper.getCon();
sql = "select count(0) from tb_goods where gname like ?";
ps = con.prepareStatement(sql);
ps.setString(1, "%"+str+"%");
rs = ps.executeQuery();
if(rs.next()) {
maxPage = rs.getInt(1) / 3;
if(rs.getInt(1) % 3 != 0) {
maxPage ++;
}
}
DBhelper.closeObj(con, ps, rs);
return maxPage;
}
}
@SuppressWarnings("all")的作用是抑制一些无关紧要的警告。
同理,
在 biz 包在 IGoodsBiz 接口中
public interface IGoodsBiz {
/**
* 查询所有(分页/模糊)
* @param pageIndex
* @param str
* @return
* @throws SQLException
*/
List<Goods> query(Integer pageIndex, String str) throws SQLException;
/**
* 获取最大页码(模糊查询)
* @param str
* @return
* @throws SQLException
*/
int getMaxPage(String str) throws SQLException;
}
在实现包 impl 中的 GoodsBiz 类中(实现 IGoodsBiz 接口)
public class GoodsBiz implements IGoodsBiz{
// 调用业务逻辑层
IGoodsDao igd = new GoodsDao();
@Override
public List<Goods> query(Integer pageIndex, String str) throws SQLException {
return igd.query(pageIndex, str);
}
@Override
public int getMaxPage(String str) throws SQLException {
return igd.getMaxPage(str);
}
}
3.案例演示
初始效果展示(没有功能)
主界面代码(开头):
<%@ 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 PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>无刷新分页</title>
<script type="text/javascript" src="${pageContext.request.contextPath }/js/jquery-3.3.1.min.js""></script>
<script type="text/javascript" src="${pageContext.request.contextPath }/js/bootstrap.js"></script>
<link href="${pageContext.request.contextPath }/css/bootstrap.css" rel="stylesheet" type="text/css" />
这里除了引用了 jQuery 库,还引用了 bootstrap 的 css 和 js 库。如果想要了解 bootstrap,指引:
https://blog.csdn.net/weixin_62332711/article/details/123910490
CSS样式代码:
<style type="text/css">
td{
vertical-align: middle!important;
text-align: center;
font-weight: bolder;
}
hr{
width:1000px;
height:2px;
background-color: red
}
</style>
JS代码:
<script type="text/javascript">
var sname;
var pid = 1;// 默认展示第一页
var maxPage;// 总页码
var listGoods;
// 定义向后台发送ajax请求的方法
function query(){
sname = $("#sname").val();// 获取模糊查询关键字
$.post("${pageContext.request.contextPath}/loadDataServlet.do",{
sname:sname,pid:pid
},function(jsonStr){
var obj = $.parseJSON(jsonStr);
listGoods = obj.listGoods;
maxPage =js obj.maxPage;
var sb = "<table class=\"table table-hover\">";
sb += "<tr style=\"background:yellow;color: red;font-weight: bolder;font-size: 30px;\">";
sb += "<td>商品序号</td>";
sb += "<td>商品名称</td>";
sb += "<td>商品价格</td>";
sb += "<td>商品描述</td>";
sb += "<td>商品图片</td>";
sb += "<td>商品操作</td>";
sb += "</tr>";
// 绑定数据
$.each(listGoods,function(i,g){
sb += "<tr>";
sb += "<td>"+g.gid+"</td>";
sb += "<td>"+g.gname+"</td>";
sb += "<td>"+g.gprice+"</td>";
sb += "<td>"+g.ginfo+"</td>";
sb += "<td><img src='"+g.gpath+"'/></td>";
sb += "<td><a href=''>删除</a> <a href=''>修改</a></td>";
sb += "</tr>";
})
sb += "</table>"
// 最后将sb赋给div
$("#content").html(sb);
// 给当前页码和总页码赋值
$("#pid").html(pid);
$("#maxPage").html(maxPage);
});
}
// 翻页方法
function changePage(type){// type表示点击的是上面的翻页标签
if(type == 'first'){// 首页
pid = 1;
}else if(type == 'minus'){// 上一页
//pid = pid>1?pid-1:1;
if(pid > 1){
pid --;
}else{
alert("已经是第一页了");
}
}else if(type == 'add'){// 下一页
//pid = pid<maxPage?pid+1:maxPage;
if(pid < maxPage){
pid ++;
}else{
alert("已经是最后一页了");
}
}else{// 末页
pid = maxPage;
}
// 最后发送ajax请求
query();
}
$(function(){
// 页面加载完自动执行
query();
})
</script>
HTML代码:
</head>
<body style="background-image: url('${pageContext.request.contextPath }/images/绿色2.jpg');background-repeat: norepeat">
<br />
<center>
<div class="input-group">
<input type='text' id = "sname" name = "sname" class="form-control" style="width: 250px" placeholder="请输入查询关键字"/>
<button onclick="query()" class="btn btn-success">查询</button>
</div>
</center>
<br/>
<!-- 绑定数据 -->
<div id="content" class="container">
</div>
<hr />
<!-- 分页 -->
<center>
<div style="font-size: 18px">
<ul class="pager">
<li><a href="javascript:changePage('first')">首页</a></li>
<li><a href="javascript:changePage('minus')">上一页</a></li>
<li>
<a>当前页:<span id="pid"></span>/<span id="maxPage"></span></a>
</li>
<li><a href="javascript:changePage('add')">下一页</a></li>
<li><a href="javascript:changePage('last')">末页</a></li>
</ul>
</div>
</center>
</body>
</html>
(结尾)
servlet 包下的 LoadDataServlet 类
@SuppressWarnings("all")
@WebServlet("/loadDataServlet.do")
public class LoadDataServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
try {
// 设置编码
req.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset = utf-8");
// 获取out内置对象
PrintWriter out = resp.getWriter();// 调用业务逻辑层
IGoodsBiz igb = new GoodsBiz();
// 获取前端提交的模糊查询关键字和页码参数
String str = req.getParameter("sname");
if(null == str) {
str = "";
}
Integer pageIndex = Integer.parseInt(req.getParameter("pid"));
// 调用带有模糊查询分页的方法
List<Goods> listGoods = igb.query(pageIndex, str);
// 调用获取最大页码的方法
int maxPage = igb.getMaxPage(str);
// 实例化Test对象
Test test = new Test(listGoods, maxPage);
Test类
在entity包中建一个类,为Test,用来保存分页的listGoods集合和求最大页码的方法,再到 LoadDataServlet中去实例化
public class Test implements Serializable{
private static final long serialVersionUID = 1L;
private List<Goods> listGoods;
private Integer maxPage;
public List<Goods> getListGoods() {
return listGoods;
}
public void setListGoods(List<Goods> listGoods) {
this.listGoods = listGoods;
}
public Integer getMaxPage() {
return maxPage;
}
public void setMaxPage(Integer maxPage) {
this.maxPage = maxPage;
}
public static long getSerialversionuid() {
return serialVersionUID;
}
public Test() {
// TODO Auto-generated constructor stub
}
public Test(List<Goods> listGoods, Integer maxPage) {
super();
this.listGoods = listGoods;
this.maxPage = maxPage;
}
@Override
public String toString() {
return "Test [listGoods=" + listGoods + ", maxPage=" + maxPage + "]";
}
}
// 把test对象保存在JSON字符串中
String jsonStr = JSON.toJSONString(test);// toJSONString:转换成JSON格式的字符串
// 将响应新信息输出/响应到前端
out.write(jsonStr);// 把JSON字符串响应到前端
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
最终效果演示:
完。
感谢观看!!!