首页 > 代码库 > 自定义标签案例

自定义标签案例

(1)、用自定义标签模仿完成if功能

首先写一个标签处理类

package com.gqx.a_tag;

import java.io.IOException;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.SimpleTagSupport;

public class IfTag extends SimpleTagSupport {
	//添加属性
	private boolean test;
	public void setTest(boolean test){
		this.test=test;
	}
	@Override
	public void doTag() throws JspException, IOException {
		//根据test的返回的内容决定是否输出内容
		if (test) {
			this.getJspBody().invoke(null);
		}
	}
}

去tld文件中添加标签

<!--有属性的Tag标签  -->
 	<tag>
 		<name>if</name>
 		<tag-class>com.gqx.a_tag.IfTag</tag-class>
 		<body-content>scriptless</body-content>
 		<!-- 传入属性 -->
 		<attribute>
 			<!-- 标签名 -->
 			<name>test</name>
 			<!-- 是否一定需要 -->
 			<required>true</required>
 			<!-- 是否支持EL表达式 -->
 			<rtexprvalue>true</rtexprvalue>
 		</attribute>	
 	</tag>

然后去jsp页面添加taglib指令

<%@taglib uri="http://www.gqxing.com" prefix="c" %>

然后在body内容中添加

<c:if test="${10<5 }">
    	条件成立啦。
    </c:if>

(2)、完成自定义choose标签

有三个处理类

父标签

package com.gqx.ChooseTag;

import java.io.IOException;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.SimpleTagSupport;
//choose标签只需要执行里面的内容就行了
public class Choose extends SimpleTagSupport {
	//保存临时对象,即子标签中when中的判断值
	private boolean flag;
	public void setFlag(boolean flag) {
		this.flag = flag;
	}
	public boolean isFlag() {
		return flag;
	}
	@Override
	public void doTag() throws JspException, IOException {
		this.getJspBody().invoke(null);
	}
}

两个子标签

package com.gqx.ChooseTag;

import java.io.IOException;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.SimpleTagSupport;
//When标签需要做判断
public class When extends SimpleTagSupport {
	private boolean test;
	public void setTest(boolean test){
		this.test=test;
	}
	@Override
	public void doTag() throws JspException, IOException {
		if (test) {
			this.getJspBody().invoke(null);
		}
		//因为choose标签下面另一个子标签othsewhise需要做判断,
		//而otherwise没有属性,需要通过父标签传递判断的结果,
		//将结果保存在父标签中的flag中。
		//获取父标签
		Choose parent=(Choose)this.getParent();
		parent.setFlag(test);
	}
}

  

package com.gqx.ChooseTag;

import java.io.IOException;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.SimpleTagSupport;
//完成otherwise功能 
public class Otherwise extends SimpleTagSupport {
	@Override
	public void doTag() throws JspException, IOException {
		//从父标签中获取When判断的结果
		Choose parent=(Choose)this.getParent();
		Boolean test=parent.isFlag();
		if (!test) {
			this.getJspBody().invoke(null);
		}
		
	}
}

接下来继续去tld文件中配置标签

    <!--choose标签  -->
 	<tag>
 		<name>choose</name>
 		<tag-class>com.gqx.ChooseTag.Choose</tag-class>
 		<body-content>scriptless</body-content>
 	</tag>
 	<!--有属性的when标签  -->
 	<tag>
 		<name>when</name>
 		<tag-class>com.gqx.ChooseTag.When</tag-class>
 		<body-content>scriptless</body-content>
 		<!-- 传入属性 -->
 		<attribute>
 			<!-- 标签名 -->
 			<name>test</name>
 			<!-- 是否一定需要 -->
 			<required>true</required>
 			<!-- 是否支持EL表达式 -->
 			<rtexprvalue>true</rtexprvalue>
 		</attribute>	
 	</tag>
 	<!--otherwise标签  -->
 	<tag>
 		<name>Otherwise</name>
 		<tag-class>com.gqx.ChooseTag.Otherwise</tag-class>
 		<body-content>scriptless</body-content>	
 	</tag>
 	

