您的位置:首页 > 其它

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

2009-08-24 10:26 316 查看
作者:张纪豪(转载请注明出处)

(五)、视图层的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>
[/code]
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>

[/code]
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>
[/code]
由于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目录下,当然也可以去掉,用文或符号描述。
[/code]

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

zhangjihao.tld
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: