两个字母搞定J2EE通用分页标签(四)

作者:张纪豪(转载请注明出处)


(五)、视图层的JSP页面输出分页数据

由于Action中往request对象里放了分页数据,那我们在JSP页面就可遍历出来,但同时应将页码信息输出来,我们看看JSP页面是如何处理的?

在WebRoot/WEB-INF/jsp/目录下建立两个jsp文件:

list_book.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://zhangjihao.com/page" prefix="t" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>图书列表</title>
  </head>
  
  <body>
  <h1 align="center">图书列表</h1>
  <TABLE align="center">
   <tr>
    <td>书名</td>
    <td>作者</td>
    <td>出版社</td>
    <td>价格</td>
    <td>ISBN号</td>
    <td>日期</td>
   </tr>
   <tr>
     <c:forEach items="${books}" var="book">
      <td>${book.bookname}</td>
     <td>${book.author}</td>
     <td>${book.publisher}</td>
     <td>${book.price}</td>
     <td>${book.isbn}</td>
     <td>${book.pubDate}</td>
     </c:forEach>
   </tr>
   </TABLE>
   <!-- 注意了,两个字母实现通用分页 -->
   <t:p/>
  </body>
</html>

list_news.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://zhangjihao.com/page" prefix="t" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>新闻列表</title>
  </head>
  
  <body>
  <h1 align="center">新闻列表</h1>
  <TABLE align="center">
   <tr>
    <td>新闻标题</td>
    <td>新闻来源</td>
    <td>日期</td>
   </tr>
   <tr>
     <c:forEach items="${newses}" var="news">
      <td>${news.title}</td>
     <td>${news.rootin}</td>
     <td>${news.createdate}</td>
     </c:forEach>
   </tr>
   </TABLE>
   <!-- 注意了,两个字母实现通用分页 -->
   <t:p/>
  </body>
</html>

jsp文件中最重要的是声明标签库和调用分页标签:

<%@ taglib uri="http://zhangjihao.com/page" prefix="t" %> <t:p/>

事实上这目前还不能在页面上输出页码信息,做过JSP标签库的朋友都知道,还要编写标签库和配置标签,好,下一步也是最后一步,我们就开始编写分页标签。

(六)、标签库编程及配置

对于标签大家熟悉不过了,HTML文件全是标签组成,再看JSP、JSTL、Struts、Spring MVC都搞那么多标签,全把程序员捆在尖括号中央,郁闷之余,发誓也搞个自己的尖括号^_^。

机会来了......

先带大家了解下JSP标记:

标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求,这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib,其实换句话说,taglib可以看成是对JSP标记的一种扩展,正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中,这种标签库存放着你自己定义的tag标签。简而言之,如果使用taglib,那么你可以设计自己的JSP标记!

一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时,tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后,实际上tag标签被转化成为了对tag处理类的操作。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN"
                        "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">
<taglib>
 	<tlib-version>1.0</tlib-version>
 	<jsp-version>1.0</jsp-version>
 	<short-name>p</short-name>
	<!-- 标签库地址,如果这写这个,JSP页面上用逻辑路径指定也可以找到 -->

 	<uri>http://zhangjihao.com/page</uri>
 	<description>分页标签库</description>
 	<tag>
  		<!-- 标签名 -->
		<name>p</name> 
		<!-- 实现类 -->

  		<tag-class>com.zhangjihao.web.taglib.PagePrint</tag-class>
		<!-- 参数:是否输出页数信息,默认为输出 -->
  		<attribute>
   			<name>totalcount</name>
   			<rtexprvalue>false</rtexprvalue>
   			<type>boolean</type>
  		</attribute>
		<!-- 参数:是否输出总记录信息,默认为输出 -->

  		<attribute>
   			<name>pagecount</name>
   			<rtexprvalue>false</rtexprvalue>
   			<type>boolean</type>
  		</attribute>
		<!-- 参数:当前页码的显示样式,如果不指定,将按默认值 -->

  		<attribute>
   			<name>curPageNumberStyle</name>
   			<rtexprvalue>false</rtexprvalue>
   			<type>String</type>
  		</attribute>
  		<!-- 参数:带链接的页码的显示样式,如果不指定,将按默认值 -->

  		<attribute>
   			<name>linkPageNumberStyle</name>
   			<rtexprvalue>false</rtexprvalue>
   			<type>String</type>
  		</attribute>
	</tag>
