自定义标签实现(out,if,forEach,dept,select)

目录

1.自定义out标签

2.自定义if标签

3.自定义forEach标签

4.自定义dept数据标签

5.自定义select下拉框标签


在上篇给大家介绍了自定义标签的使用步骤,这篇我们来使用自定义标签

1.自定义out标签

<c:out value=""/>

out标签是空标签,有value属性,创建OutTag标签助手类,定义属性value

package com.zking.tag;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.BodyTagSupport;
import java.io.IOException;

/**
 * 自定义out标签
 */
public class OutTag extends BodyTagSupport {

    private Object value;

    public Object getValue() {
        return value;
    }

    public void setValue(Object value) {
        this.value = value;
    }

    @Override
    public int doStartTag() throws JspException {
        
        JspWriter out = pageContext.getOut();
        try {
            out.write(value.toString());
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return SKIP_BODY;
    }

    @Override
    public int doEndTag() throws JspException {
        return EVAL_PAGE;
    }
}

在 mytag.tld标签描述文件中定义out输出标签及属性信息

<tag>
		<!-- 标签名 -->
		<name>out</name>
		<!-- 标签工具类 -->
		<!--Class.forName(com.zking.tag.TestTag)
		ClASSNotFoundException异常
		-->
		<tag-class>com.zking.tag.OutTag</tag-class>
		<!-- 标签的内容类型:empty表示空标签,jsp表示可以为任何合法的JSP元素 -->
		<body-content>empty</body-content>
		<!-- 自定义标签的属性定义,请注意一定要在标签类中提供对应的get/set方法 -->
		<attribute>
			<!-- 自定义标签的属性名称 -->
			<name>value</name>
			<!-- true表示必填 -->
			<required>true</required>
			<!-- true支持动态值,可以向值里面填jsp表达式、EL表达式,false则不支持 -->
			<rtexprvalue>true</rtexprvalue>
		</attribute>
	</tag>

在指定jsp界面应用自定义out标签

<h2>自定义out标签</h2>
<z:out value="${name}"/>

2.自定义if标签

if是标准标签,有test属性,创建ifTag标签助手类,定义属性text

package com.zking.tag;

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

public class IfTag extends BodyTagSupport {

    //定义if标签的条件判断属性test
    private boolean test;

    public boolean isTest() {
        return test;
    }

    public void setTest(boolean test) {
        this.test = test;
    }

    @Override
    public int doStartTag() throws JspException {
        if(this.test)
            return EVAL_BODY_INCLUDE;
        else
            return SKIP_BODY;
    }

    @Override
    public int doEndTag() throws JspException {
        return EVAL_PAGE;
    }
}

在mytag.tld标签描述文件中定义if判断标签及属性信息

<tag>
		<!-- 标签名 -->
		<name>if</name>
		<!-- 标签工具类 -->
		<!--Class.forName(com.zking.tag.TestTag)
		ClASSNotFoundException异常
		-->
		<tag-class>com.zking.tag.IfTag</tag-class>
		<!-- 标签的内容类型:empty表示空标签,jsp表示可以为任何合法的JSP元素 -->
		<body-content>jsp</body-content>
		<!-- 自定义标签的属性定义,请注意一定要在标签类中提供对应的get/set方法 -->
		<attribute>
			<!-- 自定义标签的属性名称 -->
			<name>test</name>
			<!-- true表示必填 -->
			<required>true</required>
			<!-- true支持动态值,可以向值里面填jsp表达式、EL表达式,false则不支持 -->
			<rtexprvalue>true</rtexprvalue>
		</attribute>
	</tag>

在指定jsp界面应用自定义if标签

<z:if test="${name eq 'hhh'}">
        今天也很棒

    </z:if>

3.自定义forEach标签

forEach是标准标签,有属性var和items,创建forEachTag标签助手类,定义属性var和items

package com.zking.tag;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.BodyTagSupport;
import java.util.Iterator;
import java.util.List;

public class ForEachTag extends BodyTagSupport {

    //循环遍历的变量名
    //将每次循环遍历的结果保存到作用域俄中,并以var属性命名
    //request.setAttribute(var,循环变量的值)
    private String var;

    //循环遍历的集合
    private List items;


    public String getVar() {
        return var;
    }

    public void setVar(String var) {
        this.var = var;
    }

    public List getItems() {
        return items;
    }

    public void setItems(List items) {
        this.items = items;
    }

    @Override
    public int doStartTag() throws JspException {
        if(null!=items && items.size()>0){
            //获取items的迭代器对象
            Iterator it = items.iterator();
            //通过next方法移动下标并取出元素
            Object value = it.next();
            //把当前取出的元素保存到pageContext作用域,并以var属性来命名
            //四大作用域:page/request/session/application
            pageContext.setAttribute(var,value);
            //将没有遍历完成的it迭代器对象保存到page作用域,留到doAfterBody中再次判断是否继续执行
            pageContext.setAttribute("it",it);
            return EVAL_BODY_INCLUDE;

        }
        return SKIP_BODY;
    }

