Top > MyPage
 

JSP Pager Tag Library

JSP Pager Tag Library のタグ

まずは、このタグの使い方を簡単な例で調べてみる。

参考ページ: Pager Tag Library v2.0

Pager Tag Libraryをつかうための準備

  • Pager Tag Libraryをつかいたいアプリケーションの[WEB-INF/lib]ディレクトリにpager-taglib.jarをコピーする。
  • pager-taglib.tldをアプリケーションの任意のディレクトリにコピーする。例えば[WEB-INF/tld]
  • web.xmlに以下のような定義を書き込む。taglib-locationはtldをコピーしたディレクトリに応じてかえる。
        <taglib>
            <taglib-uri>http://jsptags.com/tags/navigation/pager</taglib-uri>
            <taglib-location>/WEB-INF/tld/pager-taglib.tld</taglib-location>
        </taglib>
        
  • このタグを使いたいJSPで次に示すように宣言する。
        <%@ taglib uri="http://jsptags.com/tags/navigation/pager" prefix="pg" %>
        

これで準備は完了したので、例として次に示す内容のindex.jspというファイルを用意して、表示させてみるとする。


<%@ page contentType="text/html; charset=shift_jis" %>
<%@ taglib uri="http://jsptags.com/tags/navigation/pager" prefix="pg" %>
<html>
<head>
<title>Pager Tag Library</title>
</head>
<body>

<%
java.util.List list = new java.util.ArrayList();
for(int i = 1; i < 100; i++){
    list.add(new Integer(i));
}
int maxPageItems = 5;
int pageCount = list.size() % maxPageItems==0 ?
    list.size() / maxPageItems : list.size() / maxPageItems + 1;
%>

<pg:pager items="<%= list.size() %>"
          index="center"
          maxPageItems="<%=maxPageItems%>"
          export="offset,currentPageNumber=pageNumber"
          scope="request">

    <p>
    <pg:prev export="pageUrl"><a href="<%= pageUrl %>"><</a></pg:prev>
    <pg:pages> <a href="<%= pageUrl %>"><%= pageNumber %></a></pg:pages>
    <pg:next export="pageUrl"> <a href="<%= pageUrl %>">></a></pg:next>
    </p>

    <p>
    <pg:prev export="pageUrl"><a href="<%= pageUrl %>">前の5件</a></pg:prev>
    <%=currentPageNumber%>/<%=pageCount%>
    <pg:next export="pageUrl"><a href="<%= pageUrl %>">次の5件</a></pg:next>
    </p>

    <ul>
    <%
    for(int i = offset.intValue(); i < offset.intValue() + maxPageItems; i++){
        if(list.size() <= i){
            break;
        }
    %>
    <li><%=list.get(i)%></li>
    <% } %>
    </ul>
</pg:pager>

</body>
</html>

これをブラウザ上でみるとこのように表示されています。

 <  6 7 8 9 10 11 12 13 14 15  >

前の5件 11/20 次の5件

    * 51
    * 52
    * 53
    * 54
    * 55

ソースを上から見ていくとします。

bodyタグのすぐ後の<% %>内で

  • 1から99までの整数(Integer)を格納したListを作成
  • 1ページあたりの要素数に使うmaxPageItemsを5に設定
  • ListのsizeとmaxPageItemsから総ページ数を算出してpageCountとして設定

という処理をしている。

その次のpg:pagerタグでページャーの定義をします。

詳しくはこちら

上の例で設定しているものを見てみると、このようになっています。

<pg:pager items="<%= list.size() %>"
          index="center"
          maxPageItems="<%=maxPageItems%>"
          export="offset,currentPageNumber=pageNumber"
          scope="request">

・itemsは表示する要素の総数を設定する項目です。listのsizeを渡しているのが分かります。・indexはページャのindexの表示に関する設定をします。デフォルトはcenterなので、この例のような場合は記述不要です。・maxPageItemsは1ページあたりの要素数を設定します。・exportは出力する変数を設定します。・scopeは変数のスコープを設定します。

次に使われているpg:prevタグですが、名前のとおり「前のページへ」を実現するためのものです。例ではリンク先にpageUrlを書き出していますが、この場合「現在のurl?pager.offset=15」のようになります。ページ数などに変える方法は後述。

