对jsp自定义标签的理解

    技术2022-07-11  88

    1.创建标签助手类

    1.这个类继承了BodyTagSupport。 2.这个类中我们要实现三个方法,分别是 1)doStartTag(),它有两种返回值分别为 SKIP_BODY:跳过标签体, EVAL_BODY_INCLUDE:运行标签体。 2)doAfterBody(),它有两种返回值分别为 SKIP_BODY:跳过标签体, EVAL_BODY_AGAIN:重新调用本方法。 3)doEndTag(),它有两种返回值分别为 EVAL_PAGE:运行结束标签后续内容, SKIP_PAGE:跳过结束标签后续内容。 现在举一个例子,假设现在有一个类为TestTag,代码如下:

    package com.zking.tag.jsptag; import javax.servlet.jsp.JspException; import javax.servlet.jsp.tagext.BodyTagSupport; public class TestTag extends BodyTagSupport { private int count=0; /** * 标签体运行的时候调用的方法 * 返回值: * 1.SKIP_BODY:跳过标签体 * 2.EVAL_BODY_AGAIN:重新调用本方法 */ @Override public int doAfterBody() throws JspException { System.out.println("<z:test>我在运行的时候会调用的方法</z:test>"); if(count<3) { count++; return EVAL_BODY_AGAIN; } else{ return SKIP_BODY; } } /** * 结束标签运行的时候调用的方法 * 返回值: * 1.EVAL_PAGE:运行结束标签后续内容 * 2.SKIP_PAGE:跳过结束标签后续内容 */ @Override public int doEndTag() throws JspException { System.out.println("结束标签运行起来了"); return EVAL_PAGE; } /** * 当开始标签运行的时候调用这个方法 * 返回值: * 1.SKIP_BODY:跳过标签体 * 2.EVAL_BODY_INCLUDE:运行标签体 */ @Override public int doStartTag() throws JspException { System.out.println("开始标签运行起来了"); return EVAL_BODY_INCLUDE; } }

    2.创建tld文件

    它有五个部分组成,分别是 1)tag 2)name:标签名 3)tag-class:该标签的助手类 4) body-content:它可以是空标签,即empty,也可以是jsp,即jsp文档或者表达式 5)attribute:标签属性。 现在举一个例子,假设现在有一个文件名为mytag.tld,我在里面自定义了一个名字叫test的标签,代码如下:

    <tag> <!-- 标签名 --> <name>test</name> <!-- 标签助手类 --> <tag-class>com.zking.tag.jsptag.TestTag</tag-class> <!-- 标签的内容类型:empty表示空标签,jsp表示可以为任何合法的JSP元素 --> <body-content>jsp</body-content> </tag>

    3.页面引入自定义标签

    例如下面的代码:

    <%@taglib prefix="z" uri="/zking" %>

    4.forEach标签

    首先在mytag.tld里面定义标签和属性,代码如下:

    <tag> <name>forEach</name> <tag-class>com.zking.tag.jsptag.ForEachTag</tag-class> <body-content>jsp</body-content> <attribute> <name>items</name> <required>true</required> <rtexprvalue>true</rtexprvalue> </attribute> <attribute> <name>var</name> <required>true</required> <rtexprvalue>false</rtexprvalue> </attribute> </tag>

    然后再到标签助手类即ForEachTag里面定义两个和tld文件属性名一模一样的属性即items和var,并且写上这两个属性的set和get方法,然后再写三个方法,分别是doAfterBody()、doEndTag()、doStartTag()。代码如下:

    package com.zking.tag.jsptag; import java.util.Iterator; import java.util.List; import javax.servlet.jsp.JspException; import javax.servlet.jsp.tagext.BodyTagSupport; public class ForEachTag extends BodyTagSupport{ //规则1:tld文件中标签有哪些属性,那么助手类必须要有哪些属性 //规则2:标签助手类中属性名必须跟tld文件属性名一模一样 private List<Object> items; private String var; public List<Object> getItems() { return items; } public void setItems(List<Object> items) { this.items = items; } public String getVar() { return var; } public void setVar(String var) { this.var = var; } @Override public int doAfterBody() throws JspException { //取出作用域中后续的值 Iterator<Object> it =(Iterator<Object>) pageContext.getAttribute("it"); //判断是否有值 if(it.hasNext()) { //取值 Object o = it.next(); pageContext.setAttribute(var, o); pageContext.setAttribute("it", it); return EVAL_BODY_AGAIN; } return SKIP_BODY; } @Override public int doEndTag() throws JspException { // TODO Auto-generated method stub return EVAL_PAGE; } @Override public int doStartTag() throws JspException { //只要调用了这个方法,意味着开始标签开始运行了 if(null!=items) { /** * 通过迭代器的方式拿到items里面的值开始操作 */ Iterator<Object> it = items.iterator(); //拿到第一个值 Object o = it.next(); //将这个值以var为键位放入到作用域中 pageContext.setAttribute(var, o); pageContext.setAttribute("it", it); return EVAL_BODY_INCLUDE; } return SKIP_BODY; } }

    最后在到自己写的jsp文件里面去循环取值,这里我举个例子,现在有一个jsp页面名字叫admin.jsp,在这里循环输出自己定义的集合里面的值,代码如下:

    <%@page import="java.util.ArrayList"%> <%@page import="java.util.List"%> <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib prefix="z" uri="/zking" %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> </head> <body> <% List<String> list=new ArrayList(); for(int i=0;i<20;i++){ list.add("zs"+i); } session.setAttribute("list", list); %> <z:forEach items="${list }" var="a"> ${a }<br/> </z:forEach> </body> </html>
    Processed: 0.010, SQL: 9