JavaWeb了解之入门篇2-1(JSP自定义标签)开发标签库

目录
  1. 自定义标签
  2. 开发标签库

自定义标签:旨在移除JSP页面中的Java代码。

1. 自定义标签

优点:
  1. 减少JSP页面对JSP脚本的需求和依赖。
  2. 将JSP页面和业务逻辑分离(增强可维护性、可重用性)。

使用步骤:
  1. 创建自定义标签类(实现相关接口、类)。
  2. 创建.tld标签库描述文件(.tld文件通常位于WEB-INF目录下)。
    用来将类映射成JSP标签。采用XML文件格式进行描述,后缀名为.tld。
    1. 标签(配置 标签库的信息)  只能有一个
      常用子标签
        1. tlib-version     
          标签库的版本号。
        2. jsp-version  
          标签库使用的JSP版本号。
        3. short-name   
          标签库的前缀。
        4. uri  
          标签库的uri地址。
        5. 标签(可以有多个)
          每个tag标签代表一个自定义标签。
    2. 标签(配置 自定义标签的信息)
      常用子标签:
        1. name(必填)     
          自定义标签的名称。
        2. tag-class(必填)    
          自定义标签的实现类路径。
        3. description  
          自定义标签的功能描述。
        4. attribute    
          自定义标签的属性(可以有多个)。
        5. body-content
          1. empty
            没有标签体
          2. JSP
            有标签体(可以是任意内容)不符合避免出现Java代码的初衷。
          3. tagdependent
            标签体的内容由标签类自己处理(很少使用)
            如:SELECT * FROM USER中的SQL语句就是给标签类使用的。
          4. scriptless    
            标签体的内容不允许是JSP脚本。
        【存疑】在简单标签中标签体body-content的值只允许是empty和scriptless、tagdependent,不允许设置成JSP否则异常。
        【存疑】在传统标签中标签体body-content的值4个类型都可以。
        6. variable
          自定义标签的变量属性。
    3. 标签(用来定义标签中的属性)注意子标签顺序
      常用子标签:
        1. name(必填)     
          属性名称。
        2. description  
          属性描述。
        3. required     
          属性是否是必须的(默认值:false)
        4. rtexprvalue  
          属性值是否支持JSP表达式
        5. type     
          属性的 Java 类型(默认值:String)
        6. fragment     
          如果声明了该属性,属性值将被视为一个JspFragment。
    4.  标签(用来定义标签中的变量属性)
      常用子标签:
        1. declare  
          变量声明
        2. description  
          变量描述
        3. name-from-attribute  
          指定的属性名称,其值为变量,在调用JSP页面时可以使用的名字
        4. name-given   
          变量名(标签使用时的变量名)
        5. scope    
          变量的作用范围,有3个值:
          1. NESTED 开始和结束标签之间
          2. AT_BEGIN 从开始标签到页面结束
          3. AT_END 从结束标签之后到页面结束
        6. variable-class   
          变量的Java类型(默认值:String)
  3. 在jsp中使用自定义标签。
    1. 引用标签库(多个uri相同时,使用td文件路径来区分)
      <%@taglib uri="/MyCusTag" prefix="hello" %> 
      <%@taglib uri="/WEB-INF/MyCusTag.tld" prefix="hi"%>
    2. 使用标签
      标签体
  1. 相关接口
