微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

JSP基于Bootstrap分页显示实例解析

首先介绍一款简单利落的分页利器:bootstrap-paginator,可以参考:这篇文章进行学习。 效果截图:

GitHub官方下载地址: 下面就来详细介绍一下基于这款分页利器的JSP分页显示实现过程(注:相较于原网页我隐去了很多不必要的内容,本例只专注于分页显示的实现)

一、为什么需要分页显示

这篇博文说得很透彻:

二、JSP页面部分

,这里直接在JSP页面中用JDBC连接SqlServer2005数据库查询数据(实际实现里不建议把复杂的业务逻辑封装在JSP页面中,JSP页面应当只是负责显示;对客户端的响应、业务逻辑调用、结果转发都应该由Servlet来完成) 代码如下:

<%@ page import="java.util.*"%> <%@ page import="java.sql.*"%>

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>

<%!
private static final int pageSize = 20; //设定每页显示的记录条数(当前为每页显示20条记录)
%>

<%
request.setCharacterEncoding("UTF-8"); //设定客户端提交给servlet的内容按UTF-8编码
response.setCharacterEncoding("UTF-8"); //设定servlet传回给客户端的内容按UTF-8编码
response.setContentType("text/html;charset=UTF-8"); //告知浏览器用UTF-8格式解析内容

String pageNoStr = request.getParameter("pageNoStr"); //接收客户端传递的要显示页数
int pageNo = 1; //要显示的页数
int totalPages = 1; //总页数

//检查、设置pageNo
if (pageNoStr != null && !pageNoStr.equals("")) {
try {
pageNo = Integer.parseInt(pageNoStr);

if (pageNo < 1) {
//pageNo小于1时默认显示第一页
pageNo = 1;
}
}
catch (NumberFormatException e) {
//获取到的pageNo(当前页面数)不合法时,默认显示第一页
pageNo = 1;
}
}
else {
//其他未获取到pageNo的情况都默认显示第一页
pageNo = 1;
}

/ ========================================连接数据库(获取总页数与当前页内要显示的观测记录)====================================== /

/ 获取数据库中将记录按指定条数(pageSize)分页后的总页数 /
Connection totalConn = null;
Statement totalStmt = null;
ResultSet totalRs = null;

try {
totalConn = DBUtil.getConnection();

//生成sql语句
String sqlGetTotalPages = "select count(*) from alldata";

//获取总记录条数
totalStmt = totalConn.createStatement();
totalRs = totalStmt.executeQuery(sqlGetTotalPages);
totalRs.next();
int countResult = totalRs.getInt(1);

//取得总页数
totalPages = countResult % pageSize == 0 ? countResult / pageSize : (int)(countResult / pageSize) + 1;

} catch (SQLException e) {
System.out.println("历史记录查询出错,操作未完成!");
e.printStackTrace();
} finally {
DBUtil.close(totalRs);
DBUtil.close(totalStmt);
DBUtil.close(totalConn);
}

/ 如果页数大于总页数,则默认显示最后一页 /
if (pageNo > totalPages) {
pageNo = totalPages;
}

/ 获取数据库中当前页内要显示的观测记录,使用一个List来盛装记录 /
List records = new ArrayList();

Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;

int startIndex = (pageNo - 1) pageSize + 1;
int endIndex = pageNo
pageSize;

try {
conn = DBUtil.getConnection();

String sql = "select from (select row_number() over(order by data_taizhan_num,data_date asc) as 'num', from alldata) as temp where num between " + startIndex + " and " + endIndex;
pstmt = conn.prepareStatement(sql);
rs = pstmt.executeQuery();
while (rs.next()) {
//取出每条记录的数据,并将其封装成Record对象
Record r = new Record();
r.setTaizhan_num(rs.getString(2));
r.setDate(rs.getTimestamp(3));
r.setTem(rs.getString(4));
r.setHum(rs.getString(5));
r.setPa(rs.getString(6));
r.setRain(rs.getString(7));
r.setWin_dir(rs.getString(8));
r.setWin_sp(rs.getString(9));

records.add(r); //将封装好的Record对象放入列表容器中
}

} catch (SQLException e) {
System.out.println("查询出错,操作未完成!");
e.printStackTrace();
} finally {
DBUtil.close(rs);
DBUtil.close(pstmt);
DBUtil.close(conn);
}
System.out.println(totalPages);
System.out.println(pageNo);
/ ========================================数据库连接结束====================================== /

