1.Tip:案例
使用标签控制页面逻辑案例:
开发防盗链标签
开发<c:if>标签
开发<c:if><c:else>标签
开发迭代标签
开发html转义标签
打包标签库
package com.csdn.ifDemo;
import java.io.IOException;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.servlet.jsp.JspException;
importjavax.servlet.jsp.tagext.SimpleTagSupport;
/**
* 该自定义标签,可以遍历任何集合和数组
*@author xiaosong
*
*/
public class ForEachTag0 extendsSimpleTagSupport {
privateCollection<Object> collection;
privateString var1;
privateObject items;
publicvoid setVar1(String var1) {
this.var1= var1;
}
publicvoid setItems(Object items) {
this.items= items;
if(itemsinstanceof Map){
Map map = (Map)items;
collection= map.entrySet();
}
if(itemsinstanceof Collection){
collection= (Collection) items;
}
if(items.getClass().isArray()){
collection = new ArrayList();
intlen = Array.getLength(items);
for(inti=0;i<len;i++){
Objectobj = Array.get(items, i);
collection.add(obj);
}
}
}
@Override
publicvoid doTag() throws JspException, IOException {
Iterator<Object>it = collection.iterator();
while(it.hasNext()){
Objectobj = it.next();
this.getJspContext().setAttribute(var1,obj);
this.getJspBody().invoke(null);
}
}
}
<?xml version="1.0"encoding="UTF-8" ?>
<taglibxmlns="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 http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
version="2.0">
<description>A tag library exercising SimpleTaghandlers.</description>
<tlib-version>1.0</tlib-version>
<short-name>c</short-name>
<uri>/ifDemo</uri>
<tag>
<name>if0</name>
<tag-class>com.csdn.ifDemo.IfDemo0</tag-class>
<body-content>scriptless</body-content>
<attribute>
<name>test</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
<tag>
<name>choose</name>
<tag-class>com.csdn.ifDemo.ChooseTag</tag-class>
<body-content>scriptless</body-content>
</tag>
<tag>
<name>if</name>
<tag-class>com.csdn.ifDemo.WhenTag</tag-class>
<body-content>scriptless</body-content>
<attribute>
<name>test</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
<tag>
<name>else</name>
<tag-class>com.csdn.ifDemo.OtherTag</tag-class>
<body-content>scriptless</body-content>
</tag>
<tag>
<name>ForEach</name>
<tag-class>com.csdn.ifDemo.ForEachTag</tag-class>
<body-content>scriptless</body-content>
<attribute>
<name>var1</name>
<required>true</required>
</attribute>
<attribute>
<name>items</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
<tag>
<name>ForEach0</name>
<tag-class>com.csdn.ifDemo.ForEachTag0</tag-class>
<body-content>scriptless</body-content>
<attribute>
<name>var1</name>
<required>true</required>
</attribute>
<attribute>
<name>items</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
<tag>
<name>filter</name>
<tag-class>com.csdn.Demo.HTMLFilter</tag-class>
<body-content>scriptless</body-content>
</tag>
</taglib>
<%@ page language="java"import="java.util.*,com.csdn.ifDemo.Person"pageEncoding="UTF-8"%>
<%@ taglib uri="/ifDemo"prefix="c" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTDHTML 4.01 Transitional//EN">
<html>
<head>
<title>if @@ if else @@ List</title>
</head>
<body>
<br/>----------<br/>
<c:choose>
if:<c:iftest="true">ifelse标签truetruetruetrue</c:if>
<c:else>ifelse标签falsefalsefalse</c:else>
</c:choose>
<br/>
<c:choose>
else:<c:iftest="false">ifelse标签truetruetruetrue</c:if>
<c:else>ifelse标签falsefalsefalse</c:else>
</c:choose>
<br/>----------<br/>
<c:if0 test="true">if标签truetruetruetrue</c:if0>
<br/>----------<br/>
List:<br/>
<%
List list = new ArrayList();
list.add("aaaaa");
list.add("bbbbb");
list.add("ccccc");
list.add("ddddd");
request.setAttribute("list",list);
%>
<c:ForEach var1="str"items="${list}">${str}<br></c:ForEach>
<c:ForEach0 items="${list}"var1="str2">${str2}<br></c:ForEach0>
<br/>----------<br/>
Map:<br/>
<%
Map map = new LinkedHashMap();
map.put("a",newPerson("qiao"));
map.put("b",newPerson("xiao"));
map.put("c",newPerson("song"));
request.setAttribute("map",map);
%>
<c:ForEach0items="${map}" var1="str1">${str1.key}......${str1.value.name}<br/s></c:ForEach0>
<br/>----------<br/>
<c:filter><ahref="">转义标签</a></c:filter>
</body>
</html>
2.打包自定义标签库
把自定义的标签打到一个jar包中,就是要把标签处理类的字节码和标签库描述文件按照一定的存放方式添加到一个jar包中。具体做法如下。
把标签处理类字节码和标签库描述文件按如下所示的结构组织。
使用jar命令来创建jar文件:
jar cvf mytaglib_0.9.jar META-INF com
完成这两个步骤之后,一个自定义标签库jar包就打好了,可以把它添加到任何想使用这个标签库的Web应用程序的WEB-INF/lib目录下使用了。
3. 实用案例:自定义分页标签
分页标签的使用方式如下:
<q:pager pageNo="当前页号" pageSize="每页要显示的记录数" recordCount="总记录数" url="要跳转的URI" />
通过给这个标签传入当前页号、每页要显示的记录数、总记录数和要跳转的URI,这个标签就可以生成翻页的HTML元素。
标签处理类
这个标签只是通过指定属性值就可以生成所有的翻页元素,因此这个标签不需要主体,可以直接继承自TagSupport类:public class PagerTag extends TagSupport {...}
然后为这个标签定义4个属性,给它们提供setter方法,以便使用标签时,从外部传值进来。
最主要的逻辑实现都是在doStartTag()方法中,首先通过总记录数和每页要显示的记录数计算出总页数:
int pageCount = (recordCount + pageSize - 1) / pageSize;
编写要输出到响应的StringBuilder实例。
把请求对象中获取的所有请求参数都作为隐藏表单域(<input type=“hidden”>)生成到一个form表单中:
生成翻页的HTML元素。这一段逻辑稍微复杂一些。
生成“总记录数和总页数”
是否要显示“上一页”超链接的逻辑处理。
如果总页数超过5页,显示“…”
当前页和它附近页的显示处理
如果总页数比当前页数超过2页,显示“...”
是否要显示“下一页”超链接的逻辑处理
在标签库描述符文件描述这个标签的信息
在页面中使用该分页标签
用taglib指令引用该标签库描述文件:
< %@ taglib uri="http://blog.csdn.net/qjyong/tags/pager"prefix="q"%>
为该分页标签准备好一些样式,让翻页元素更美观:
用代码片段显示数据
调用分页标签
创建一个TestPagerTagServlet的Servlet,用来准备测试数据,并为分页标签准备好参数值,然后转发到测试页。
/**
* ClassName: PagerTag.java
* createdon 2009-03-20
* Copyrights 2009 qjyong All rights reserved.
* EMail: qjyong@gmail.com
*/
package com.qiujy.web.tags;
import java.io.IOException;
import java.util.Enumeration;
importjavax.servlet.http.HttpServletRequest;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.TagSupport;
/**
* 分页标签处理类
*/
public class PagerTag extends TagSupport {
privatestatic final long serialVersionUID = 5729832874890369508L;
privateString url; //请求URI
privateint pageSize = 10; //每页要显示的记录数
privateint pageNo = 1; //当前页号
privateint recordCount; //总记录数
@SuppressWarnings("unchecked")
publicint doStartTag() throws JspException {
intpageCount = (recordCount + pageSize - 1) / pageSize; //计算总页数
//拼写要输出到页面的HTML文本
StringBuildersb = new StringBuilder();
sb.append("\r\n<divclass=\"pagination\">\r\n");
if(recordCount== 0){
sb.append("<strong>没有可显示的项目</strong>\r\n");
}else{
//页号越界处理
if(pageNo> pageCount){ pageNo =pageCount; }
if(pageNo< 1){ pageNo = 1; }
sb.append("<formmethod=\"post\" action=\"\" ")
.append("name=\"qPagerForm\">\r\n");
//获取请求中的所有参数
HttpServletRequestrequest = (HttpServletRequest) pageContext
.getRequest();
Enumeration<String>enumeration = request.getParameterNames();
Stringname = null; //参数名
Stringvalue = null; //参数值
//把请求中的所有参数当作隐藏表单域
while(enumeration.hasMoreElements()) {
name= enumeration.nextElement();
value= request.getParameter(name);
//去除页号
if(name.equals("pageNo")) {
if(null != value && !"".equals(value)) {
pageNo = Integer.parseInt(value);
}
continue;
}
sb.append("<inputtype=\"hidden\" name=\"")
.append(name)
.append("\" value=\"")
.append(value)
.append("\"/>\r\n");
}
//把当前页号设置成请求参数
sb.append("<inputtype=\"hidden\" name=\"").append("pageNo")
.append("\"value=\"").append(pageNo).append("\"/>\r\n");
//输出统计数据
sb.append(" 共<strong>").append(recordCount)
.append("</strong>项")
.append(",<strong>")
.append(pageCount)
.append("</strong>页: \r\n");
//上一页处理
if(pageNo == 1) {
sb.append("<spanclass=\"disabled\">« 上一页")
.append("</span>\r\n");
}else {
sb.append("<ahref=\"javascript:void(null)\"")
.append(" onclick=\"turnOverPage(")
.append((pageNo - 1))
.append(")\">« 上一页</a>\r\n");
}
//如果前面页数过多,显示"..."
intstart = 1;
if(this.pageNo> 4){
start= this.pageNo - 1;
sb.append("<ahref=\"javascript:void(null)\"")
.append("onclick=\"turnOverPage(1)\">1</a>\r\n");
sb.append("<ahref=\"javascript:void(null)\"")
.append("onclick=\"turnOverPage(2)\">2</a>\r\n");
sb.append("…\r\n");
}
//显示当前页附近的页
intend = this.pageNo + 1;
if(end> pageCount){
end= pageCount;
}
for(inti = start; i <= end; i++){
if(pageNo== i){ //当前页号不需要超链接
sb.append("<spanclass=\"current\">")
.append(i)
.append("</span>\r\n");
}else{
sb.append("<ahref=\"javascript:void(null)\"")
.append("onclick=\"turnOverPage(")
.append(i)
.append(")\">")
.append(i)
.append("</a>\r\n");
}
}
//如果后面页数过多,显示"..."
if(end< pageCount - 2){
sb.append("…\r\n");
}
if(end< pageCount - 1){
sb.append("<ahref=\"javascript:void(null)\"")
.append("onclick=\"turnOverPage(")
.append(pageCount- 1)
.append(")\">")
.append(pageCount- 1)
.append("</a>\r\n");
}
if(end< pageCount){
sb.append("<ahref=\"javascript:void(null)\"")
.append("onclick=\"turnOverPage(")
.append(pageCount)
.append(")\">")
.append(pageCount)
.append("</a>\r\n");
}
//下一页处理
if(pageNo == pageCount) {
sb.append("<spanclass=\"disabled\">下一页 »")
.append("</span>\r\n");
}else {
sb.append("<ahref=\"javascript:void(null)\"")
.append("onclick=\"turnOverPage(")
.append((pageNo+ 1))
.append(")\">下一页 »</a>\r\n");
}
sb.append("</form>\r\n");
//生成提交表单的JS
sb.append("<scriptlanguage=\"javascript\">\r\n");
sb.append(" function turnOverPage(no){\r\n");
sb.append(" var qForm=document.qPagerForm;\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(" qForm.pageNo.value=no;\r\n");
sb.append(" qForm.action=\"").append(url).append("\";\r\n");
sb.append(" qForm.submit();\r\n");
sb.append(" }\r\n");
sb.append("</script>\r\n");
}
sb.append("</div>\r\n");
//把生成的HTML输出到响应中
try{
pageContext.getOut().println(sb.toString());
}catch (IOException e) {
thrownew JspException(e);
}
returnSKIP_BODY; //本标签主体为空,所以直接跳过主体
}
publicvoid setUrl(String url) {
this.url= url;
}
publicvoid setPageSize(int pageSize) {
this.pageSize= pageSize;
}
publicvoid setPageNo(int pageNo) {
this.pageNo= pageNo;
}
publicvoid setRecordCount(int recordCount) {
this.recordCount= recordCount;