次、pg:pagesタグは各ページへのリンクを表示させるものです。表示するリンクの最大数は、pg:pagerで設定できます。

pg:nextタグは、「次のページへ」のタグです。使い方はpg:prevと同じです。

他にpg:first、pg:lastなどがある。

リクエストにoffsetだけではなく、ページ番号を

次のようにすることで、ページ番号をサーバーに送ることが出来る。pg:nextを例にとって説明する


<pg:next export="offset,pageNumber"> 
    <a href="<%= pageUrl %>&page=<%= pageNumber %>">></a>
</pg:next>

この例のようにexportでpageNumberも指定すると、タグ内でこの変数が使えるようになる。であるので、リンクのところを任意の形に書き換えてpageNumberをつけると良い。

pageUrlを使わずにurlを書き換えてもよさそうな気もするが、さにあらず。pageUrlに含まれるoffsetの値を取得しないと動作がおかしくなるのだ。したがって、pageUrlを必ず使い、この後ろに必要なパラメータを付け足すという形にしなければならない。

JSP Pager Tag Libraryとあわせて使うクラスを作ってみよう

このタグを簡単に使うためのクラスを作ってみようと思う。簡便に使うために、表示する検索結果(あるいは全件)のリストを受け取り、タグで必要なパラメータを含んだインスタンスを返すだけのクラスにしてみた。

ページャに渡すパラメータを格納するクラス

このクラスが持つ値は次の5つである。

  • items表示する全要素数
  • maxPageItems 1ページに表示する要素数
  • maxIndexPages 1ページに表示するインデックス数
  • totalPages全ページ数
  • currentPage現在のページ番号

このうち外部から渡してやる必要があるのがmaxPageItems、maxIndexPages、currentPageの三つであり、前二つは設定ファイルから取得するなどする必要があるだろう。currentPageはリクエストから取得するなどする。itemsは、渡されたListのサイズをとればよい。totalPagesはitemsとmaxPageItemsから算出することが出来る。メソッドpageParamの引数にListと各パラメータを入れる。その後、インスタンスをJSPで参照出来るようにする。

まだまだ詰めがあまいが、以下、このクラスのソースである。-----------------------------ForPager.java------------------------------------

package com.utils;
import java.util.List;


public class ForPager {
    
    int items;
    int maxPageItems;
    int maxIndexPages;
    int totalPages;
    int currentPage;


    public void  pageParam(List list, int entryPerPage, int indexPerPage,
                                                           int currentPage) {
        
        this.setItems(list.size());
        this.setMaxIndexPages(indexPerPage);
        this.setMaxPageItems(entryPerPage);
        this.setCurrentPage(currentPage);
        
        int pageCount = list.size() % entryPerPage==0 ?
                list.size() / entryPerPage : list.size() / entryPerPage + 1;
        this.setTotalPages(pageCount);        

    }

    public void setItems(int items_) {
        this.items = items_;
    }
    public int getItems() {
        return this.items;
    }

    public void setMaxPageItems(int maxPageItems_) {
        this.maxPageItems = maxPageItems_;
    }
    public int getMaxPageItems() {
        return this.maxPageItems;
    }
    
    public void setMaxIndexPages(int maxIndexPages_) {
        this.maxIndexPages = maxIndexPages_;
    }
    public int getMaxIndexPages() {
        return this.maxIndexPages;
    }

    public void setTotalPages(int totalPages_) {
        this.totalPages = totalPages_;
    }
    public int getTotalPages() {
        return this.totalPages;
    }

    public void setCurrentPage(int currentPage_) {
        this.currentPage = currentPage_;
    }
    public int getCurrentPage() {
        return this.currentPage;
    }
}

ご覧のとおり、とても単純なクラスである。ほとんど、受け取った値をまとめるだけといっても過言ではない。

メソッドpageParamを実行した後はJSPに渡すだけなので、例えばこのようにする。


ForPager jsppg = new ForPager();

jsppg.pageParam(itemList,maxPageItems,maxIndexPages,pageIndex);

request.setAttribute("jsppg" , jsppg);

このクラスと連携するためのJSP側の記述。