%>

<link rel="stylesheet" href="css/bootstrap.css">
<link rel="stylesheet" href="css/recordSearchResult.css">

<script type="text/javascript" src="js/jquery-1.12.3.min.js">
<script type="text/javascript" src="js/bootstrap.min.js">
<script type="text/javascript" src="js/bootstrap-paginator.min.js">

- 搜索记录 -

<div class="container">
<div class="wrapper">

<form class="form-area">

<% if (records == null || records.size() == 0) { out.println("

没有符合要求的记录呢,不如换个搜索条件试试吧~

观测台站

if (r.getTem() != null) {
out.println("<td>

温度(℃)

</td>");
}
if (r.getHum() != null) {
out.println("<td>

湿度(%)

</td>");
}
if (r.getPa() != null) {
out.println("<td>

压强(hPa)

</td>");
}
if (r.getRain() != null) {
out.println("<td>

雨量(mm)

</td>");
}
if (r.getWin_dir() != null) {
out.println("<td>

风向(°)

</td>");
}
if (r.getWin_sp() != null) {
out.println("<td>

风速(m/s)

</td>");
}

%>
<td>

观测时间

</td>
</tr>
<%
}
%>

<%
if (records != null && records.size() != 0) {
for (Record r : records) {
%>

<tr>
<td><%= r.getTaizhan_num() %></td>

<%
if (r.getTem() != null) {
out.println("<td>" + r.getTem() + "</td>");
}
if (r.getHum() != null) {
out.println("<td>"+ r.getHum() +"</td>");
}
if (r.getPa() != null) {
out.println("<td>" + r.getPa() + "</td>");
}
if (r.getRain() != null) {
out.println("<td>" + r.getRain() + "</td>");
}
if (r.getWin_dir() != null) {
out.println("<td>" + r.getWin_dir() + "</td>");
}
if (r.getWin_sp() != null) {
out.println("<td>" + r.getWin_sp() + "</td>");
}
%>
<td><%= r.getDate() %></td>
</tr>

<%

}
%>

</table>

<div align="center">
<ul class="pagination" id="paginator">

<%
}
%>

三、关于本例中用到的Record、DBUtil类:

Record类是一个用于封装数据的,对外仅提供get/set方法的普通Java类,其属性与数据库表中包含的字段一一对应,代码如下:

import java.sql.*;

/**

  • 封装气象数据信息
  • @author zhong
  • */
    public class Record {

private String taizhan_num; //台站名
private String tem; //温度
private String hum; //湿度
private String pa; //压强
private String rain; //雨量
private String win_dir; //风向
private String win_sp; //风速
private Timestamp date; //观测日期(原始格式)

/**

  • 获取产生该观测记录的台站名称;
  • @return 台站名称
    */
    public String getTaizhan_num() {
    return taizhan_num;
    }

/**

  • 设置产生该观测记录的台站名称;
  • @param taizhan_num 待设置台站名称
    */
    public void setTaizhan_num(String taizhan_num) {
    this.taizhan_num = taizhan_num;
    }

/**

  • 获取温度;
  • @return 温度值
    */
    public String getTem() {
    return tem;
    }

/**

  • 设置温度;
  • @param tem 待设置温度值
    */
    public void setTem(String tem) {
    this.tem = tem;
    }

/**

  • 获取湿度;
  • @return 湿度值
    */
    public String getHum() {
    return hum;
    }

/**

  • 设置湿度;
  • @param hum 待设置湿度值
    */
    public void setHum(String hum) {
    this.hum = hum;
    }

/**

  • 获取压强;
  • @return 压强值
    */
    public String getPa() {
    return pa;
    }

/**

  • 设置压强;
  • @param pa 待设置压强值
    */
    public void setPa(String pa) {
    this.pa = pa;
    }

/**

  • 获取雨量;
  • @return 雨量值
    */
    public String getRain() {
    return rain;
    }

/**

  • 设置雨量;
  • @param rain 待设置雨量值
    */
    public void setRain(String rain) {
    this.rain = rain;
    }

/**

  • 获取风向;
  • @return 风向值
    */
    public String getWin_dir() {
    return win_dir;
    }

/**

  • 设置风向;
  • @param win_dir 待设置风向值
    */
    public void setWin_dir(String win_dir) {
    this.win_dir = win_dir;
    }

/**

  • 获取风速;
  • @return 风速值
    */
    public String getWin_sp() {
    return win_sp;
    }

/**

  • 设置风向;
  • @param win_sp 待设置风向值
    */
    public void setWin_sp(String win_sp) {
    this.win_sp = win_sp;
    }

/**

  • 获取观测日期;
  • @return 观测日期
    */
    public Timestamp getDate() {
    return date;
    }

/**

  • 设置观测日期;
  • @param date 观测日期值
    */
    public void setDate(Timestamp date) {
    this.date = date;
    }

}

对应的alldata表部分数据截图:

DBUtil类是一个数据库工具类,统一对外提供与数据库相关的Connection、Statement等,代码如下:

import java.sql.*;

import org.apache.tomcat.jdbc.pool.DataSource;
import org.apache.tomcat.jdbc.pool.PoolProperties;

/**

  • 数据库工具类(采用了tomcat jdbc pool)
  • @author zhong
  • */
    public class DBUtil {

private static DataSource ds;

static {
//配置tomcat jdbc pool (连接池)
PoolProperties p = new PoolProperties();
p.setUrl("jdbc:sqlserver://localhost:1433; DatabaseName=weather"); //设置连接的url
p.setDriverClassName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); //载入数据库驱动
p.setUsername("sa"); //用于远程连接的用户名
p.setPassword("2003NianDeDiYiChangXue"); //密码
p.setJmxEnabled(true);
p.setTestWhileIdle(false);
p.setTestOnBorrow(true);
p.setValidationQuery("SELECT 1");
p.setTestOnReturn(false);
p.setValidationInterval(30000);
p.setTimeBetweenEvictionRunsMillis(30000);
p.setMaxActive(100);
p.setInitialSize(10);
p.setMaxWait(10000);
p.setRemoveAbandonedTimeout(60);
p.setMinEvictableIdleTimeMillis(30000);
p.setMinIdle(10);
p.setLogAbandoned(true);
p.setRemoveAbandoned(true);
p.setJdbcInterceptors(
"org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;"+
"org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer");
ds = new DataSource();
ds.setPoolProperties(p);
}

private DBUtil() {}

/**

  • 获取一个数据库连接(Connection);
  • @return Database Connection
    */
    public static Connection getConnection() {
    Connection conn = null;

try {
conn = ds.getConnection();
} catch (SQLException e) {
e.printStackTrace();
}

return conn;
}

/**

  • 关闭传入的Connection;
  • @param conn 待关闭的Connection
    */
    public static void close(Connection conn) {
    try {
    if (conn != null) {
    conn.close();
    conn = null;
    }
    } catch (SQLException e) {
    e.printStackTrace();
    }
    }

/**

  • 关闭传入的Statement;
  • @param stmt 待关闭的Statement
    */
    public static void close(Statement stmt) {
    try {
    if (stmt != null) {
    stmt.close();
    stmt = null;
    }
    } catch (SQLException e) {
    e.printStackTrace();
    }
    }

/**

  • 关闭传入的ResultSet;
  • @param rs 待关闭的ResultSet
    */
    public static void close(ResultSet rs) {
    try {
    if (rs != null) {
    rs.close();
    rs = null;
    }
    } catch (SQLException e) {
    e.printStackTrace();
    }
    }

}

四、补充说明:

①:SQLServer实现分页时需借助ROW_NUMBER()函数,以生成一个单独记录了行号的列,方便后面分页时取出对应行号区间段的记录。例:

看到了吧,最前面多了一列存储了行号的字段名为num的列; (如果表内主键id是自动递增的数字的话,也可以直接用id来分段取出记录,但前提是id必须连续且自动递增) 关于更多ROW_NUMBER()函数实现分页的信息请参考:

②:MysqL分页实现起来简单很多,直接使用limit关键字即可。例: select * from table1 order by id asc limit 3,2 意即将表table1中的数据按id值排序(升序)后,从第三行开始,取后面的两行记录(即第四、五行记录) ③:关于bootstrap-paginator的具体使用方法可以参考官方的文档(位于解压后的document文件夹内),官方文档写得很棒,简单易懂。 在使用时要注意对于bootstrap V3版本来说,要使用