Skip to content

May 27, 2011

3

Simple pagination taglib for JSP

Pagination is a common requirement when writing JSPs. Long sets of data must be broken up across multiple pages. There is no standard way to implement pagination in JSP or JSTL, however. You must use a custom tag to generate the page numbers.

I’ve created a simple pagination taglib that generates the page links. You can customize it to your needs. Usage example below. Here, I’m using it to paginate search results from Lucene:

<c:url var="searchUri" value="/searchResults.html?s=${searchval}&page=##" />
<paginator:display maxLinks="10" currPage="${page}" totalPages="${totalPages}" uri="${searchUri}" />

The paginator:display tag produces this output:

shows links 1 through 10

This is obviously showing Page 4 of the search results. As you can see, you specify the URI, and the tag expects a ## where the page number will go. You also specify the current page, the total number of pages, and the maximum number of page links you want to show.

The paginator output is an unordered list, which you’ll want to style something like this:

.paginatorList { margin: 2px 6px; list-style: none outside none; }
.paginatorList li { float: left; padding: 2px 4px; font-size: 1.2em; }
li.paginatorCurr { font-weight: bold; font-size: 1.5em; margin-top: -2px; }
li.paginatorLast { float: none; }

This CSS will style the page links just like the example above.

Here is the java code for the paginator taglib:

package my.taglibs;

import java.io.Writer;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.SimpleTagSupport;

public class Paginator extends SimpleTagSupport {
    private String uri;
    private int currPage;
    private int totalPages;
    private int maxLinks = 10;
    
    private Writer getWriter() {
        JspWriter out = getJspContext().getOut();
        return out;
    }

    @Override
    public void doTag() throws JspException {
        Writer out = getWriter();
        
        boolean lastPage = currPage == totalPages;
        int pgStart = Math.max(currPage - maxLinks / 2, 1);
        int pgEnd = pgStart + maxLinks;
        if (pgEnd > totalPages + 1) {
            int diff = pgEnd - totalPages;
            pgStart -= diff - 1;
            if (pgStart < 1)
                pgStart = 1;
            pgEnd = totalPages + 1;
        }

        try {
            out.write("<ul class=\"paginatorList\">");
            
            if (currPage > 1)
                out.write(constructLink(currPage - 1, "Previous", "paginatorPrev"));
            
            for (int i = pgStart; i < pgEnd; i++) {
                if (i == currPage)
                    out.write("<li class=\"paginatorCurr"+ (lastPage && i == totalPages ? " paginatorLast" : "")  +"\">"+ currPage + "</li>");
                else
                    out.write(constructLink(i));
            }
            
            if (!lastPage)
                out.write(constructLink(currPage + 1, "Next", "paginatorNext paginatorLast"));
            
            out.write("</ul>");

        } catch (java.io.IOException ex) {
            throw new JspException("Error in Paginator tag", ex);
        }
    }
    
    private String constructLink(int page) {
        return constructLink(page, String.valueOf(page), null);
    }
    
    private String constructLink(int page, String text, String className) {
        StringBuilder link = new StringBuilder("<li");
        if (className != null) {
            link.append(" class=\"");
            link.append(className);
            link.append("\"");
        }
        link.append(">")
            .append("<a href=\"")
            .append(uri.replace("##", String.valueOf(page)))
            .append("\">")
            .append(text)
            .append("</a></li>");
        return link.toString();
    }

    public void setUri(String uri) {
        this.uri = uri;
    }

    public void setCurrPage(int currPage) {
        this.currPage = currPage;
    }

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

    public void setMaxLinks(int maxLinks) {
        this.maxLinks = maxLinks;
    }
}

And the .tld file:

<?xml version="1.0" encoding="UTF-8"?>
<taglib version="2.1" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd">
  <tlib-version>1.0</tlib-version>
  <short-name>paginator</short-name>
  <uri>/WEB-INF/tlds/Paginator</uri>
  
  <tag>
    <name>display</name>
    <tag-class>my.taglibs.Paginator</tag-class>
    <body-content>empty</body-content>
    <attribute>
      <name>uri</name>
      <required>true</required>
      <rtexprvalue>true</rtexprvalue>
      <type>java.lang.String</type>
    </attribute>
    <attribute>
      <name>currPage</name>
      <required>true</required>
      <rtexprvalue>true</rtexprvalue>
      <type>int</type>
    </attribute>
    <attribute>
      <name>totalPages</name>
      <required>true</required>
      <rtexprvalue>true</rtexprvalue>
      <type>int</type>
    </attribute>
    <attribute>
      <name>maxLinks</name>
      <rtexprvalue>true</rtexprvalue>
      <type>int</type>
    </attribute>
  </tag>
</taglib>

Now you can easily add pagination to any JSP. Leave a comment if you found this useful! If you have a blog as well, I wouldn’t mind a link. ^_^

Read more from Java
3 Comments Post a comment
  1. Christos
    Feb 19 2012

    I was seeking for a simple pagination library for spring mvc, but I couldn’t find something based on my needs.
    And then I found your taglib which is exactly what I need !
    Thanks a lot !

    Reply
  2. max
    Mar 8 2013

    You could write something about the business logic of pagination. How to retrieve paged results, how to store intermediate results, what to store – whole data in server, whole data in client, 50-50, etc…
    This is a topic worth a whole book.

    Reply
  3. Mihail.Smazhevsky
    Mar 24 2013

    Thank you very much for that really useful and simple taglib

    Reply

Share your thoughts, post a comment.

(required)
(required)

Note: HTML is allowed. Your email address will never be published.

Subscribe to comments