JSP側では以下のようにする。

先ずは、Pager Tagライブラリと、先のクラスを使うので宣言する。


<%@ taglib uri="http://jsptags.com/tags/navigation/pager" 
       prefix="pg" %>
<%@ page import="com.utils.ForPager" %>

次に以下のようにして、ページャータグで使うための変数の用意などをする。

<%
ForPager paging = (ForPager)request.getAttribute("jsppg");
int pageCount = paging.getTotalPages();
int currentPageNumber = paging.getCurrentPage();
String pagingUrl = "/JBBS/action/commentlist";
%>

この例では、・先のクラスのインスタンスをpagingに格納。・pageCount、currentPageNumberにインスタンスから取り出した値を格納。・pagingUrlにページャのpost先のurlを格納。をしている。

次に、実際にページャとして表示される部分を示す


<pg:pager id="pg1"
          items="<%= paging.getItems() %>"
          url="<%= pagingUrl %>"
          index="center"
          maxPageItems="<%=paging.getMaxPageItems() %>"
          maxIndexPages="<%=paging.getMaxIndexPages() %>"
          export="offset,pageNumber"
          scope="request">

    <p>

    <pg:prev export="pageUrl,pageNumber">
        <a href="<%= pageUrl %>
           &pageindex=<%= pageNumber %>&threadCheck=false
               &deleteOnCheck=false"><</a>
    </pg:prev>

    <pg:pages> 
        <a href="<%= pageUrl %>
            &pageindex=<%= pageNumber %>&threadCheck=false
                &deleteOnCheck=false"><%= pageNumber %></a>
    </pg:pages>

    <pg:next export="pageUrl,pageNumber">
        <a href="<%= pageUrl %>
            &pageindex=<%= pageNumber %>&threadCheck=false
                &deleteOnCheck=false">></a>
    </pg:next>
    </p>

    <p>
    <pg:prev export="pageUrl,pageNumber">
        <a href="<%= pageUrl %>
            &pageindex=<%= pageNumber %>&threadCheck=false
                &deleteOnCheck=false">前の5件</a>
    </pg:prev>

    <%=currentPageNumber%>/<%=pageCount%>

    <pg:next export="pageUrl,pageNumber">
        <a href="<%= pageUrl %>
            &pageindex=<%= pageNumber %>&threadCheck=false
                         &deleteOnCheck=false">次の5件</a>
    </pg:next>
    </p>

</pg:pager>

先に説明したpagerの使い方では、pg:pagerタグのパラメータにidとurlは、なかった。この二つを設定するとpageUrlが大きく変わる。

前述のとおり、デフォルトのままだとpageUrlは「現在のurl?pager.offset=15」のようになるわけだが、例のようにidにpg1、urlに先に設定した/JBBS/action/commentlistをそれぞれ入れたとするとpageUrlは「/JBBS/action/commentlist?pg1.offset=15」のようになる。

それぞれ、きっちりと設定しておいた方が安全である。

後は、先に説明したものとあまり変わらないので、注意点を説明する。

pg:prevタグ内で、pageUrl、pageNumberが使われているため、exportで両方宣言されていることに注意。宣言を忘れるとエラーになる。pageUrlの後ろにパラメータがいくつかくっついているのがわかる。実装する場合に応じてパラメータを修正する必要あり。

あとはこの例に関しては特筆すべきところはない。

例で使用しなかったタグについて。

上の例では、もっともシンプルな形で試したため、pg:prev、pg:pages、pg:nextしか使わなかった。そのほかの良く使うであろうタグについて、上の例と同様の簡単な使い方を説明する。

pg:first  名前から分かるかと思うが一番最初のページへのリンクとなるタグである。pg:prevと使い方はあまり変わらない。

<pg:first export="pageUrl,pageNumber">
<a href="<%= pageUrl %>
    &pageindex=<%= pageNumber %>&threadCheck=false&deleteOnCheck=false"><</a>
</pg:first>

pg:last  pg:firstとは逆に最後のページへのリンクとなるタグである。使い方は同じ。

<pg:last export="pageUrl,pageNumber">
    <a href="<%= pageUrl %>
        &pageindex=<%= pageNumber %>&threadCheck=false&deleteOnCheck=false"><</a>
