最近公司跟别的公司合作天发一个项目,用到了那家公司自己开发的一套开发框架,其中包括了很多自定义标签很是方便,其中也有迭代标签,很方便。之前没有玩过自定义标签,于是在网上找了一些这方面的资料,了解了解其中的原理。然后自己写了一个简单的迭代标签。其中包括两个标签Collection、CollectionItem,都继承了BodyTagSupport。代码如下:
tld文件
<?xml version="1.0" encoding="UTF-8"?>
<taglib version="2.1" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd">
<tlib-version>1.0</tlib-version>
<short-name>mytag</short-name>
<uri>/WEB-INF/tlds/mytag</uri>
<tag>
<name>collection</name>
<tag-class>com.jquery.mytags.Collection</tag-class>
<body-content>jsp</body-content>
<attribute>
<name>dataSource</name>
<required>true</required>
</attribute>
</tag>
<tag>
<name>collectionItom</name>
<tag-class>com.jquery.mytags.CollectionItem</tag-class>
<body-content>empty</body-content>
<attribute>
<name>property</name>
<required>true</required>
</attribute>
<attribute>
<name>title</name>
<required>false</required>
</attribute>
</tag>
</taglib>
web.xml中加入以下代码
<jsp-config>
<taglib>
<taglib-uri>/WEB-INF/tlds/mytag</taglib-uri>
<taglib-location>/WEB-INF/mytld/jquery-helloworld.tld</taglib-location>
</taglib>
</jsp-config>
Collection处理代码
import java.io.IOException;
import java.util.Iterator;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.BodyContent;
import javax.servlet.jsp.tagext.BodyTagSupport;
public class Collection extends BodyTagSupport {
/**
*
*/
private static final long serialVersionUID = 1L;
private PageContext pageContext;
private String dataSource;// 数据源名称
@SuppressWarnings("unchecked")
private Iterator iter;
public String getDataSource() {
return dataSource;
}
public void setDataSource(String dataSource) {
this.dataSource = dataSource;
}
public Collection() {
super();
}
public int doAfterBody() throws JspException {
if(iter.hasNext()){
try {
pageContext.getOut().print("</tr>");
pageContext.setAttribute(dataSource,iter.next());
} catch (IOException e) {
e.printStackTrace();
}
return EVAL_BODY_AGAIN;//表示循环处理标签体
}
return SKIP_BODY;
}
public int doEndTag() throws JspException {
try {
pageContext.getOut().print("</table>");
} catch (IOException e) {
e.printStackTrace();
}
return EVAL_PAGE;
}
@SuppressWarnings("unchecked")
public int doStartTag() throws JspException {
java.util.Collection coll = (java.util.Collection) pageContext.findAttribute(dataSource);
// 表示如果未找到指定集合,则不用处理标签体,直接调用doEndTag()方法。
if (coll == null || coll.isEmpty())
return SKIP_BODY;
try {
pageContext.getOut().print("<table><tr>");
} catch (IOException e) {
e.printStackTrace();
}
iter = coll.iterator();
pageContext.setAttribute(dataSource,"setHeader");//处理列表表头
// 这里一定要返回EVAL_BODY_INCLUDE,否则标签体的内容不会在网页上输出显示
return EVAL_BODY_INCLUDE;
}
public void release() {
}
public void setPageContext(PageContext arg0) {
pageContext = arg0;
}
// 在doInitBody方法之前执行,在这里被绕过不执行
public void setBodyContent(BodyContent arg0) {
System.out.println("setBodyContent...");
super.setBodyContent(arg0);
}
// 此方法被绕过不会被执行
public void doInitBody() throws JspException {
System.out.println("doInitBody...");
super.doInitBody();
}
}
CollectionItem处理代码
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspTagException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.BodyTagSupport;
import javax.servlet.jsp.tagext.Tag;
public class CollectionItem extends BodyTagSupport {
/**
*
*/
private static final long serialVersionUID = 2093044170883495102L;
private PageContext pageContext;
private Tag parent;
private String property;//打印字段名
private String width;//列宽
private String title;//标题
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getProperty() {
return property;
}
public void setProperty(String property) {
this.property = property;
}
public String getWidth() {
return width;
}
public void setWidth(String width) {
this.width = width;
}
public CollectionItem() {
super();
}
public int doEndTag() throws JspException {
return EVAL_PAGE;
}
@SuppressWarnings("unchecked")
public int doStartTag() throws JspException {
try {
String dataSourceName = ((Collection)parent).getDataSource();
Object objItem = pageContext.getAttribute(dataSourceName);
if (objItem == null) return SKIP_BODY;
//判断是否是打印表头
if(objItem.toString()=="setHeader"){
String itemTile = title==null?property:title;//如果没写标题,刚表头显示为该列的字段名
pageContext.getOut().write("<td>"+itemTile+"</td>");
return SKIP_BODY;
}
Class cItem = objItem.getClass();
String itemStr = "";
Method method;
if(cItem==Map.class||cItem==HashMap.class||cItem==Hashtable.class){
method = cItem.getMethod("get",Object.class);
itemStr = (String) method.invoke(objItem,property);
}
else{
String getMethodNao = "get"+property.substring(0,1).toUpperCase()+property.substring(1);
method = cItem.getMethod(getMethodNao);
itemStr = (String) method.invoke(objItem);
}
String result="<td>"+itemStr;
result +="</td>";
pageContext.getOut().write(result);
} catch (Exception e) {
throw new JspTagException("IO Error: " + e.getMessage());
}
return SKIP_BODY;
}
public Tag getParent() {
return parent;
}
public void release() {
}
public void setPageContext(PageContext arg0) {
this.pageContext = arg0;
}
public void setParent(Tag arg0) {
parent = arg0;
}
}
doStartTag()和doEndTag()、doAfterBody()方法的返回值说明:
SKIP_BODY 表示不用处理标签体,直接调用doEndTag()方法。
SKIP_PAGE 忽略标签后面的jsp内容。
EVAL_PAGE 处理标签后,继续处理jsp后面的内容。
EVAL_BODY_BUFFERED 表示需要处理标签体,且需要重新创建一个缓冲(调用setBodyContent方法)。
EVAL_BODY_INCLUDE 表示在现有的输出流对象中处理标签体,但绕过setBodyContent()和doInitBody()方法
EVAL_BODY_AGAIN 对标签体循环处理。(存在于javax.servlet.jsp.tagext.IterationTag接口中)
Jsp应用代码
<%@ page language="java" contentType="text/html; charset=GBK"
pageEncoding="GBK"%>
<%@taglib uri="/WEB-INF/tlds/mytag" prefix="hello" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=GBK">
<title>Insert title here</title>
<script type="text/javascript" src="../js/jquery-1.3.1.js"></script>
<script type="text/javascript">
$(document).ready(function(){
window.location.href = "../collectionSource.do";
});
</script>
</head>
<body>
<hello:collection dataSource="userList">
<hello:collectionItom property="userName" title="用户名"/>
<hello:collectionItom property="address" title="地址"/>
</hello:collection>
</body>
</html>
Action代码
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) {
Person p1 = new Person();
Person p2 = new Person();
Map p3 = new HashMap();
p1.setUserId(1111);
p1.setAddress("北京");
p1.setAge(25);
p1.setPassWord("12345");
p1.setUserName("张三");
p2.setUserId(1111);
p2.setAddress("上海");
p2.setAge(25);
p2.setPassWord("12345");
p2.setUserName("李四");
p3.put("address", "广州");
p3.put("age", 30);
p3.put("passWord", "12345");
p3.put("userName", "王五");
ArrayList arr = new ArrayList();
arr.add(p1);
arr.add(p2);
arr.add(p3);
request.setAttribute("userList", arr);
return mapping.findForward("jspView");
}