这是一个基于prototype.js的ajax分页,运用了spring框架,自定义分页标签,每次进入列表页面时,把列表存入session,分页只对session存储的列表进行分页,不需要再去查询数据库。但在数据量十分大的情况下,没有做性能测试。
首先在web.xml中配置spring监听和servlet
web.xml内容如下:
# <?xml version="1.0" encoding="UTF-8"?> # <web-app version="2.5" # 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-app_2_5.xsd"> # # # <context-param> # <param-name>contextConfigLocation</param-name> # <param-value>classpath*:com/kt/application/application-context.xml</param-value> # </context-param> # # <listener> # <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> # </listener> # # <servlet> # <servlet-name>root-dispatcher</servlet-name> # <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> # <load-on-startup>1</load-on-startup> # </servlet> # # <servlet-mapping> # <servlet-name>root-dispatcher</servlet-name> # <url-pattern>*.do</url-pattern> # </servlet-mapping> # # <welcome-file-list> # <welcome-file>index.jsp</welcome-file> # </welcome-file-list> # </web-app>
还需要在WEB-INF下建个root-dispatcher-servlet.xml的文件(没有这个文件会报错,为什么少了这个会出错就不知道了)
root-dispatcher-servlet.xml内容如下:
# <?xml version="1.0" encoding="UTF-8"?> # # <beans xmlns="http://www.springframework.org/schema/beans" # xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" # xmlns:util="http://www.springframework.org/schema/util" # xmlns:lang="http://www.springframework.org/schema/lang" # xmlns:aop="http://www.springframework.org/schema/aop" # xmlns:tx="http://www.springframework.org/schema/tx" # xsi:schemaLocation=" # http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd # http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.0.xsd # http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-2.0.xsd # http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd # http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd"> # # </beans>
下面是spring的配置文件,文件名是application-context.xml(为了方便spring的配置都写这个文件里了),启动tomcat 的时候加载
application-context.xml 内容如下
# <?xml version="1.0" encoding="UTF-8"?> # # <beans xmlns="http://www.springframework.org/schema/beans" # xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" # xmlns:util="http://www.springframework.org/schema/util" # xmlns:lang="http://www.springframework.org/schema/lang" # xmlns:aop="http://www.springframework.org/schema/aop" # xmlns:tx="http://www.springframework.org/schema/tx" # xsi:schemaLocation=" # http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd # http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.0.xsd # http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-2.0.xsd # http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd # http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd"> # # <bean id="requiredChecker" class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor" /> # # <bean name="urspin:urlMap" scope="singleton" lazy-init="true" # class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> # <property name="mappings"> # <props> # <prop key="/test/testController.do">testController</prop> # <prop key="/test/paginationController.do">paginationController</prop> # </props> # </property> # </bean> # # <bean id="testController" lazy-init="true" scope="singleton" # class="com.kt.controller.TestController"> # <property name="pageSize" value="5"/> # <lookup-method name="getModelAndView" bean="testGetModelAndView"/> # </bean> # # <bean id="testGetModelAndView" lazy-init="true" scope="prototype" # class="org.springframework.web.servlet.ModelAndView"> # <property name="viewName" value="/page/test.jsp" /> # </bean> # # <bean id="paginationController" lazy-init="true" scope="singleton" # class="com.kt.controller.PaginationController"> # <lookup-method name="getModelAndView" bean="paginationControllerGetModelAndView"/> # </bean> # # <bean id="paginationControllerGetModelAndView" lazy-init="true" scope="prototype" # class="org.springframework.web.servlet.ModelAndView"> # <property name="viewName" value="/page/test_1.jsp" /> # </bean> # </beans>
下面开始写分页标签,文件名为TagTest,要继承TagSupport类
TagTest.java 内容如下
# package com.kt.tag; # # import java.io.IOException; # import java.util.List; # # import javax.servlet.http.HttpSession; # import javax.servlet.jsp.JspWriter; # import javax.servlet.jsp.tagext.TagSupport; # # public class TagTest extends TagSupport # { # private int pageSize; # # private List list; # # private String url; # # private String location; # # public int doStartTag() # { # JspWriter out = pageContext.getOut();// 用pageContext获取out,他还能获取session等, # // 基本上jsp的内置对象都能获取 # HttpSession session = (HttpSession) pageContext.getSession(); # session.setAttribute("list", list); # # int pageCount = (int)Math.ceil((double)list.size()/pageSize); # # StringBuffer strBuffer = new StringBuffer(); # strBuffer.append("<table><tr><td>").append("共") # .append(list.size()).append("条").append("</td><td>") # .append("<span id=\"current\"></span>").append("/").append(pageCount).append("页</td><td>") # .append("<input id=\"txt\" type=\"text\" size=\"1\" /><a href= \"javascript:goto()\">跳转</a>").append("</td>") # .append("<td><a href="\" mce_href="\""javascript:firstPage();\">首页</a></td>").append( # "<td><a href="\" mce_href="\""javascript:prePage(); \">上一页</a></td>") # .append("<td><a href="\" mce_href="\""javascript:nextPage(); \">下一页</a></td>").append( # "<td><a href="\" mce_href="\""javascript:endPage()\">最后一页</a>").append("</td>").append( # "</tr>").append("</table>").append("<mce:script type="text/javascript"><!-- # var currentPage = 1;\n").append( # "function page(currentPage1){").append("new Ajax.Updater(") # .append("\"").append(location).append("\"").append(",").append( # "\"").append(url).append( # "\",{method:\"post\", parameters:\"") # .append("currentPage=").append("\" + currentPage1 + \"").append("&pageSize=") # .append(pageSize).append("\"}); }") # .append("\nfunction prePage(){ if( 1==currentPage){ page(1); }else{ currentPage = currentPage - 1; document.getElementById(\"current\").innerHTML = currentPage; page(") # .append("currentPage").append("); }") # .append("}\n") # .append("function nextPage(){ if(currentPage!=").append(pageCount).append("){currentPage = currentPage + 1; document.getElementById(\"current\").innerHTML = currentPage; page(").append("currentPage").append(");}}\n") # .append("function firstPage(){ currentPage = 1; document.getElementById(\"current\").innerHTML = currentPage; page(currentPage); }\n") # .append("function endPage(){ currentPage = ").append(pageCount).append("; page(currentPage); document.getElementById(\"current\").innerHTML = currentPage;}\n") # .append("function goto(){var targetPage = document.getElementById(\"txt\").value;") # .append("if(\"\" == targetPage){alert(\"没有输入页码\"); return;}") # .append("if(!(targetPage.search(\"^-?\\\\d+$\")!=0) && 0<targetPage && targetPage<=").append(pageCount).append(") {currentPage = targetPage; document.getElementById(\"current \").innerHTML = currentPage; page(currentPage);}else{alert(\"输入的页码不正确 \");}") # .append("document.getElementById(\"txt\").value = \"\";}\n") # .append("document.getElementById(\"current\").innerHTML = currentPage;") # .append(" # // --></mce:script>"); # if (Integer.valueOf(pageSize) instanceof Integer) # { # try # { # out.println(strBuffer.toString()); # } catch (IOException e) # { # e.printStackTrace(); # } # } else # { # # try # { # out.println("<table>"); # out.println("<tr>"); # out.println("<td>"); # out.println("你输入的参数格式不对"); # out.println("</td>"); # out.println("<td>"); # # out.println("</td>"); # out.println("</tr>"); # out.println("</table>"); # } catch (IOException e) # { # e.printStackTrace(); # } # } # return EVAL_PAGE;// 标签执行完后,继续执行后面的 # } # # public int doEndTag() # { # return SKIP_BODY;// 标签执行完后,不继续执行后面的 # } # # public int getPageSize() # { # return pageSize; # } # # public void setPageSize(int pageSize) # { # this.pageSize = pageSize; # } # # public List getList() # { # return list; # } # # public void setList(List list) # { # this.list = list; # } # # public String getUrl() # { # return url; # } # # public void setUrl(String url) # { # this.url = url; # } # # public String getLocation() # { # return location; # } # # public void setLocation(String location) # { # this.location = location; # } # }
写好java标签后,在WEB-INF下建立个tld类型的文件配置标签,我建的标签配置文件叫tagLib
tagLib.tld 内容如下:
# <?xml version="1.0" encoding="UTF-8"?> # <!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN" # "http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd"> # <taglib> # <tlibversion>1.2</tlibversion> # <jspversion>1.1</jspversion> # <shortname>bean</shortname> # <uri>MyTagLib</uri> # <tag> # <name>showDataTag</name> # <tagclass>com.kt.tag.TagTest</tagclass> # # <attribute> # <name>pageSize</name> # <required>true</required> # <rtexprvalue>true</rtexprvalue> # </attribute> # # <attribute> # <name>list</name> # <required>true</required> # <rtexprvalue>true</rtexprvalue> # </attribute> # # <attribute> # <name>url</name> # <required>true</required> # <rtexprvalue>true</rtexprvalue> # </attribute> # # <attribute> # <name>location</name> # <required>true</required> # <rtexprvalue>true</rtexprvalue> # </attribute> # # </tag> # </taglib>
现在开始写用于显示列表的两个controller
TestController.java用于首次进入列表页面(test.jsp),分页时调用PaginationController.java,返回一个简单页面(test_1.jsp),并局部刷新test.jsp页面
TestController.java 内容如下
# package com.kt.controller; # # import java.util.ArrayList; # import java.util.List; # # import javax.servlet.http.HttpServletRequest; # import javax.servlet.http.HttpServletResponse; # # import org.springframework.beans.factory.annotation.Required; # import org.springframework.web.servlet.ModelAndView; # import org.springframework.web.servlet.mvc.AbstractController; # # import com.kt.entity.Person; # import com.kt.entity.impl.PersonImpl; # # public class TestController extends AbstractController # { # private int pageSize; # # private ModelAndView modelAndView; # # @Override # protected ModelAndView handleRequestInternal(HttpServletRequest request, # HttpServletResponse response) throws Exception # { # List<Person> list = new ArrayList<Person>(); # for(int i = 0; i<23; i++) # { # Person person = new PersonImpl(); # person.setUserName("name_" + i); # person.setAge(i); # list.add(person); # } # # # List<Person> pageList = list.subList(0, pageSize); # # ModelAndView modelAndView = getModelAndView(); # modelAndView.addObject("list", list); # modelAndView.addObject("pageList", pageList); # return modelAndView; # } # # @Required # public void setPageSize(int pageSize) # { # this.pageSize = pageSize; # } # # public ModelAndView getModelAndView() # { # return modelAndView; # } # }
其中pageSize属性在spring配置文件中注入,其值应该与页面标签代码中的pageSize相同,否则分页会不正确
PaginationController.java内容如下
# package com.kt.controller; # # import java.util.ArrayList; # import java.util.List; # # import javax.servlet.http.HttpServletRequest; # import javax.servlet.http.HttpServletResponse; # # import org.springframework.web.servlet.ModelAndView; # import org.springframework.web.servlet.mvc.AbstractController; # # public class PaginationController extends AbstractController # { # private ModelAndView modelAndView; # # @SuppressWarnings("unchecked") # @Override # protected ModelAndView handleRequestInternal(HttpServletRequest request, # HttpServletResponse response) throws Exception # { # int pageSize = Integer.valueOf(request.getParameter("pageSize")); # # int currentPage = Integer.valueOf(request.getParameter("currentPage")); # # List list = (List)request.getSession().getAttribute("list"); # # int totalCount = list.size(); # # List pageList = new ArrayList(); # # if(pageSize >= totalCount) # { # pageList = list; # }else if((pageSize > 0)&&(pageSize < totalCount)) # { # if(1 == currentPage) # { # pageList = getPageList(list, 0, pageSize); # }else if(1 < currentPage){ # # pageList = (currentPage * pageSize > totalCount)? # getPageList(list, (currentPage - 1) * pageSize, totalCount) # :getPageList(list, (currentPage - 1) * pageSize, currentPage * pageSize); # } # } # # ModelAndView modelAndView = getModelAndView(); # modelAndView.addObject("pageList", pageList); # return modelAndView; # } # # @SuppressWarnings("unchecked") # private List getPageList(List list, int startIndex, int endIndex) # { # return list.subList(startIndex, endIndex); # } # # public ModelAndView getModelAndView() # { # return modelAndView; # } # # }
由于考虑到共用性,该controller中的List没有指明具体的类型。
下面建立个简单的JavaBean,用于测试
接口类Person.java
实现类PersonImpl.java
Person.java 内容如下:
1. package com.kt.entity; 2. 3. public interface Person 4. { 5. public abstract String getUserName(); 6. 7. public abstract void setUserName(String userName); 8. 9. public abstract int getAge(); 10. 11. public abstract void setAge(int age); 12. }
PersonImpl.java 内容如下:
# package com.kt.entity.impl; # # import com.kt.entity.Person; # # public class PersonImpl implements Person # { # private String userName; # # private int age; # # public String getUserName() # { # return userName; # } # # public void setUserName(String userName) # { # this.userName = userName; # } # # public int getAge() # { # return age; # } # # public void setAge(int age) # { # this.age = age; # } # }
下面是页面代码
test.jsp
# <%@ page language="java" contentType="text/html; charset=UTF-8" # pageEncoding="UTF-8" isELIgnored="false"%> # <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> # <%@taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%> # <%@taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%> # <%@taglib uri="http://www.springframework.org/tags/form" prefix="form"%> # <%@taglib uri="/WEB-INF/tagLib.tld" prefix="aaa" %> # # # <html> # <head> # <title>Hotel List</title> # <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> # <mce:script type="text/javascript" src="../js/prototype.js" mce_src="js/prototype.js"></mce:script> # </head> # <body> # <table> # <tr> # <td>姓名</td> # <td>年龄</td> # </tr> # <tbody id="dataShow"> # <c:forEach items="${pageList}" var="person" varStatus="status"> # <tr> # <td>${person.userName}</td> # <td>${person.age}</td> # </tr> # </c:forEach> # </tbody> # </table> # <div style="width: 500px; float: left;"> # <aaa:showDataTag url="/ajaxPagination/test/paginationController.do" location="dataShow" list="${list}" pageSize="5"></aaa:showDataTag> # </div> # </body> # </html>
url:是Ajax要提交的controller映射 ''/ajaxPagination/test/paginationController.do"中,ajaxPagination为项目名称
location:返回页面要刷新的区域
list:用于分页的List
pageSize:每页显示的条数,该数值应与TestController.java中的pageSize数值相同
注意:在test.jap页面中不要忘记把prototype.js文件放进去
test_1.jsp
# <%@ page language="java" contentType="text/html; charset=UTF-8" # pageEncoding="UTF-8" isELIgnored="false"%> # <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> # <%@taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%> # <%@taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%> # <%@taglib uri="http://www.springframework.org/tags/form" prefix="form"%> # # <c:forEach items="${pageList}" var="person" varStatus="status"> # <tr> # <td>${person.userName}</td> # <td>${person.age}</td> # </tr> # </c:forEach>