</pg:last>

pg:skip  pg:prevタグとpg:nextタグの場合は1ページずつの移動であるが、        pg:skipタグの場合は指定したページ数の分移動する。        数値に負の値を設定するとpg:prevと同じ方向へ、        設定した数値の絶対値分移動する。下の例では5ページ進む。

<pg:skip pages="<%= 5 %>" export="pageUrl,pageNumber">
    <a href="<%= pageUrl %>
        &pageindex=<%= pageNumber %>&threadCheck=false&deleteOnCheck=false"><</a>
</pg:skip>

クラスを改良する

パラメータを保持させる

ページャのリンクをクリックしてページ移動する際、アプリケーションで必須なパラメータがあるだろう。例えば、検索結果をページングする際は、ページャのリンクをクリックしたとき、リクエストに検索条件がなかったら、全件検索したことになってしまう。

それらパラメータをページャと別に管理すると、ちょっと面倒になるうえに、間違いやすいだろう。

そこで、アプリケーションで必要になるパラメータをハッシュ(Map)にして、ページャークラスのインスタンスに格納することにした。そうしておけば、必要なときにそのインスタンスから取り出せばよい。

次に示すのが、改良後のクラスのソースである。書き加えた部分をで表示する。


package com.utils;

import java.util.List;



/**
 * 渡されたリストからJSP Pagerに必要な値を含んだインスタンスを返す
 * アプリケーションで必要なパラメータも格納するようにしている。
 * @author kazkaz
 * @version 
 */
public class ForPager {
    
    int items;
    int maxPageItems;
    int maxIndexPages;
    int totalPages;
    int currentPage;
    
    /**
     * items            要素の総数
     * maxPageItems     1ページあたりの要素数
     * maxIndexPages    1ページあたりのインデックス数
     * totalPages       全ページ数
     * currentPage      現在のページ番号
     * condition        検索条件などのパラメータを格納するマップ
     */
    public void  pageParam(List list, int entryPerPage, 
                                          int indexPerPage, int currentPage) {
        
        this.setItems(list.size());
        this.setMaxIndexPages(indexPerPage);
        this.setMaxPageItems(entryPerPage);
        this.setCurrentPage(currentPage);
        
        int pageCount = list.size() % entryPerPage==0 ?
                list.size() / entryPerPage : list.size() / entryPerPage + 1;
        this.setTotalPages(pageCount);        

    }

    /**
     * @param items_
     *         設定するitems
     */
    public void setItems(int items_) {
        this.items = items_;
    }

    /**
     * @return items
     */
    public int getItems() {
        return this.items;
    }

    /**
     * @param maxPageItems_
     *         設定するmaxPageItems
     */
    public void setMaxPageItems(int maxPageItems_) {
        this.maxPageItems = maxPageItems_;
    }
    /**
     * @return maxPageItems
     */
    public int getMaxPageItems() {
        return this.maxPageItems;
    }
    
    /**
     * @param maxIndexPages_
     *         設定するmaxIndexPages
     */
    public void setMaxIndexPages(int maxIndexPages_) {
        this.maxIndexPages = maxIndexPages_;
    }
    /**
     * @return maxIndexPages
     */
    public int getMaxIndexPages() {
        return this.maxIndexPages;
    }

    /**
     * @param totalPages_
     *         設定する totalPages
     */
    public void setTotalPages(int totalPages_) {
        this.totalPages = totalPages_;
    }
    /**
     * @return totalPages
     */
    public int getTotalPages() {
        return this.totalPages;
    }

    /**
     * @param currentPage_
     *         設定するcurrentPage
     */
    public void setCurrentPage(int currentPage_) {
        this.currentPage = currentPage_;
    }
    /**
     * @return currentPage
     */
    public int getCurrentPage() {
        return this.currentPage;
    }
}

書き足した部分はほんのわずかです。

  • 先ず、Mapが使えるようにimportの宣言をします。
  • 次に、クラス内で使う変数conditionを定義します。
  • そして、ゲッタ、セッタをつくります。

これで、クラスのほうは準備完了です。ではどのように使うかです。

パラメータをMapへ

