自定义标签之IterationTag

IterationTag是javax.servlet.jsp.tagext包下的接口,其扩展自Tag接口。IterationTag接口中定义了一个doAfterBody()方法,此方法的作用是可以重复执行BODY中的内容,所谓BODY是指标签中间的内容,比如<a>BODY</a>,先上一张图来看一下此接口的执行流程:

下面上具体的例子:

首先创建一个标签类实现IterationTag接口:

 1 public class TestIterationTag implements IterationTag {
 2     private PageContext pageContext;
 3     private List<String> list;
 4     private String item;
 5     private Iterator<String> it;
 6     //省略GET SET方法
 7 
 8     public int doEndTag() throws JspException {
 9         System.out.println("doEndTag...");
10         return 0;
11     }
12 
13     public int doStartTag() throws JspException {
14         System.out.println("doStartTag...");
15         it = list.iterator();
16         if (it.hasNext()) {
17             pageContext.setAttribute(item, it.next());
18         }
19         return EVAL_BODY_INCLUDE;
20     }
21 
22     public Tag getParent() {
23         return null;
24     }
25 
26     public void release() {
27     }
28 
29     public void setPageContext(PageContext paramPageContext) {
30         this.pageContext = paramPageContext;
31     }
32 
33     public void setParent(Tag paramTag) {
34     }
35 
36     public int doAfterBody() throws JspException {
37         if (it.hasNext()) {
38             pageContext.setAttribute(item, it.next());
39             return (EVAL_BODY_AGAIN);
40         } else {
41             return SKIP_BODY;
42         }
43     }
44 }

然后是JSP文件:

 1 <body>
 2     <%
 3         List<String> list = new ArrayList<String>();
 4         list.add("test01");
 5         list.add("test02");
 6         list.add("test03");
 7         list.add("test04");
 8         list.add("test05");
 9         application.setAttribute("list", list);
10     %>
11     <web:testIteration list = "${list }"  item="item">
12         <%=pageContext.getAttribute("item") %>
13     </web:testIteration>
14 </body>

这个JSP文件中的标签的BODY就是<%=pageContext.getAttribute("item") %>,那么当doStartTag()执行完毕之后,返回的是EVAL_BODY_INCLUDE,所以会先去执行BODY的代码,然后再去执行标签内中的doAfterBody()方法,然后如果doAfterBody()方法返回的是EVAL_BODY_AGAIN,那么继续先执行BODY,再执行doAfterBody(),如果返回的是SKIP_BODY,则跳出循环,去执行doEndTag()。

再上一个JSP被编译后的Java代码片段:

 1 int _jspx_eval_web_005ftestIteration_005f0 = _jspx_th_web_005ftestIteration_005f0.doStartTag();
 2       if (_jspx_eval_web_005ftestIteration_005f0 != javax.servlet.jsp.tagext.Tag.SKIP_BODY) {
 3         do {// 开始循环执行BODY和doAfterBody()方法
 4           out.write("
");
 5           out.write("		");
 6           out.print(pageContext.getAttribute("item") );//执行BODY
 7           out.write('
');
 8           out.write('
');
 9           out.write('    ');
10           int evalDoAfterBody = _jspx_th_web_005ftestIteration_005f0.doAfterBody();
11           if (evalDoAfterBody != javax.servlet.jsp.tagext.BodyTag.EVAL_BODY_AGAIN)//返回EVAL_BODY_AGAIN,继续循环,否则退出循环
12             break;
13         } while (true);
14       }

以上。

原文地址:https://www.cnblogs.com/huashui/p/3745477.html