JspTag接口(所有自定义标签的父接口,接口中没有任何属性和方法) 有2个直接子接口:
  传统标签需要使用三个标签接口(Tag、IterationTag、BodyTag)来完成不同的功能,繁琐且不利于推广,所以sun公司推出了SimpleTag接口。
  1. Tag接口(实现Tag接口的自定义标签称为传统标签)
    接口中定义了如下方法:
      1. doStartTag()  
        返回常量EVAL_BODY_INCLUDE则执行标签体。
        返回常量SKIP_BODY则跳过(忽略)标签体,直接执行结束标签。
      2. doEndTag()  
        返回常量EVAL_PAGE则会执行结束标签后的jsp代码。
        返回常量SKIP_PAGE则忽略结束标签后的所有内容。
      3. setParent()、getParent()、setPageContext()、release()
    有1个直接子接口:IterationTag接口(继承自Tag接口,实现功能:重复执行标签体)
      接口中定义了doAfterBody()方法(在执行完自定义标签的标签体后会调用该方法)
        返回常量EVAL_BODY_AGAIN则重复执行标签体内容。
        返回常量SKIP_BODY则去执行doEndTag()。
      IterationTag接口的默认实现类:TagSupport(用于简化开发)。
      有1个直接子接口:BodyTag接口(继承自IterationTag接口,实现功能:修改标签体内容)
        接口中定义了setBodyContent()、doInitBody()方法。
        在doStartTag方法还可以返回常量EVAL_BODY_BUFFERED,WEB容器就会创建一个BodyContent对象(用于捕获标签体运行结果),然后调用setBodyContent方法将BodyContent对象的引用传递给标签处理器,WEB容器接着将标签体的执行结果写入到BodyContent对象中。在doEndTag方法中可以通过先前保存的BodyContent对象的引用来获取标签体的执行结果,然后调用BodyContent对象特有的方法对BodyContent对象中的内容(即标签体的执行结果)进行修改和控制其输出。
        BodyTag接口的默认实现类:BodyTagSupport(用于简化开发)。
  2. SimpleTag接口(实现SimpleTag接口的自定义标签称为简单标签)
    接口中定义了如下方法:
      1. doTag()
        是否执行标签体、迭代标签体、对标签体内容进行修改等功能都可以在doTag方法中完成。
      2. getParent()、setParent()、setJspContext()、setJspBody()。
    SimpleTag接口的默认实现类:SimpleTagSupport(用于简化开发)。
  1. 自定义传统标签
JSP引擎遇到自定义标签时的【执行流程】:
  首先创建标签类的实例对象,然后依次调用该对象的如下方法:
   1. public void setPageContext(PageContext pc) 
      将JSP页面的pageContext对象传递给标签类,标签类通过pageContext对象和JSP页面通信。
   2. public void setParent(Tag t) 
      将当前标签的父标签传递给标签类,如果没有则为null。
   3. public int doStartTag() 
      处理标签的开始标记。
   4. public int doEndTag() 
      执行完标签体后,会处理标签的结束标记。
   5. public void release() 
      执行完自定义标签后,标签类的实例对象会驻留在内存中直至web应用关闭时会调用release方法进行释放。