    @Override
    public int doAfterBody() throws JspException {
        //将page作用域中未遍历完的it迭代器对象去出来
        Iterator it = (Iterator)pageContext.getAttribute("it");
        //判断it迭代器对象中的下一个元素是否存在
        if(it.hasNext()){
            //通过next方法移动下标并取出元素
            Object value = it.next();
            //将取出的元素保存到pageContext作用域,并以var属性来命名
            pageContext.setAttribute(var,value);
            //将没有遍历完成的it迭代器对象保存到page作用域,留到doAfterBody中再次判断是否继续执行
            pageContext.setAttribute("it",it);
            return EVAL_BODY_AGAIN;

        }
        return SKIP_BODY;
    }

    @Override
    public int doEndTag() throws JspException {
        return EVAL_PAGE;
    }
}

在mytag.tld标签描述文件中定义forEach循环标签及属性信息

<tag>
		<!-- 标签名 -->
		<name>forEach</name>
		<!-- 标签工具类 -->
		<!--Class.forName(com.zking.tag.TestTag)
		ClASSNotFoundException异常
		-->
		<tag-class>com.zking.tag.ForEachTag</tag-class>
		<!-- 标签的内容类型:empty表示空标签,jsp表示可以为任何合法的JSP元素 -->
		<body-content>jsp</body-content>
		<!-- 自定义标签的属性定义,请注意一定要在标签类中提供对应的get/set方法 -->
		<attribute>
			<!-- 自定义标签的属性名称 -->
			<name>var</name>
			<!-- true表示必填 -->
			<required>true</required>
			<!-- true支持动态值,可以向值里面填jsp表达式、EL表达式,false则不支持 -->
			<rtexprvalue>false</rtexprvalue>
		</attribute>
		<attribute>
			<!-- 自定义标签的属性名称 -->
			<name>items</name>
			<!-- true表示必填 -->
			<required>true</required>
			<!-- true支持动态值,可以向值里面填jsp表达式、EL表达式,false则不支持 -->
			<rtexprvalue>true</rtexprvalue>
		</attribute>
	</tag>

在指定jsp界面应用自定义forEach标签

 <h2>自定义forEach标签</h2>
    <z:forEach items="${names}" var="n">
        你是${n}
    </z:forEach>

4.自定义dept数据标签

创建DeptTag标签助手类,定义属性var和scope,并在mytag.tld标签描述文件中定义DeptTag标签及属性信息

package com.zking.tag;

import com.zking.dao.StudentDao;
import com.zking.entity.Student;

import javax.servlet.ServletContext;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpSession;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.BodyTagSupport;
import java.util.List;

public class DeptTag extends BodyTagSupport {

    private String var;

    private String scope;

    public String getVar() {
        return var;
    }

    public void setVar(String var) {
        this.var = var;
    }

    public String getScope() {
        return scope;
    }

    public void setScope(String scope) {
        this.scope = scope;
    }

    @Override
    public int doStartTag() throws JspException {
        //调用Dao层代码从数据库中获取部门数据
        List<Student> lst = new StudentDao().getLike();

        if(null==scope || scope.equalsIgnoreCase("page")){
            pageContext.setAttribute(var,lst);
        }else if(scope.equalsIgnoreCase("request")){
            ServletRequest request = pageContext.getRequest();
            request.setAttribute(var,lst);
        }else if(scope.equalsIgnoreCase("session")){
            HttpSession session = pageContext.getSession();
            session.setAttribute(var,lst);
        }else if(scope.equalsIgnoreCase("application")){
            ServletContext application = pageContext.getServletContext();
            application.setAttribute(var,lst);
        }else{
            pageContext.setAttribute(var,lst);
        }


        return SKIP_BODY;
    }

    @Override
    public int doEndTag() throws JspException {
        return EVAL_PAGE;
    }
}
<tag>
		<!-- 标签名 -->
		<name>dept</name>
		<!-- 标签工具类 -->
		<!--Class.forName(com.zking.tag.TestTag)
		ClASSNotFoundException异常
		-->
		<tag-class>com.zking.tag.DeptTag</tag-class>
		<!-- 标签的内容类型:empty表示空标签,jsp表示可以为任何合法的JSP元素 -->
		<body-content>empty</body-content>
		<!-- 自定义标签的属性定义,请注意一定要在标签类中提供对应的get/set方法 -->
		<attribute>
			<!-- 自定义标签的属性名称 -->
			<name>scope</name>
			<!-- true表示必填 -->
			<required>false</required>
			<!-- true支持动态值,可以向值里面填jsp表达式、EL表达式,false则不支持 -->
			<rtexprvalue>false</rtexprvalue>
		</attribute>
		<attribute>
			<!-- 自定义标签的属性名称 -->
			<name>var</name>
			<!-- true表示必填 -->
			<required>true</required>
			<!-- true支持动态值,可以向值里面填jsp表达式、EL表达式,false则不支持 -->
			<rtexprvalue>false</rtexprvalue>
		</attribute>
	</tag>

5.自定义select下拉框标签

创建SelectTag标签助手类,定义相关属性,并在mytag.tld标签描述文件中定义SelectTag标签及属性信息

package com.zking.tag;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.BodyTagSupport;
import java.lang.reflect.Field;

import java.util.List;

public class SelectTag extends BodyTagSupport {

