我们先看看这个分页标签的效果:
使用标签的最大好处就是下次再用到的话直接引用就行,而不必重写。
本人对Struts2自定义标签没有太深究,在网上找了一些资料可以参考参考:
其实,开发自定义标签并不需要Struts2的支持,一般情况下,只需要继承javax.servlet.jsp.tagext.BodyTagSupport类,重写doStartTag,doEndTag等方法即可。这里在实现自定义标签时,继承的2个类分别是org.apache.struts2.views.jsp.ComponentTagSupport和org.apache.struts2.components.Component,ComponentTagSupport实际上是对BodyTagSupport的一次封装,看一下ComponentTagSupport类的继承关系就明了了:
java.lang.Object extended by javax.servlet.jsp.tagext.TagSupport extended by javax.servlet.jsp.tagext.BodyTagSupport extended by org.apache.struts2.views.jsp.StrutsBodyTagSupport extended by org.apache.struts2.views.jsp.ComponentTagSupport继承ComponentTagSupport类是为了获得标签中的属性值,并包装成Component对象。继承Component类是为了从Struts2中的ValueStack中获得相对应的值。
Struts2要实现自定义标签的话,其实很简单,只需三个步骤就能实现:
第一步:创建tld文件。
tld文件其实就相当与一个标准的XML文件,其中包含了对自定义标签的声明(标签名,对应类全限定名,标签主题类型,标签属性等),在jsp中引入该标签时,web服务器会对对应的全限定名类进行实例化,和Struts的配置文件极为相似,代码如下:
pager.tld
<?xml version="1.0" encoding="UTF-8"?> <taglib version="2.0" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee web-jsptaglibrary_2_0.xsd"> <tlib-version>5.0</tlib-version> <short-name>myTag</short-name> <uri>http://hi.csdn.net/tjcyjd/tags</uri> <!-- 自定义标签的描述信息 --> <tag> <!-- 标签名 --> <name>pager</name> <!-- 对应的标签处理类全限定名 --> <tag-class>com.yjd.web.tags.PagerTag</tag-class> <!-- 标签主体的类型 --> <body-content>empty</body-content> <!-- 当前页号属性的描述信息 --> <attribute> <!-- 属性名 --> <name>pageNo</name> <!-- 该属性是否为必要的 --> <required>true</required> <!-- 属性值是否可以在JSP运行时期动态产生 --> <rtexprvalue>true</rtexprvalue> <!-- 属性的数据类型 --> <type>int</type> </attribute> <!-- 总记录数属性的描述信息 --> <attribute> <name>recordCount</name> <required>true</required> <rtexprvalue>true</rtexprvalue> <type>int</type> </attribute> <!-- 总页数属性的描述信息 --> <attribute> <name>pageSize</name> <required>true</required> <rtexprvalue>true</rtexprvalue> <type>int</type> </attribute> <!-- 分页标签要跳转的URI属性的描述信息 --> <attribute> <name>url</name> <required>true</required> <rtexprvalue>true</rtexprvalue> <type>java.lang.String</type> </attribute> </tag> </taglib>
第二步:编写自定义标签类,注意要和对应的标签处理类全限定名一致,代码如下:
PagerTag.java
package com.yjd.web.tags; import java.io.IOException; import java.util.Enumeration; import javax.servlet.http.HttpServletRequest; import javax.servlet.jsp.JspException; import javax.servlet.jsp.tagext.TagSupport; public class PagerTag extends TagSupport { private static final long serialVersionUID = 5729832874890369508L; private String url; private int pageSize = 10; private int pageNo = 1; private int recordCount; public int doStartTag() throws JspException { int pageCount = (this.recordCount + this.pageSize - 1) / this.pageSize; StringBuilder sb = new StringBuilder(); sb.append("<style type=\"text/css\">"); sb.append(".pagination {padding: 5px;float:right;font-size:12px;}"); sb .append(".pagination a, .pagination a:link, .pagination a:visited {padding:2px 5px;margin:2px;border:1px solid #aaaadd;text-decoration:none;color:#006699;}"); sb .append(".pagination a:hover, .pagination a:active {border: 1px solid #ff0000;color: #000;text-decoration: none;}"); sb .append(".pagination span.current {padding: 2px 5px;margin: 2px;border: 1px solid #ff0000;font-weight: bold;background-color: #ff0000;color: #FFF;}"); sb .append(".pagination span.disabled {padding: 2px 5px;margin: 2px;border: 1px solid #eee; color: #ddd;}"); sb.append("</style>\r\n"); sb.append("<div class=\"pagination\">\r\n"); if (this.recordCount == 0) { sb.append("<strong>没有可显示的项目</strong>\r\n"); } else { if (this.pageNo > pageCount) this.pageNo = pageCount; if (this.pageNo < 1) this.pageNo = 1; sb.append("<form method=\"post\" action=\"").append(this.url) .append("\" name=\"qPagerForm\">\r\n"); HttpServletRequest request = (HttpServletRequest) this.pageContext .getRequest(); Enumeration enumeration = request.getParameterNames(); String name = null; String value = null; while (enumeration.hasMoreElements()) { name = (String) enumeration.nextElement(); value = request.getParameter(name); if (name.equals("pageNo")) { if ((value != null) && (!"".equals(value))) { this.pageNo = Integer.parseInt(value); } } else { sb.append("<input type=\"hidden\" name=\"").append(name) .append("\" value=\"").append(value).append( "\"/>\r\n"); } } sb.append("<input type=\"hidden\" name=\"").append("pageNo") .append("\" value=\"").append(this.pageNo).append( "\"/>\r\n"); sb.append(" 共<strong>").append(this.recordCount).append( "</strong>项").append(",<strong>").append(pageCount).append( "</strong>页: \r\n"); if (this.pageNo == 1) sb.append("<span class=\"disabled\">« 上一页").append( "</span>\r\n"); else { sb.append("<a href=\"javascript:turnOverPage(").append( this.pageNo - 1).append(")\">« 上一页</a>\r\n"); } int start = 1; if (this.pageNo > 4) { start = this.pageNo - 1; sb.append("<a href=\"javascript:turnOverPage(1)\">1</a>\r\n"); sb.append("<a href=\"javascript:turnOverPage(2)\">2</a>\r\n"); sb.append("…\r\n"); } int end = this.pageNo + 1; if (end > pageCount) { end = pageCount; } for (int i = start; i <= end; i++) { if (this.pageNo == i) sb.append("<span class=\"current\">").append(i).append( "</span>\r\n"); else { sb.append("<a href=\"javascript:turnOverPage(").append(i) .append(")\">").append(i).append("</a>\r\n"); } } if (end < pageCount - 2) { sb.append("…\r\n"); } if (end < pageCount - 1) { sb.append("<a href=\"javascript:turnOverPage(").append( pageCount - 1).append(")\">").append(pageCount - 1) .append("</a>\r\n"); } if (end < pageCount) { sb.append("<a href=\"javascript:turnOverPage(").append( pageCount).append(")\">").append(pageCount).append( "</a>\r\n"); } if (this.pageNo == pageCount) sb.append("<span class=\"disabled\">下一页 »").append( "</span>\r\n"); else { sb.append("<a href=\"javascript:turnOverPage(").append( this.pageNo + 1).append(")\">下一页 »</a>\r\n"); } sb.append("</form>\r\n"); sb.append("<script language=\"javascript\">\r\n"); sb.append(" function turnOverPage(no){\r\n"); sb.append(" if(no>").append(pageCount).append("){"); sb.append(" no=").append(pageCount).append(";}\r\n"); sb.append(" if(no<1){no=1;}\r\n"); sb.append(" document.qPagerForm.pageNo.value=no;\r\n"); sb.append(" document.qPagerForm.submit();\r\n"); sb.append(" }\r\n"); sb.append("</script>\r\n"); } sb.append("</div>\r\n"); try { this.pageContext.getOut().println(sb.toString()); } catch (IOException e) { throw new JspException(e); } return 0; } public void setUrl(String url) { this.url = url; } public void setPageSize(int pageSize) { this.pageSize = pageSize; } public void setPageNo(int pageNo) { this.pageNo = pageNo; } public void setRecordCount(int recordCount) { this.recordCount = recordCount; } }
第三步:在jsp页面中直接引入该标签,其实和普通的c标签时一样的,代码如下(看第4句和第91句):
myTag.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@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://hi.csdn.net/tjcyjd/tags" prefix="myTag" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html><head><title>在线留言系统</title> <meta http-equiv=content-type content="text/html; charset=UTF-8"> <link href="images/style.css" type=text/css rel=stylesheet></link> <style type="text/css"> body{font-size: 12px} table{font-size: 12px} a{font-size:12px} .current{font-size:12px;} </style> </head> <body><!--留言表单 --> <form name=form1 action="msg/add.action" method=post> <table class=tab cellspacing=1 align=center border=0> <tbody> <tr> <td class=title background=images/titlebg.jpg colspan=2 height=25><span>请 签 写 留 言</span> </td></tr> <tr> <td align=right width="20%">您的称呼: </td> <td width="80%"><input id="username" maxlength=50 name="msg.nickname"/> </td></tr> <tr> <td align=right width="20%">您的性别: </td> <td width="80%"><input id=sex type=radio value="true" name="msg.gender"> 男 <input type=radio checked value="false" name="msg.gender"> 女 </td></tr> <tr> <td align=right>选择头像: </td> <td><select id=image name="msg.header_img"> <option value=1.gif selected>1.gif</option> <option value=2.gif>2.gif</option> <option value=3.gif>3.gif</option> <option value=4.gif>4.gif</option> <option value=5.gif>5.gif</option> <option value=6.gif>6.gif</option> <option value=7.gif>7.gif</option> <option value=8.gif>8.gif</option> <option value=9.gif>9.gif</option> <option value=10.gif>10.gif</option> <option value=11.gif>11.gif</option> <option value=12.gif>12.gif</option> <option value=13.gif>13.gif</option> <option value=14.gif>14.gif</option> <option value=15.gif>15.gif</option> <option value=16.gif>16.gif</option> <option value=17.gif>17.gif</option> <option value=18.gif>18.gif</option> <option value=19.gif>19.gif</option> <option value=20.gif>20.gif</option></select> </td></tr> <tr> <td align=right>您的qq: </td> <td><input id=qq maxlength=50 name="msg.qq"> </td></tr> <tr> <td align=right>您的邮箱: </td> <td><input id=email maxlength=50 name="msg.email"> </td></tr> <tr> <td align=right>留言内容: </td> <td><textarea id=content name="msg.content" rows=5 cols=50></textarea> </td></tr> <tr> <td align="center" colspan=2><input type=submit value=提交> <input type=reset value=重置> </td></tr></tbody></table></form><!--留言表单结束 --><!--留言列表 --> <table class=tab cellspacing=1 align=center border=0> <tbody> <tr> <td class=title background=images/titlebg.jpg colspan=2 height=25><span>留 言 列 表【<a href="login.jsp">管理登录</a>】 </span></td></tr> <c:forEach items="${pm.data}" var="msg"> <tr> <td align="center" width="20%" rowspan=4>你好 : ${msg.nickname} ${msg.gender ? "帅哥" : "靓妹"} <br><br><img src="images/${msg.header_img}"> </td></tr> <tr> <td width="80%" height="100%">发表于: <fmt:formatDate value="${msg.pubTime}" pattern="yyyy-MM-dd HH:mm:ss"/> <img src="images/8_online.gif" border=0> <a href="mailto:${msg.email}"><img src="images/email.gif" border=0></a> <img src="images/ip.gif" border=0> 来自:${msg.ip}</td></tr> <tr> <td>${msg.content}</td></tr> <tr> <td><font color=#ff0000>管理员回复:</font> </td></tr> </c:forEach> </tbody></table><!--留言列表显示结束--> <!--一引入分页标签 --> <myTag:pager pageSize="${pm.pageSize}" pageNo="${pm.pageNo}" url="index.action" recordCount="${pm.recordCount}"/> <!--分页标签结束 --> </body></html>