在jsp页面添加如下代码

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@taglib uri="http://www.gqxing.com" prefix="c" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
  	<title>My JSP ‘chooseTag.jsp‘ starting page</title>
   </head> 
  <body>
    <c:choose>
    	<c:when test="${10<5}">你通过啦!!!哈哈</c:when>
    	<c:Otherwise>不开心,没有通过呢!!!</c:Otherwise>
    </c:choose>
  </body>
</html>

 结果如图:

技术分享


(3)、完成foreach标签的自定义

标签处理类

package com.gqx.a_tag;

import java.io.IOException;
import java.util.List;


import java.util.Map;
import java.util.Set;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.SimpleTagSupport;

import com.google.common.collect.Multiset.Entry;

public class Foreach extends SimpleTagSupport {
	private Object items;
	private String var;
	public void setItems(Object items) {
		this.items = items;
	}
	public void setVar(String var) {
		this.var = var;
	}
	@Override
	public void doTag() throws JspException, IOException {
		//得到当前页面的pagecontex,方便在后面的操作中将值插入域对象中
		PageContext context=(PageContext) this.getJspContext();
		//这里只判断List对象
		if (items instanceof List) {
			List list=(List)items;
			for (Object object : list) {
				//将对应的值传入域对象,用以在如下形式的方式输出
				//姓名:${student.name } - 年龄:${student.age }
				context.setAttribute(var, object);
				//输出到页面上去
				this.getJspBody().invoke(null);
			}
		}
		
		
	}
}

tld文件的tag配置

<!--foreach标签  -->
 	<tag>
 		<name>forEach</name>
 		<tag-class>com.gqx.a_tag.Foreach</tag-class>
 		<body-content>scriptless</body-content>
 		<!-- 传入属性 -->
 		<attribute>
 			<!-- 标签名 -->
 			<name>items</name>
 			<!-- 是否一定需要 -->
 			<required>true</required>
 			<!-- 是否支持EL表达式 -->
 			<rtexprvalue>true</rtexprvalue>
 		</attribute>
 		<attribute>
 			<!-- 标签名 -->
 			<name>var</name>
 			<!-- 是否一定需要 -->
 			<required>true</required>
 			<!-- 是否支持EL表达式 -->
 			<rtexprvalue>false</rtexprvalue>
 		</attribute>	
 	</tag>

jsp页面

 <%
       //保存数据
       //List
     	List<Student>  list = new ArrayList<Student>();
     	list.add(new Student("rose",18));
     	list.add(new Student("jack",28));
     	list.add(new Student("lucy",38));
     	//放入域中
     	pageContext.setAttribute("list",list);
     	
     %>
     
     <c:forEach items="${list}" var="student">
     		姓名:${student.name } - 年龄:${student.age }<br/>
     </c:forEach>

运行结果如图:

技术分享


关于集合的理解

Java SDK不提供直接继承自Collection的类,Java SDK提供的类都是继承自Collection的“子接口”如List和Set。

技术分享

  如何遍历Collection中的每一个元素?不论Collection的实际类型如何,它都支持一个iterator()的方法,该方法返回一个迭代子,使用该迭代子即可逐一访问Collection中每一个元素。典型的用法如下:

       Iterator it = collection.iterator(); // 获得一个迭代子
    while(it.hasNext()) {
      Object obj = it.next(); // 得到下一个元素
    }    

1、如果涉及到堆栈,队列等操作,应该考虑用List,对于需要快速插入,删除元素,应该使用LinkedList,如果需要快速随机访问元素,应该使用ArrayList。

2、尽量返回接口而非实际的类型,如返回List而非ArrayList,这样如果以后需要将ArrayList换成LinkedList时,客户端代码不用改变。

3、如果程序在单线程环境中,或者访问仅仅在一个线程中进行,考虑非同步的类,其效率较高,如果多个线程可能同时操作一个类,应该使用同步的类。

如:List list = Collections.synchronizedList(new LinkedList(...));Vector类本身就是同步的类等

 

自定义标签案例