フォームから受け取った検索条件などのパラメータをMapクラスのインスタンスにputしてページャークラスのインスタンスにsetするわけですが、先ずは必要なクラスをimportします。Mapはインターフェイスなので、それを実装したクラスをimportしてそれをnewしてインスタンスを作る必要があります。

import java.util.Map;
import java.util.HashMap;


Map tmpMap = new HashMap();

このインスタンスのメソッドputにより、key,valueの対で値を保存することが出来る。たとえば、このような感じ。

tmpMap.put("searchId", "236");
tmpMap.put("searchName","SHINOHARA");
tmpMap.put("searchSeq","DESC");

例では分かりやすいように、文字列を直に書いているが、javadocを見ると引数は両方とも、Objectとなっている。つまりこの場合はStringである。これは間違いやすいので注意が必要である。

型に注意しつつ、必要なパラメータすべてをputし終わったら、今度はページャークラスのインスタンスにセットします。

ForPager jsppg = new ForPager();



//JSPに渡すため、リクエストにセット
request.setAttribute("jsppg" , jsppg);

これで、アプリで必要なパラメータがページャークラスのインスタンスに入っているため、インスタンスをJSPに渡せば、JSP側でそれらのパラメータも取り出すことが出来ます。

また、このインスタンスの持っている値はDAOでも使うものなので、DAOにインスタンスを渡して活用するという方法もあります。

JSP側で受け取ったMapからパラメータを取り出してつかう

JSP側でも当然、Mapを扱うことになるので、importを宣言します。この場合不要かと思われたのですが、年のためHashMapもimportしました。


<%@ page import="java.util.Map" %>
<%@ page import="java.util.HashMap" %>

そして、ページャークラスのインスタンスから取り出して、各パラメータを変数に代入します。このときも型に注意しましょう。

<%
// ページャークラスのインスタンスを受け取る。
ForPager paging = (ForPager)request.getAttribute("jsppg");
//ページャで使う変数を定義。受け取ったインスタンスから値を代入。
int pageCount = paging.getTotalPages();
int currentPageNumber = paging.getCurrentPage();
String pagingUrl = "/JBBS/action/commentlist";
//インスタンスからマップを取り出して、値を取り出す。

%>

これらのパラメータを、ページャーのリンクのところにつける例は先のJSPのソースをすこし書き換えて以下のようになります。

「次のページへ」の例です。


<pg:next export="pageUrl,pageNumber">
<a href="<%= pageUrl %>
  &pageindex=<%= pageNumber %>
      &searchId=<%= searchId %>
         &searchName=<%= searchName %>
             &searchSeq=<%= searchSeq %>">次のページへ</a>
</pg:next>

前述のとおり、pageUrlは「/JBBS/action/commentlist?pg1.offset=0」のようになるので、ほしいパラメータをこの後ろに付け加えていきます。この例のとおりにしていたとすると、ブラウザで表示したときにこのタグの部分のリンクは次のようになります。

href="/JBBS/action/commentlist
          ?pg1.offset=10
            &pageindex=2
              &searchId=236
                &searchName=SHINOHARA
                  &searchSeq=DESC"

必要なパラメータがもっとある場合は、後ろに追加すればよい。そして、アクションで受け取ったパラメータをMapに入れるのを忘れないようにすること。

これで、だいぶJSP Tag Pagerを使いやすくなったのではなかろうか。

ちょっとメソッドを変更

メソッドpageParamの主な目的は、総ページ数の算出であったが、名前が分かりにくい上に、目的に不要な引数もあったため、組みなおしてすっきりさせることにした。pageParamをなくしてpageCountingというメソッドを作った。


    public void  pageCounting(List list, int entryPerPage) {
        
        this.setItems(list.size());
        this.setMaxPageItems(entryPerPage);
        
        
        int pageCount = list.size() % entryPerPage==0 ?
                list.size() / entryPerPage : list.size() / entryPerPage + 1;
        this.setTotalPages(pageCount);
    }

この変更により、前は実行不要だった(pageParam内で実行されていたため)setMaxIndexPagesとsetCurrentPageをアクションなどで必ず実行してからJSPにわたさなくてはならなくなった。