</taglib>
    

由于request作用的不同,所以在n个JSP页面上调用<t:p/>都不会出输出重复的内容,故实现最大的简化。

到此为止已经完成了通用分页过程,如果有不明之处,或有批评和建议者,欢迎致信!

要使用tag标签,JSP程序员必须做两件事:

· 声明此tag标签的tag库
· 实现此tag标签

我们反着来,先实现tag标签

PagePrint.java

 

package com.zhangjihao.web.taglib; import java.io.IOException; import javax.servlet.http.HttpServletRequest; import javax.servlet.jsp.JspException; import javax.servlet.jsp.JspWriter; import javax.servlet.jsp.tagext.TagSupport; import com.zhangjihao.bean.Page; /** * 页码标签程序,特点: * 1、5页后当前页码总在中间 * 2、页码上的URL地址支持多种方式,如: * page.setUrl("http://www.zhangjihao.com/article/list_*.do"); “*”号会被替换成页码,Spring MVC支持这种伪静态地址 * page.setUrl("http://www.zhangjihao.com/article/list.do"); 地址后面会自动加上页码参数 * page.setUrl("http://www.zhangjihao.com/article/list.do?cid=1"); 地址后面会自动加上页码参数,不影响多参数连接。 * 3、页码显示样式可由外面css样式传入 * * @author 张纪豪 * @version 0.2 * Build Time Mar 21, 2007 */ public class PagePrint extends TagSupport { private static final long serialVersionUID = 1L; /**是否显示总记录数*/ private boolean totalcount = true; //如果外面不指定,将默认为显示 /**是否显示总页数*/ private boolean pagecount = true; //如果外面不指定,将默认为显示 /**当前页码的显示样式**/ private String curPageNumberStyle = "pagenumbervisited"; //如果外面不指定,将按默认值 /**带链接的页码的显示样式**/ private String linkPageNumberStyle = "pagenumber";//如果外面不指定,将按默认值 public int doStartTag() throws JspException { //在标签类中定义Request对象 HttpServletRequest request = (HttpServletRequest)pageContext.getRequest(); String curPath = request.getContextPath(); if(request.getAttribute("page") != null){ //大家还记得我们在控制层将page对象放到了Request作用里吗?现在是用它的时候了 Page page = (Page)request.getAttribute("page"); JspWriter out = pageContext.getOut(); StringBuffer sb = new StringBuffer(""); try { //如果设定了要打印总页数,则在JSP页面中输出当前页和总页数 if(this.isPagecount()) sb.append("当前页/总页数:"+page.getPageIndex()+"/"+page.getPageCount()+""); sb.append("页码:"); //如果当前页码大于1时,应该输出开始一页和上一页的连接 if(page.getPageIndex() > 1){ sb.append("<a title=\"开始一页\" href="\" mce_href="\"""+conversionUrl(page.getUrl(),1)+"\"> <img src="\" mce_src="\"""+curPath+"/images/navigation_top.gif\" border=\"0\"/></a>"); sb.append("<a title=\"上一页\" href="\" mce_href="\"""+conversionUrl(page.getUrl(),page.getPageIndex()-1)+"\"> <img src="\" mce_src="\"""+curPath+"/images/navigation_previous.gif\" border=\"0\"/></a>"); } //开始在总页数里循环 for (int cur = 1; cur <= page.getPageCount(); cur++){ //假如有几十页、几百页、甚至n多,我们不能全部将页码输出吧?这里只取10页 if(page.getPageIndex() < 5 && cur < 10){ if(cur == page.getPageIndex()){ //当前页不应该有连接 sb.append("<span class=\"pagenumbervisited\">"+cur+"</span>"); }else{ sb.append("<a href="\" mce_href="\"""+conversionUrl(page.getUrl(),cur)+"\" class=\"pagenumber\" title=\"第"+cur+"页\">"+cur+"</a>"); } }else{ //进入5页以后,要让当前页码总在中间。百度原来是不是抄我的?哈哈...吹一把 if(cur > page.getPageIndex() -5 && cur < page.getPageIndex()+5){ if(cur == page.getPageIndex()){ sb.append("<span class=\"pagenumbervisited\">"+cur+"</span>"); }else{ sb.append("<a href="\" mce_href="\"""+conversionUrl(page.getUrl(),cur)+"\" class=\"pagenumber\" title=\"第"+cur+"页\">"+cur+"</a>"); } } } } //只要没有进到最后一页,都应该输出下一面和最后一页连接 if(page.getPageIndex() < page.getPageCount()){ sb.append("<a title=\"下一页\" href=""+conversionUrl(page.getUrl(),page.getPageIndex()+1)+"" mce_href=""+conversionUrl(page.getUrl(),page.getPageIndex()+1)+""> <img src="\" mce_src="\"""+curPath+"/images/navigation_next.gif\" border=\"0\"/></a>"); sb.append("<a title=\"最后一页\" href=""+conversionUrl(page.getUrl(),page.getPageCount())+"" mce_href=""+conversionUrl(page.getUrl(),page.getPageCount())+""> <img src="\" mce_src="\"""+curPath+"/images/navigation_bott.gif\" border=\"0\"/></a>\n"); } //标记中调用是否指定输出每页记录数和总记录数 if(this.isTotalcount()) sb.append("每页记录数/总记录数:"+ page.getPageSize()+"/"+page.getTotalCount()); } catch (Exception e) { sb.append(e.getMessage()); }finally{ //往页面上输出 try { out.println(sb.toString()); } catch (IOException e) { e.printStackTrace(); } } } return TagSupport.SKIP_BODY; } //辅助方法 private String conversionUrl(String url, int pageindex){ if(url == null || url.length() < 1) return "index.jsp"; if(url.indexOf('*')>-1){ return url.replace("*", String.valueOf(pageindex)); }else{ StringBuffer sb = new StringBuffer(url); if(sb.indexOf("?") > -1){ char c = sb.charAt(sb.length()-1); if(c=='?' || c=='&'){ sb.append(Page.pageNumberParameterName + "=" + pageindex); }else{ sb.append("&"+Page.pageNumberParameterName + "=" + pageindex); } }else{ sb.append("?"+Page.pageNumberParameterName + "=" + pageindex); } return sb.toString(); } } /Setter&Getter/ public boolean isTotalcount() { return totalcount; } public boolean isPagecount() { return pagecount; } public void setTotalcount(boolean totalcount) { this.totalcount = totalcount; } public void setPagecount(boolean pagecount) { this.pagecount = pagecount; } public String getCurPageNumberStyle() { return curPageNumberStyle; } public void setCurPageNumberStyle(String curPageNumberStyle) { this.curPageNumberStyle = curPageNumberStyle; } public String getLinkPageNumberStyle() { return linkPageNumberStyle; } public void setLinkPageNumberStyle(String linkPageNumberStyle) { this.linkPageNumberStyle = linkPageNumberStyle; } }

标签的实现需要继承TagSupport,有关这方面的详细知识可以参考J2EE规范Servlet中的JSP2.0技术。页码信息中还用了几个小图片,像开始一页、上一页、下一页、最后一页都是用图片标识的,所以大家去找几个图片放在Webroot/images目录下,当然也可以去掉,用文或符号描述。

下面配置上述的标签实现,在WEB-INF目录下建立一个tld文件(这里我用了自己的名字全拼作文件名):

zhangjihao.tld

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值