    //设置select中option的值
    private String value;
    //设置select中option的显示文本
    private String text;

    //数据源
    private List<Object> items;

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }

    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }

    public List<Object> getItems() {
        return items;
    }

    public void setItems(List<Object> items) {
        this.items = items;
    }

    @Override
    public int doStartTag() throws JspException {
        JspWriter out = pageContext.getOut();
        try {
            out.print(toHtml());
        }catch (Exception e){
            e.printStackTrace();
        }
        return SKIP_BODY;
    }

    private String toHtml() throws NoSuchFieldException {
            //创建Stringbuffer
            StringBuffer sb=new StringBuffer();

            //拼接select标签(开始标签)
            sb.append("<select>");
            for (Object object : items) {
                //反射获取对象中的属性
                //获取Student对象中id属性的值
                Object optionValue=this.getObjValue(value,object);
                //获取Student对象中nmae属性的值
                Object optionText = this.getObjValue(text, object);

                //拼接option标签
                sb.append("<option value='"+optionValue+"'>"+optionText+"</option>");
            }
            //拼接select标签(开始标签)
            sb.append("</select>");
            return sb.toString();
    }

    /**
     *获取对象中属性的值
     * @param fieldName 获取对象中的哪一个属性值的属性名
     * @param obj 获取属性的对象(Student)
     * @return
     */
    private Object getObjValue(String fieldName,Object obj) throws NoSuchFieldException {
        Object val=null;
        try {
            //获取类对象
            Class cls = obj.getClass();

            //获取对象中的属性
            Field[] fields = cls.getDeclaredFields();

            //循环遍历属性
            for (Field field : fields) {
                //判断循环遍历的属性名与传入的参数属性名是否一致
                if(field.getName().toUpperCase().equals(fieldName.toUpperCase())){
                    field.setAccessible(true);
                    //获取属性的值
                    val=field.get(obj);
                    break;
                }
            }

        }catch (Exception e){
            e.printStackTrace();
        }
        return val;

    }

    @Override
    public int doEndTag() throws JspException {
        return EVAL_PAGE;
    }
}
<tag>
		<!-- 标签名 -->
		<name>select</name>
		<!-- 标签工具类 -->
		<!--Class.forName(com.zking.tag.TestTag)
		ClASSNotFoundException异常
		-->
		<tag-class>com.zking.tag.SelectTag</tag-class>
		<!-- 标签的内容类型:empty表示空标签,jsp表示可以为任何合法的JSP元素 -->
		<body-content>empty</body-content>
		<!-- 自定义标签的属性定义,请注意一定要在标签类中提供对应的get/set方法 -->
		<attribute>
			<!-- 自定义标签的属性名称 -->
			<name>value</name>
			<!-- true表示必填 -->
			<required>true</required>
			<!-- true支持动态值,可以向值里面填jsp表达式、EL表达式,false则不支持 -->
			<rtexprvalue>false</rtexprvalue>
		</attribute>
		<attribute>
			<!-- 自定义标签的属性名称 -->
			<name>text</name>
			<!-- true表示必填 -->
			<required>true</required>
			<!-- true支持动态值,可以向值里面填jsp表达式、EL表达式,false则不支持 -->
			<rtexprvalue>false</rtexprvalue>
		</attribute>
		<attribute>
			<!-- 自定义标签的属性名称 -->
			<name>items</name>
			<!-- true表示必填 -->
			<required>true</required>
			<!-- true支持动态值,可以向值里面填jsp表达式、EL表达式,false则不支持 -->
			<rtexprvalue>true</rtexprvalue>
		</attribute>
	</tag>

最后是jsp页面自定义标签引用

<%@ page import="java.util.Arrays" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@taglib prefix="z" uri="/zking"%>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <%
        request.setAttribute("name","hhh");
        String[] names={"hh","aa","cc"};
        request.setAttribute("names", Arrays.asList(names));
    %>

    <h2>自定义test标签</h2>
    <z:test name="${name}">123</z:test>
    <h2>自定义out标签</h2>
    <z:out value="${name}"/>
    <c:out value=""/>
    <h2>自定义if标签</h2>
    <z:if test="${name eq 'hhh'}">
        今天也很棒

    </z:if>

    <h2>自定义forEach标签</h2>
    <z:forEach items="${names}" var="n">
        你是${n}
    </z:forEach>

    <h2>自定义dept标签</h2>
    <z:dept var="depts" scope="request"/>
    ${pageScope.depts}
    <z:forEach items="${requestScope.depts}" var="d">
        编号=${d.getId()} , 姓名=${d.getName()}<br>
    </z:forEach>

    <h2>自定义select标签</h2>
    <z:select value="id" text="name" items="${depts}"/>




</body>
</html>

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值