• 1.4(学习笔记)JSP自定义标签


    一、JSP自定义标签

       JSP自定义标签,可以通过实现Tag接口、继承TagSupport类来设置标签功能。

      后续通过配置文件将标签和具体的实现类关联。

    二、自定义第一个标签(实现Tag接口)

      自定义标签需要先创建一个Java类,然后实现Tge接口或者继承S.....类

      我们先来看实现接口这种方法自定义标签:

      2.1创建Java类

    HelloTag.java

    import java.io.IOException;
    
    import javax.servlet.jsp.JspException;
    import javax.servlet.jsp.JspWriter;
    import javax.servlet.jsp.PageContext;
    import javax.servlet.jsp.tagext.Tag;
    
    public class HelloTag implements Tag {
        
        private PageContext pageContext;
        
        @Override
        public int doEndTag() throws JspException {
            // TODO Auto-generated method stub
            System.out.println("endTag");
            return EVAL_PAGE;//继续显示该标签后续内容
        }
    
        @Override
        public int doStartTag() throws JspException {
            // TODO Auto-generated method stub
            String msg = "MyTag";
            JspWriter out = pageContext.getOut();
            try {
                out.println(msg);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println("startTag");
            return EVAL_BODY_INCLUDE;//显示标签体中的内容
        }
    
        @Override
        public Tag getParent() {
            // TODO Auto-generated method stub
            return null;
        }
    
        @Override
        public void release() {
            // TODO Auto-generated method stub
        }
    
        @Override
        public void setPageContext(PageContext pageContext) {
            // TODO Auto-generated method stub
            //获取JSP页面的pageContext
            this.pageContext = pageContext;
            System.out.println("pageContext");
        }
    
        @Override
        public void setParent(Tag arg0) {
            // TODO Auto-generated method stub
        }
        
    }

      2.2创建好java类后,需要创建配置文件

        2.2.1创建my_tag_config.tld文件

        在WEB-INF文件夹下新建XML文件。

        

        

         将.xml改为.tld(结果如下图所示)

         

        点击next,进入如下页面。(结果如下图所示)

        

        点击next(结果如下图所示)

        

        点击next,(效果如下图所示)

        

        点击finish,创建结束。

        打开创建好的文件,效果如下图所示。

        

        接着我们就要对其进行配置,将标签和我们创建的类关联。

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd" >
    <taglib>
      <tlib-version>1.0</tlib-version>
      <jsp-version>1.2</jsp-version>
      <short-name>short-name</short-name>
      
      <!-- 此处的uri只是一个标识,可任意指定,后续JSP页面中引用时保持一致即可 -->
      <uri>http://www.myTag.com</uri>
      
      <tag>
        <name>hello</name>   <!-- 设置标签名 -->
        <tag-class>com.myTag.HelloTag</tag-class>  <!-- 设置标签名关联类 -->
        <body-content>JSP</body-content> <!-- 指定标签体显示格式 -->
      </tag>
    </taglib>

    其中<body-content>中的属性有四种:

    tagdependent,empty,JSP,

    各个属性的含义可参阅:https://www.cnblogs.com/keyi/p/7127685.html

    以上都配置好了后,我们就来使用标签。

    tag.jsp  

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    
    <!-- 指定需要使用标签的URi和前缀 -->
    <%@ taglib uri="http://www.myTag.com" prefix = "m" %>
    
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
        <m:hello>include body</m:hello>
    </body>
    </html>

    自定义标签的功能是输出“MyTag”,结果正常输出。

    我们来看下控制台的输出:

    最后我们分析下标签的执行流程

    我们看下tag.jsp生存的servlet中的代码:

    Servlet中调用了一个方法,我们来看下这个方法

    查看代码可以很清楚的看到自定义标签的执行流程。

     三、自定义out标签(继承TagSupport类实现)

    java类

    import java.io.IOException;
    
    import javax.servlet.jsp.JspException;
    import javax.servlet.jsp.JspWriter;
    import javax.servlet.jsp.PageContext;
    import javax.servlet.jsp.tagext.TagSupport;
    
    public class HelloTagEx extends TagSupport {
        private String value;
        private JspWriter out;
        
        public void setValue(String value) {//设置值
            this.value = value;
        }
    
        @Override
        public int doStartTag() throws JspException {
            // TODO Auto-generated method stub
         //不重写setPageContext方法,也可直接使用pageContext
         // 例如: this.out = pageContext.getOut();
    try { out.println(value); //将设置的value输出 } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return SKIP_BODY;//不输出标签体中内容 } @Override public int doEndTag() throws JspException { // TODO Auto-generated method stub return SKIP_PAGE;//不输出界面后续内容 } @Override public int doAfterBody() throws JspException { // TODO Auto-generated method stub return super.doAfterBody(); } @Override //此方法也可以不重写,在doStartTag、doEndTag中可以直接使用pageContext
             
    public void setPageContext(PageContext pageContext) { this.pageContext = pageContext; this.out = pageContext.getOut(); } }

    标签配置:

    <tag>
              <name>helloEx</name>
              <tag-class>com.myTag.HelloTagEx</tag-class>
             <body-content>JSP</body-content>  
             
              <attribute>
                  <name>value</name>  <!-- 属性名要和类中属性名对应 -->
                  <required>true</required>      <!-- 该属性是否为必填项 true 代表为必填,不填会报错 -->
                  <rtexprvalue>true</rtexprvalue> <!-- 能否使用表达式赋值  true表示可以用表达式-->
              </attribute>
        </tag>

    tag.jsp

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    
    <!-- 指定需要使用标签的URi和前缀 -->
    <%@ taglib uri="http://www.myTag.com" prefix = "m" %>
    
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
        <m:helloEx value="123">ss</m:helloEx>
        endTag方法返回值是SKIP_PAGE,不输出后续界面,所以这句话不会输出。
    </body>
    </html>

    四、自定义if标签

     有了前面两个作为基础,后面的就很简单了。

    标签类

    import javax.servlet.jsp.JspException;
    import javax.servlet.jsp.tagext.TagSupport;
    
    public class IF extends TagSupport{
        private boolean flag;
        
        public void setFlag(boolean flag) {
            this.flag = flag;
        }
        
        @Override
        public int doStartTag() throws JspException {
            // TODO Auto-generated method stub
            if(flag == true) {//如果为true,标签体中内容执行,反正不执行。
                return EVAL_BODY_INCLUDE;
            }else {
                return SKIP_BODY;
            }
        }
        
        @Override
        public int doEndTag() throws JspException {
            // TODO Auto-generated method stub
            return EVAL_PAGE;//IF标签结束后,继续执行页面内容
        }
        
        
    }

    配置:

    <tag>
              <name>IF</name>
              <tag-class>com.myTag.IF</tag-class>
             <body-content>JSP</body-content>  
             
              <attribute>
                  <name>flag</name>  <!-- 属性名要和类中属性名对应 -->
                  <required>true</required>      <!-- 该属性是否为必填项 true 代表为必填,不填会报错 -->
                  <rtexprvalue>true</rtexprvalue> <!-- 能否使用表达式赋值  true表示可以用表达式-->
              </attribute>
        </tag>

    tag.jsp

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    
    <!-- 指定需要使用标签的URi和前缀 -->
    <%@ taglib uri="http://www.myTag.com" prefix = "m" %>
    
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
        <m:IF flag="${3>2}">
            true
        </m:IF>
    </body>
    </html>

     

    五、自定义foreach标签

    标签类:ForEach.java

    import java.util.Iterator;
    import java.util.List;
    
    import javax.servlet.jsp.JspException;
    import javax.servlet.jsp.tagext.TagSupport;
    
    public class ForEach extends TagSupport {
        
        private List<String> list;
        private String var;
    
        public void setList(List<String> list) {
            this.list = list;
        }
        
        public void setVar(String var) {
            this.var = var;
        }
        
        @Override
        public int doStartTag() throws JspException {
            // TODO Auto-generated method stub
            if(list == null) {
                return SKIP_BODY;
            }else {
                Iterator<String> items = list.iterator(); 
                pageContext.setAttribute("ite", items);
                pageContext.setAttribute("list", list);
                //由于doStartTage方法结束后是输出标签体,
                //而标签体中有${var}表达式用于输出迭代对象
                //所以此处最好先拿出一个对象。
                if(items.hasNext()) {//如果迭代器中有元素,设置值,并输出标签体
                    pageContext.setAttribute(var, items.next());
                    return EVAL_BODY_INCLUDE;
                }else {//反之则不输出标签体
                    return SKIP_BODY;
                }
                
            }
        }
        
        @Override
        public int doAfterBody() throws JspException {
            // TODO Auto-generated method stub
            //获取迭代器
            Iterator<String> items = (Iterator<String>)pageContext.getAttribute("ite");
            if(items.hasNext()) {//将其中元素取出,并设置。
                String value = (String) items.next();
                pageContext.setAttribute(var, value);
                return EVAL_BODY_AGAIN; //再一次执行标签体
            }else {
                return SKIP_BODY; //迭代器为空,则停止输出标签体
            }
        }
        
        @Override
        public int doEndTag() throws JspException {//结束标签后的内容继续输出
            // TODO Auto-generated method stub
            return EVAL_PAGE;
        }
    }

    配置:

    <tag>
              <name>FOREACH</name>
              <tag-class>com.myTag.ForEach</tag-class>
             <body-content>JSP</body-content>  
             
             <attribute>
                  <name>var</name>  <!-- 属性名要和类中属性名对应 -->
                  <required>true</required>      <!-- 该属性是否为必填项 true 代表为必填,不填会报错 -->
                  <rtexprvalue>false</rtexprvalue> <!-- 能否使用表达式赋值  false表示不可以用表达式-->
              </attribute>
             
              <attribute>
                  <name>list</name>  <!-- 属性名要和类中属性名对应 -->
                  <required>true</required>      <!-- 该属性是否为必填项 true 代表为必填,不填会报错 -->
                  <rtexprvalue>true</rtexprvalue> <!-- 能否使用表达式赋值  true表示可以用表达式-->
              </attribute>
              
        </tag>

    tag.jsp

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <%@ page import = "java.util.*" %>
    <!-- 指定需要使用标签的URi和前缀 -->
    <%@ taglib uri="http://www.myTag.com" prefix = "m" %>
    
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
    
        <%
            List<String> list = new ArrayList<String>();
            for(int i = 0; i < 5 ; i++){
                list.add("str" + i);
            }
            pageContext.setAttribute("list", list);
        %>    
        <m:FOREACH list="${list}" var="s">
            ${s}
        </m:FOREACH>
    </body>
    </html>

    foreach主要通过表达式将list对象传递到ForEach.java中,

    在ForEach.java中主要通过doAfterBody()方法,将迭代器中元素

    通过pageSetAttribute()设置到page中,然后输出${var},输出的表达式又会自动获取设置的值,

    然后往复输出执行doAfterBody()方法,并且输出标签体(表达式${var}),来实现foreach。

    直到迭代器元素全部输出,方法才终止。

    那个doAfterBody()和return EVAL_BODY_AGAIN配合的流程可能不太好理解,

    我们来看下tag.jsp生成的Servlet中的代码就很好理解了。

     执行顺序为(不考虑后续输出终止情况):

    doStartTag->标签体内容->doAfterBody->doEndTag

     <xx>  标签开始(doStartTag)

       xxxxxx   标签体

      doAfterBody判断是否继续输出标签体(doAfterBody方法也可看作标签体的一部分)

     </xx>  标签结束(doEndTag)

    参考资料: 

    https://blog.csdn.net/qq_42246139/article/details/80623607

    https://blog.csdn.net/qq_41815326/article/details/81356733  

  • 相关阅读:
    SpringCloud(9) ------>微服务应用监控
    SpringCloud(8) ------>Sleuth链路跟踪
    SpringCloud(7) ------>Config配置中心与消息总线
    java.lang.IllegalStateException: Failed to load property source from 'file:/E:/liangd/Java/cloud/user/target/classes/bootstrap.yml' (classpath:/bootstrap.yml)
    SpringCloud(6) ------>Zuul网关配置
    SpringCloud(5) ------>Openfeign声明式服务调用接口与服务降级
    SpringCloud(4) ------>自定义负载均衡策略配置
    SpringCloud(3) ------>RestTemplate调用接口示例
    SpringCloud(2) ------>Ribbon负载均衡策略配置
    SpringCloud(1) ------>搭建一个SpringCloud项目
  • 原文地址:https://www.cnblogs.com/huang-changfan/p/10341557.html
Copyright © 2020-2023  润新知