自定义标签除了能移除JSP页面中的Java代码外,也可以在JSP页面中实现以下功能:
  1. 控制jsp页面的某一部分内容是否执行。
    实现Tag接口 或 继承TagSupport类,然后覆写doStartTag() 返回不同常量。
  2. 控制整个jsp页面是否执行。
    实现Tag接口 或 继承TagSupport类,然后覆写doEndTag() 返回不同常量。
  3. 控制jsp页面内容重复执行。
    实现IterationTag接口 或 继承TagSupport类,然后覆写doStartTag()返回Tag.EVAL_BODY_INCLUDE、doEndTag()返回不同常量
  4. 修改jsp页面内容输出
    实现BodyTag接口 或 继承BodyTagSupport类,然后覆写doStartTag()返回BodyTag.EVAL_BODY_BUFFERED、doEndTag()如下:
    public int doEndTag() throws JspException {
        // this.getBodyContent()得到代表标签体的bodyContent对象
        BodyContent bodyContent = this.getBodyContent();
        // 拿到标签体内容
        String content = bodyContent.getString();
        // 修改标签体里面的内容,将标签体的内容转换成大写
        String result = content.toUpperCase();
        try {
            // 输出修改后的内容
            this.pageContext.getOut().write(result);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return Tag.EVAL_PAGE;
    }

示例(获取客户端IP)

===》第1步. 创建自定义标签类(用于获取客户端IP)
package com.sst.cx;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.Tag;
public class CusTag  implements Tag{    
    private PageContext pageContext;
    @Override
    public int doEndTag() throws JspException {
        System.out.println("调用doEndTag()方法");
        return 0;
    }
    @Override
    public int doStartTag() throws JspException {
        System.out.println("调用doStartTag()方法");
        // 可以看到pageContext对象在自定义标签中的重要性。
        HttpServletRequest request =(HttpServletRequest) pageContext.getRequest();
        JspWriter out = pageContext.getOut();
        String ip = request.getRemoteAddr();
        try {
            // 这里输出的时候会抛出IOException异常
            out.write(ip);
        } catch (IOException e) {
            // 捕获IOException异常后继续抛出
            throw new RuntimeException(e);
        }
        return 0;
    }
    @Override
    public Tag getParent() {
        return null;
    }
    @Override
    public void release() {
        System.out.println("调用release()方法");
    }
    @Override
    public void setPageContext(PageContext pageContext) {
        System.out.println("setPageContext(PageContext pageContext)");
        this.pageContext = pageContext;
    }
    @Override
    public void setParent(Tag arg0) {
    }
}

===》第2步. 创建MyCusTag.tld文件(在WEB-INF目录下)


    
    自定义标签库
    
    1.0
    
    MyCusTag
    
    /MyCusTag
    
     
        这个标签的作用是用来输出客户端的IP地址
        
        viewIP
        
        com.sst.cx.CusTag
        empty
    


===》第3步. 在jsp中使用
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<%@taglib uri="/MyCusTag" prefix="sx" %>


  
    
    My JSP 'index.jsp' starting page
    
    
        
    
    
    
  
  
    
  


不使用时,需要使用JSP脚本来实现获取客户端IP:
    <%
        // 
        String ip = request.getRemoteAddr();
        out.write(ip);
    %>
可以看到,自定义标签可以将JSP中的Java代码移除。
  1. 自定义简单标签
自定义简单标签的执行流程
  1. setJspContext() 
    将JSP页面的pageContext对象传递给标签类对象。
  2. setParent() 
    将当前标签的父标签类对象传递给标签类,只有当父标签存在时才会调用。
    使用getParent()可获取父标签类对象。
  3. 如果标签设置了属性则分别调用setter方法设值。
  4. 如果有标签体则调用setJspBody() 方法,并传入代表标签体的JspFragment对象。
  5. 执行标签时会调用doTag() ,通过操作JspFragment对象,就可以实现 是否执行、迭代、修改标签体内容。
      手动抛出javax.servlet.jsp.SkipPageException异常,则不再执行标签后的所有页面内容。
 
JspFragment对象
  代表标签体,JSP页面中的一段符合JSP语法规范的JSP片段(不能包含JSP脚本元素)
  只有2个方法:
    1. getJspContext方法
      获取JSP页面的pageContext对象。
    2. public abstract void invoke(java.io.Writer out)
      执行标签体,并将标签体的结果内容写入参数指定的流中(可以将流中的标签体内容进行修改后再输出)。可以传StringWriter输出流对象,也可以传null(会使用JspContext.getOut()方法返回的输出流对象)。
      不调用invoke方法则不会执行标签体(即不会输出标签体内容,即忽略标签体内容)。
      多次调用invoke方法则会多次执行标签体(即多次输出标签体内容)。

示例

===》第1步. 创建自定义标签类
package com.sst.cx;
import java.io.IOException;
import java.io.StringWriter;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.SkipPageException;
import javax.servlet.jsp.tagext.JspFragment;
import javax.servlet.jsp.tagext.SimpleTagSupport;
// 不推荐直接实现SimpleTag接口这种方式,推荐使用继承SimpleTagSupport类的方式来自定义简单标签。
public class SimpleTag extends SimpleTagSupport {
    // 一般只需重写doTag方法
    @Override
    public void doTag() throws JspException, IOException {
        // 得到代表jsp标签体的JspFragment对象
        JspFragment jspFragment = this.getJspBody();
        // 得到jsp页面的的PageContext对象
        // PageContext pageContext = (PageContext) jspFragment.getJspContext();
        // 调用JspWriter将标签体的内容输出到浏览器
        // jspFragment.invoke(pageContext.getOut());
       /* 
        1. 控制jsp页面某一部分内容是否执行(控制标签体是否执行)。
          调用则会执行标签体,注释掉则不再执行标签体。
          jspFragment.invoke(null);
       */ 
       /*
        2. 控制jsp页面内容重复执行。
          重复调用jspFragment.invoke(null);方法
          for (int i = 0; i < 5; i++) {
            // 将标签体的内容输出到浏览器
            jspFragment.invoke(null);
          }
       */
       /*
        3. 修改jsp页面内容输出
          StringWriter sw = new StringWriter();
          // 将标签体的内容写入到sw流中
          jspFragment.invoke(sw);
          // 获取sw流缓冲区的内容
          String content = sw.getBuffer().toString();
          content = content.toUpperCase();
          PageContext pageContext = (PageContext) this.getJspContext();
          // 将修改后的content输出到浏览器中
          pageContext.getOut().write(content);
        */
        /*
        4. 控制整个jsp页面是否执行
          抛出异常则不再执行标签后的所有内容。
          throw new SkipPageException();
        */
    }
}

===》第2步. tld中+(.tld文件通常放在WEB-INF下)
      
        SimpleTag(简单标签) 
        simple
        
        com.sst.cx.SimpleTag
        
        scriptless        
      

===》第3步. 在jsp中使用
引入
<%@taglib uri="/MyCusTag" prefix="hello" %> 
使用
nihao
  1. 开发带有属性标签

自定义标签中可以定义多个属性,在JSP页面中使用标签时设置属性值,通过这些属性可以给标签处理类传递参数信息,从而提高标签的灵活性和复用性。

使用步骤:
  1. 在标签处理类中编写每个属性及对应的setter方法(必须符合JavaBean格式)。
  2. 在TLD文件中描述标签的属性。

说明:
  1. 传统标签会在执行doStartTag方法前调用setter方法设值,简单标签会在setParent()之后setJspBody()方法之前调用setter方法设值。
  2. 如果标签的属性值是8种基本数据类型,JSP引擎会自动将字符串转换成相应的类型。但如果标签的属性是复合数据类型则无法自动转换,可使用JSP表达式或EL表达式来解决(如:Date类型 

示例

===》第1步. 在标签类中+
  private int count;  // 重复执行的次数
  public void setCount(int count) {
    this.count = count;
  }
  在doTag()方法中+
  for (int i = 0; i < this.count; i++) {
    // 将标签体的内容输出到浏览器
    jspFragment.invoke(null);
  }

===》第2步. 在tld文件的tag中+(一个属性对应一个
    描述(可选)
    
    count
    
    true
    
    true
    
    int
  

===》第3步. 在jsp中使用(会输出3遍nihao)
  nihao

2. 开发标签库

  1. 防盗链标签(防止用户直接输入网址的请求)

第1步. 创建标签类(在com.sst.cx.simpletag包下新建)

package com.sst.cx.simpletag;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.SkipPageException;
import javax.servlet.jsp.tagext.SimpleTagSupport;
public class RefererTag extends SimpleTagSupport {
    // 网站域名
    private String site;
    // 请求来路不明时 要跳转的页面
    private String page;
    @Override
    public void doTag() throws JspException, IOException {
        // 获取jsp页面的PageContext对象
        PageContext pageContext = (PageContext) this.getJspContext();
        // 通过PageContext对象来获取HttpServletRequest对象
        HttpServletRequest request = (HttpServletRequest) pageContext.getRequest();
        // 获取请求的来路(Referer)
        String referer = request.getHeader("referer");
        // 如果来路是null或者来路不是来自我们自己的site,那么就将请求重定向到page页面
        if (referer == null || !referer.startsWith(site)) {
            // 获取HttpServletResponse对象
            HttpServletResponse response = (HttpServletResponse)pageContext.getResponse();
            String webRoot = request.getContextPath();
            if (page.startsWith(webRoot)) {
                // 重定向到page页面
                response.sendRedirect(page);
            } else {
                // 重定向到page页面
                response.sendRedirect(webRoot+page);
            }
            // 重定向后,控制保护的页面不要执行
            throw new SkipPageException();
        }
    }
    public void setSite(String site) {
        this.site = site;
    }
    public void setPage(String page) {
        this.page = page;
    }
}

第2步. 创建CusTagLib.tld(在WEB-INF目录下新建)



    简单标签库
    1.0
    TagLib
    /CusTagLib
    
        
        referer
        
        com.sst.cx.simpletag.RefererTag
        
        empty
        
        
            描述标签的site属性
            
            site
            true
            
            true
        
        
            描述标签的page属性
            
            page
            true
            true
        
    

第3步. 在test.jsp文件中测试(访问则跳主页)

<%@ page language="java" pageEncoding="UTF-8"%>
<%--在jsp页面中导入自定义标签库 --%>
<%@taglib uri="/WEB-INF/CusTagLib.tld" prefix="hello"%>
<%--
在Jsp页面中使用防盗链标签 
  当用户尝试直接通过URL地址(http://localhost:8080/TestWeb2/simpletag/refererTagTest.jsp)访问这个页面时,防盗链标签的标签处理器内部就会进行处理,将请求重定向到/index.jsp。
--%>



  
    防盗链标签测试
  
  
     网站
  

  1. if标签

第1步. 创建标签类(com.sst.cx.simpletag包下新建)

package com.sst.cx.simpletag;
import java.io.IOException;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.SimpleTagSupport;
public class IFTag extends SimpleTagSupport {
    /**
     * if标签的test属性
     */
    private boolean test;
    @Override
    public void doTag() throws JspException, IOException {
        if (test) {
            this.getJspBody().invoke(null);
        }
    }
    public void setTest(boolean test) {
        this.test = test;
    }
}

第2步. CusTagLib.tld中+


    if标签
    if
    com.sst.cx.simpletag.IFTag
    scriptless
    
        if标签的test属性
        test
        true
        true
    

第3步. 在test.jsp中测试

<%@ page language="java" pageEncoding="UTF-8"%>
<%--在jsp页面中导入自定义标签库 --%>
<%@taglib uri="/WEB-INF/CusTagLib.tld" prefix="hello"%>


  
    
  
  
    <%--if标签的test属性值为true ,标签体的内容会输出--%>
    
         

网站

<%--if标签的test属性值为false ,标签体的内容不会输出--%> 不输出
  1. when otherwise标签
when标签和otherwise标签对应两个不同的标签处理器类。
希望当when标签执行后otherwise标签就不再执行,这时涉及到相互通讯的问题,可以让两个标签类拥有同一个父标签类来共享同一个变量来解决通信问题。

第1步-1. 创建标签类-父(com.sst.cx.simpletag包下新建)

package com.sst.cx.simpletag;
import java.io.IOException;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.SimpleTagSupport;
public class ChooseTag extends SimpleTagSupport {
    /**
     * 定义一个boolean类型的属性,该属性用于标识该标签下的某一个子标签是否已经执行过了,如果该标签下的某一个子标签已经执行过了,就将该属性设置为true。
     */
    private boolean isExecute;
    @Override
    public void doTag() throws JspException, IOException {
        // 输出标签体中的内容
        this.getJspBody().invoke(null);
    }
    public boolean isExecute() {
        return isExecute;
    }
    public void setExecute(boolean isExecute) {
        this.isExecute = isExecute;
    }
}

第1步-2. 创建标签类-when

package com.sst.cx.simpletag;
import java.io.IOException;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.SimpleTagSupport;
public class WhenTag extends SimpleTagSupport {
    /**
     * test属性,该属性值为true时,输出标签体中的内容
     */
    private boolean test;
    @Override
    public void doTag() throws JspException, IOException {
        // 获取标签的父标签
        ChooseTag parentTag = (ChooseTag) this.getParent();
        if (test == true && parentTag.isExecute() == false) {
            // 输出标签体中的内容
            this.getJspBody().invoke(null);
            // 将父标签的isExecute属性设置为true,告诉父标签,我(when标签)已经执行过了
            parentTag.setExecute(true);
        }
    }
    public void setTest(boolean test) {
        this.test = test;
    }
}

第1步-3. 标签处理类-otherWise

package com.sst.cx.simpletag;
import java.io.IOException;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.SimpleTagSupport;
public class OtherWiseTag extends SimpleTagSupport {
       @Override
        public void doTag() throws JspException, IOException {
            // 获取标签的父标签
            ChooseTag parentTag = (ChooseTag) this.getParent();
            // 如果父标签下的when标签没有执行过
            if (parentTag.isExecute() == false) {
                // 输出标签体中的内容
                this.getJspBody().invoke(null);
                // 设置父标签的isExecute属性为true,告诉父标签,我(otherwise标签)已经执行过了
                parentTag.setExecute(true);
            }
        }
}

第2步. CusTagLib.tld中+


        choose标签
        choose
        com.sst.cx.simpletag.ChooseTag
        scriptless
    
    
        when标签
        when
        com.sst.cx.simpletag.WhenTag
        scriptless
        
            when标签的test属性
            test
            true
            true
        
    
    
        otherwise标签
        otherwise
        com.sst.cx.simpletag.OtherWiseTag
        scriptless

第3步. 在test.jsp中测试

<%@ page language="java" pageEncoding="UTF-8"%>
<%--在jsp页面中导入自定义标签库 --%>
<%@taglib uri="/WEB-INF/CusTagLib.tld" prefix="hello"%>


  
    
  
    
          
          when标签标签体输出的内容:
              

用户为空

用户不为空
  1. foreach迭代标签

第1步. 创建标签类

package com.sst.cx.simpletag;
import java.io.IOException;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.SimpleTagSupport;
public class ForEachTag extends SimpleTagSupport {
    /**
     * 存储数据
     */
    private Object items;
    /**
     * 迭代集合时使用的变量
     */
    private String var;
    /**
     * 集合,用于存储items中的数据
     */
    private Collection collectionT;
    @Override
    public void doTag() throws JspException, IOException {
        PageContext pageContext = (PageContext) this.getJspContext();
        // 迭代collection集合
        Iterator it = collectionT.iterator();
        while (it.hasNext()) {
            // 得到一个迭代出来的对象
            Object object = (Object) it.next();
            // 将迭代出来的对象存放到pageContext对象中
            pageContext.setAttribute(var, object);
            // 输出标签体中的内容
            this.getJspBody().invoke(null);
        }
    }
    public void setVar(String var) {
        this.var = var;
    }
    public void setItems(Object items) {
        if (items instanceof Collection) {
            collectionT = (Collection) items;//list
        }else if (items instanceof Map) {
            Map map = (Map) items;
            collectionT = map.entrySet();//map
        }else if (items.getClass().isArray()) {
            collectionT = new ArrayList();
            // 获取数组的长度
            int len = Array.getLength(items);
            for (int i = 0; i < len; i++) {
                // 获取数组元素
                Object object = Array.get(items, i);
                collectionT.add(object);
            }
        }
        this.items = items;
    }
}

第2步. CusTagLib.tld中+

    
        foreach标签
        foreach
        com.sst.cx.simpletag.ForEachTag
        scriptless
        
            foreach标签的items属性
            items
            true
            true
        
        
            foreach标签的var属性
            var
            false
            true
        
    

第3步. 在test.jsp中测试

<%@ page language="java" pageEncoding="UTF-8"%>
<%--在jsp页面中导入自定义标签库 --%>
<%@taglib uri="/WEB-INF/CusTagLib.tld" prefix="hello"%>
<%@page import="java.util.HashMap"%>
<%@page import="java.util.Map"%>
<%@page import="java.util.HashSet"%>
<%@page import="java.util.Set"%>
<%@page import="java.util.ArrayList"%>
<%@page import="java.util.List"%>


  
    
  
<%
    // list集合
    List listData = new ArrayList();
    listData.add("hello");
    listData.add("hello2");
    // 对象数组
    Integer intObjArr[] = new Integer[]{1,2,3};
    // 基本数据类型数组
    int intArr[] = new int[]{4,5,6};
    // map集合
    Map mapData = new HashMap();
    mapData.put("a", "aaaaaa");
    mapData.put("b", "bbbbbb");
    // 将集合存储到pageContext对象中
    pageContext.setAttribute("listData", listData);
    pageContext.setAttribute("intObjArr", intObjArr);
    pageContext.setAttribute("intArr", intArr);
    pageContext.setAttribute("mapData", mapData);
%>
  
          <%--迭代存储在pageContext对象中的list集合 --%>
         
             ${str}

<%--迭代存储在pageContext对象中的数组 --%> ${num}

<%--迭代存储在pageContext对象中的数组 --%> ${num}

<%--迭代存储在pageContext对象中的map集合 --%> ${me}
  1. html转义标签(将标签原样输出)

第1步. 创建标签类

package com.sst.cx.simpletag;
import java.io.IOException;
import java.io.StringWriter;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.SimpleTagSupport;
public class HtmlEscapeTag extends SimpleTagSupport {
    /**
     * @param message
     * @return 转义html标签
     */
    private String filter(String message) {
        if (message == null){
            return (null);
        }
        char content[] = new char[message.length()];
        message.getChars(0, message.length(), content, 0);
        StringBuilder result = new StringBuilder(content.length + 50);
        for (int i = 0; i < content.length; i++) {
            switch (content[i]) {
            case '<':
                result.append("<");
                break;
            case '>':
                result.append(">");
                break;
            case '&':
                result.append("&");
                break;
            case '"':
                result.append(""");
                break;
            default:
                result.append(content[I]);
            }
        }
        return (result.toString());
    }
    @Override
    public void doTag() throws JspException, IOException {
        StringWriter sw = new StringWriter();
        // 将标签体中的内容先输出到StringWriter流
        this.getJspBody().invoke(sw);
        // 得到标签体中的内容
        String content = sw.getBuffer().toString();
        // 转义标签体中的html代码
        content = filter(content);
        // 输出转义后的content
        this.getJspContext().getOut().write(content);
    }
}

第2步. CusTagLib.tld中+


     HtmlEscape标签
     htmlEscape
     com.sst.cx.simpletag.HtmlEscapeTag
     scriptless

第3步. test.jsp测试

<%@ page language="java" pageEncoding="UTF-8"%>
<%--在jsp页面中导入自定义标签库 --%>
<%@taglib uri="/WEB-INF/CusTagLib.tld" prefix="hello"%>


  
    
  
  
         
              nihao
          
         
  

  1. out输出标签

第1步. 创建标签类

package com.sst.cx.simpletag;
import java.io.IOException;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.SimpleTagSupport;
public class OutTag extends SimpleTagSupport {
    /**
     * 要输出的内容
     */
    private String content;
    /**
     * 是否将内容中的html进行转义后输出
     */
    private boolean escapeHtml;
    public void setContent(String content) {
        this.content = content;
    }
    public void setEscapeHtml(boolean escapeHtml) {
        this.escapeHtml = escapeHtml;
    }
    @Override
    public void doTag() throws JspException, IOException {
        if (escapeHtml == true) {
            // 转义内容中的html代码
            content = filter(content);
            // 输出转义后的content
            this.getJspContext().getOut().write(content);
        }else {
            this.getJspContext().getOut().write(content);
        }
    }
    /**
     * @param message
     * @return 转义html标签
     */
    private String filter(String message) {
        if (message == null){
            return (null);
        }
        char content[] = new char[message.length()];
        message.getChars(0, message.length(), content, 0);
        StringBuilder result = new StringBuilder(content.length + 50);
        for (int i = 0; i < content.length; i++) {
            switch (content[i]) {
            case '<':
                result.append("<");
                break;
            case '>':
                result.append(">");
                break;
            case '&':
                result.append("&");
                break;
            case '"':
                result.append(""");
                break;
            default:
                result.append(content[I]);
            }
        }
        return (result.toString());
    }
}

第2步. CusTagLib.tld中+


        out标签
        out
        com.sst.cx.simpletag.OutTag
        empty
        
            out标签的content属性,表示要输出的内容
            content
            true
            true
        
        
            out标签的escapeHtml属性,表示是否将内容中的html进行转义后输出
            escapeHtml
            true
            false
        

第3步. test.jsp测试

<%@ page language="java" pageEncoding="UTF-8"%>
<%--在jsp页面中导入自定义标签库 --%>
<%@taglib uri="/WEB-INF/CusTagLib.tld" prefix="hello"%>


  
    
  
  
       <%--使用out标签输出content属性的内容 --%>
          
          
<%--使用out标签输出 content属性的内容,内容中的html代码会进行转义处理--%>

打包开发好的标签库

打包

1. 新建Java项目
    1. 将前面开发好的src目录下连包复制到src下
    2. 新建lib目录(从/Tomcat/lib下找jsp-api.jar和servlet-api.jar,复制到lib下)
    3. 新建META-INF目录,将前面的CusTagLib.tld复制到该目录下
2. Export项目 | Java | Jar file,不勾选.classpath .project(忽略警告)    
要打包的项目

使用

1. 将jar包放在WEB-INF的lib下
2. jsp使用
  <%@taglib uri="www.com.sst.cx/CusTagLib" prefix="hello"%>

你可能感兴趣的:(JavaWeb了解之入门篇2-1(JSP自定义标签)开发标签库)