ページネーションをつくる(サーブレット&JSP)
jspファイルにページネーションをつくってみたので、そのメモ。
大まかな流れとしては、
- SQL文で LIMIT 指定でそのページ分のデータを取得する。
- JSPでページを指定する。
1ページに表示する件数を決める。
今回は、Constクラスに static変数を設置して、そこで指定。「5」と指定した。
util.Constクラス
pacage util;
public class Const {
public static final int PER_PAGE = 5;
}
データの全件数を取得する。
データベースにアクセスするクラスとして、employeeDAO.java を作成した。
そこに、getSize() というメソッドを作成した。
dao.EmployeeDAOクラス
package dao;
...(略)...
public class EmployeeDAO {
...(略)...
public int getSize() {
int count = 0;
try (Connection conn = DriverManager.getConnection(
JDBC_URL, DB_USER, DB_PASS)) {
String sql = "SELECT COUNT(*) FROM employee";
PreparedStatement pStmt = conn.prepareStatement(sql);
ResultSet rs = pStmt.executeQuery();
rs.next();
count = rs.getInt(1); // 1番目のカラムを取得
} catch (SQLException e) {
e.printStackTrace();
return 0;
}
return count;
}
}
SQL文の「COUNT(*)」で件数を数え、rs.getInt(1)で取得している。
この「1」は、1カラム目ということである。
他にやり方としては、
COUNT(*) AS cnt
とし、
rs.getInt("cnt")
で取得する方法もあるみたい。
そして、以下のビジネス・オブジェクトを作成する。
GetSizeLogic.java
public class GetSizeLogic {
public int execute() {
EmployeeDAO dao = new EmployeeDAO();
int dataMax = dao.getSize();
return dataMax;
}
}
さて、これでデータ件数は取得できるが、この値をどこに保持しておくかである。
Constクラスに DATA_MAX として定数として保持しようかとも考えたが、 データ件数は刻々と変化するので、サーブレットで処理するごとに GetSizeLogicクラスのexecute()メソッドを実行し、データ件数を取得したほうが よいと考えた。
ページネーションを記述するJSPファイルにページ情報を渡す
ページネーションに必要な情報は、以下である。
page | 現在のページ |
dataMax | データ全件数 |
last | ラストのページ番号 |
perPage | 1ページに出力する件数 |
first | 最初のページ番号(1で固定) |
これらの数字をサーブレットからリクエストスコープを使ってJSPに 渡せばいい。
今回は、pageInfo というクラスを使った。
PageInfo.java
package model;
public class PageInfo implements Serializable {
private int dataMax;
private int perPage = Const.PER_PAGE;
private int first = 1;
private int last;
public PageInfo () {}
public PageInfo (int dataMax) {
this.dataMax = dataMax;
last = (int) Math.ceil((double) this.dataMax / (double) this.perPage);
}
// ゲッターセッター というか、ゲッターだけでいい。
}
1ページ分のデータをデータベースから取得する。
表示したいページ番号を page とする。
1ページに表示するデータ件数を
int per_page = 10;
スキップするデータ件数を
int skip = (page - 1) * per_page
とすると、必要な SQL文は以下である。
SELECT * FROM employee LIMIT skip, per_page
であるから、EmployeeDAO.java の findAll()メソッドは以下のようになる。
EmployeeDAO.java
...(略)...
public List<Employee> findAll(int skip, int perPage) {
List<Employee> empList = new ArrayList<>();
try (Connection conn =
DriverManager.getConnection(JDBC_URL, DB_USER, DB_PASS)) {
String sql = "SELECT id, name, age FROM employee LIMIT ?, ?";
PreparedStatement pStmt = conn.prepareStatement(sql);
pStmt.setInt(1, skip);
pStmt.setInt(2, perPage);
ResultSet rs = pStmt.executeQuery();
while (rs.next()) {
String id = rs.getString("id");
String name = rs.getString("name");
int age = rs.getInt("age");
Employee employee = new Employee(id, name, age);
empList.add(employee);
}
} catch (SQLException e) {
e.printStackTrace();
return null;
}
return empList;
}
したがって、GetEmployeeListLogic は以下となる。
GetEmployeeListLogic.java
public class GetEmployeeListLogic {
public List<Employee> execute(int skip, int perPage) {
EmployeeDAO dao = new EmployeeDAO();
List<Employee> empList = dao.findAll(skip, perPage);
return empList;
}
}
サーブレットでJSPにわたす各情報を作成する。
サーブレットは、”/<contextPath>/list” というURLで動作するようにするが、 “/<contextPath>/list?page=2” などというURLにも対応できるようにしておく。
つまり、”?page=2″ などというクエリ文字列が無い場合、”?page=1″ が指定された ものとする。
@WebServlet("/list")
public class EmployeeListServlet extends HttpServlet {
...(略)...
protected void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
// データ全件数を取得。
GetEmployeeSizeLogic sizeLogic = new GetEmployeeSizeLogic();
int dataMax = sizeLogic.execute();
// 全件数がわかれば、JSPにわたすページ情報を作成できる。
PageInfo pageInfo = new PageInfo(dataMax);
request.setAttribute("pageInfo", pageInfo);
// この時点では page は 0 あるいは 総ページ数より多いかもしれない。
int page = myParseInt(request.getParameter("page"));
if (page < 1) { page = 1; }
if (page > pageInfo.getLast()) { page = pageInfo.getLast(); }
// スキップするデータ数
int skip = (page - 1) * Const.PER_PAGE;
// 1ページ分のデータを取得する。
GetEmployeeListLogic listLogic = new GetEmployeeListLogic();
List<Employee> empList = listLogic.execute(skip, Const.PER_PAGE);
request.setAttribute("empList", empList);
request.setAttribute("page", page);
String url = "/WEB-INF/jsp/empList.jsp";
RequestDispatcher dispatcher = request.getRequestDispatcher(url);
dispatcher.forward(request, response);
}
private int myParseInt(String _page) {
int page = 0;
try {
page = Integer.parseInt(_page);
} catch (NumberFormatException e) {
// 不正な文字なら 1 とする
page = 1;
}
return page;
}
}
JSPのページネーション部分
JSPは長くなるので、ページネーション部分だけ載せておく。
empList.jsp
...(略)...
<div id="pagenation">
<ul>
<li><a href="<%=request.getContextPath() %>/list?page=${
page - 1 < 1 ? 1 : page - 1}"><</a></li>
<c:forEach var="c" begin="${pageInfo.first}" end="${pageInfo.last}" step="1">
<c:choose>
<c:when test="${c == page}">
<li style="font-weight: bold;">
<a href="<%=request.getContextPath() %>/list?page=${c}">${c}</a>
</li>
</c:when>
<c:otherwise>
<li><a href="<%=request.getContextPath() %>/list?page=${c}">${c}</a></li>
</c:otherwise>
</c:choose>
</c:forEach>
<li><a href="<%=request.getContextPath() %>/list?page=${
page + 1 > pageInfo.last ? pageInfo.last : page + 1}">></a></li>
</ul>
</div>
動作環境
Java11 / Tomcat9 / Servlet 4.0
カテゴリー: Java, memo
タグ: jsp, pagenation, servlet
カウント: 315