【Java】ページングでWebアプリのパフォーマンスを向上させる
スポンサーリンク
こんにちは。talosです。
Webアプリのパフォーマンスを大きく左右する要因としてDB処理が挙げられます。
扱うデータが多くなればなるほど時間がかかるため、一覧表示などは工夫しないとユーザーへの負担が大きくなります。
そこで今回は、ページングを使って一覧表示をすることで、Webアプリのパフォーマンスを向上させる方法を解説します。
ページングとは
そもそもページングとはなにかというと、検索結果などが多いときに一度にすべて表示せず、1ページには検索結果の一部のみを表示して次ページボタンや前ページボタンで他のページに移ることができるようにする処理です。
一度にすべての検索結果を取得せず1ページに表示するデータのみを取得するため、ページアクセスの際にかかるDB処理の時間を短くすることができます。
解説
src/holder/Page.javaから見ていきましょう。
/** * 1ページ中に表示される最大件数 */ public static final int OUTPUT_NUM = 10; /** * 全レコードの件数 */ private long recordNum; /** * 現在のページ */ private int currentPage = 1; /** * 全レコードの件数から算出されるページ数(recordNum/outputNum) */ private long maxPage;
まずはフィールドです。
ここはコメントの通りです。
/** * ページングに使う変数を設定する * @param recordNum */ public void config(Long recordNum) { this.recordNum = recordNum; this.maxPage = this.recordNum / OUTPUT_NUM; if (this.recordNum % OUTPUT_NUM != 0 || this.recordNum == 0) { ++this.maxPage; } }
config()はページングに使う変数を設定するメソッドです。
maxPageは(全レコードの件数/1ページに表示する最大件数)で算出します。
ですが、例えば全レコードの件数が35件の場合、整数型だと35/10=3となるため残りの5件を表示できなくなってしまいます。
そのため、
this.recordNum % OUTPUT_NUM != 0
の場合はmaxPageをインクリメントします。
また、全レコードの件数が0の場合、maxPageは0/10=0となります。
ですが、レコードがなくても1ページは表示しなくてはなりません。
そのため、
this.recordNum == 0
の場合もmaxPageをインクリメントします。
/** * 前ページボタンを表示するか * @return */ public boolean prevPageDisplay() { return currentPage > 1; } /** * 次ページボタンを表示するか * @return */ public boolean nextPageDisplay() { return currentPage < maxPage; }
この2つは前ページボタンと次ページボタンを表示するかどうかを制御するメソッドです。
1ページ目にいるときに前ページボタンが押されたら0ページ目へ遷移することになります。
ですが0ページ目はありません。
そのようなことを避けるためのメソッドです。
/** * 最初のページへ */ public void topPage() { currentPage = 1; } /** * 最後のページへ */ public void lastPage() { currentPage = (int) maxPage; } /** * 前のページへ */ public void prevPage() { if (prevPageDisplay()) { currentPage--; } } /** * 次のページへ */ public void nextPage() { if (nextPageDisplay()) { currentPage++; }
これらはページの遷移を行うメソッドです。
最初のページへ遷移するときはcurrentPageに1を代入し、最後のページに遷移するときは遷移し得る最大のページをcurrentPageを代入します。
前のページに遷移するときにはcurrentPageを-1し、次のページに遷移するときにはcurrentPageを+1します。
/** * 何番目のレコードから表示するか * @return */ public Integer offset() { return (currentPage - 1) * OUTPUT_NUM; }
何件目から表示するかを計算をするメソッドです。
画面に一覧を表示する際、1ページ目であれば1件目から表示すれば良いですが、2ページ目では11件目から表示する必要があります。
言うまでもないですが、リストのインデックスは0からなのでcurrentPageから1引いています。
次に、src/master/UserMaster.javaを見てみましょう。
/** * 登録されたユーザーのリスト */ private ArrayList<User> userList; { userList = new ArrayList<User>(); for (int i = 0; i < 35; i++) { userList.add(new User("user" + i, "test")); } }
本来はDBなどからレコードを取得してきますが、今回はサンプルのためここでデータを用意します。
35人のIDとパスワードをリストに登録しておきます。
/** * offsetからnum件のユーザーリストを返す * @param page * @return */ public ArrayList<User> getUserList(Page page) { page.config((long) userList.size()); ArrayList<User> userList = new ArrayList<>(); int offset = page.offset(); int num = Page.OUTPUT_NUM; // recordNum % OUTPUT_NUM != 0の場合リストの外を参照する try { for (int i = offset; i < offset + num; i++) { userList.add(this.userList.get(i)); } } catch (IndexOutOfBoundsException e) { e.printStackTrace(); } return userList; }
getUserList()は表示するレコードだけを返すメソッドです。
最初にpage.config()を呼んでいます。引数は全レコードの件数です。
全レコードの件数も本来であればSELECT COUNT(*)を投げて件数を取得します。
for文のところはoffset件目から10件取得してリストに追加しています。
LIMIT句で取得する件数を制限してSELECT文を投げるところを模しています。
スポンサーリンク
実行
実行するとこのような画面が開きます。
1~10件目が表示され、最初のページへのボタンと前ページへのボタンが非活性化されています。
次ページへのボタンを押すと、
11~20件目が表示されます。
最後のページへのボタンを押すと、
最後の5件が表示され、次ページへのボタンと最後のページへのボタンが非活性化されました。