JavaWeb学习之JSTL自定义标签库的使用、JSTL自定义函数库(7)

一、自定义标签,步骤
    * 确定需求
        * <my:date />  输出当前系统的时间  yyyy-MM-dd hh:mm:ss:SSS
    * 编写Java类
        新建包名:com.yxl.tag,新建类MyDateTag,实现SimpleTag接口
        * 只要与此接口有关的实现类,javax.servlet.jsp.tagext.JspTag
        * 需要实现具体的接口
            * javax.servlet.jsp.tagext.SimpleTag,简单标签,JSP2.0**,选择这个
            * javax.servlet.jsp.tagext.Tag,经典标签
        package com.yxl.tag;

        import java.io.IOException;
        import java.text.SimpleDateFormat;
        import java.util.Date;
        
        import javax.servlet.jsp.JspContext;
        import javax.servlet.jsp.JspException;
        import javax.servlet.jsp.PageContext;
        import javax.servlet.jsp.tagext.JspFragment;
        import javax.servlet.jsp.tagext.JspTag;
        import javax.servlet.jsp.tagext.SimpleTag;
        
        public class MyDateTag implements SimpleTag {
        
            public MyDateTag(){
                System.out.println("默认构造");
            }
            
            private PageContext pageContext;
            
            /**
             * 1、被调用的方法,tomcat调用
             */
            public void setJspContext(JspContext pc) {
        //        System.out.println(pc);
        //        System.out.println("setJspContext");
                this.pageContext = (PageContext) pc;
                
            }
        
            /**
             * 2、tomcat调用
             *  建议,在doTage方法中完成整个tag的功能
             *  需要再doTage方法之前,完成准备工作
             */
            public void doTag() throws JspException, IOException {
        //        System.out.println("doTag");
                //输出当前系统的时间  yyyy-MM-dd hh:mm:ss:SSS
                SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss:SSS");
                String date = format.format(new Date());
                //将获得的时间输出到浏览器
                this.pageContext.getOut().print(date);
                
            }
        
            @Override
            public JspTag getParent() {
                // TODO Auto-generated method stub
                return null;
            }
        
            @Override
            public void setJspBody(JspFragment arg0) {
                // TODO Auto-generated method stub
                
            }
        
            
        
            @Override
            public void setParent(JspTag arg0) {
                // TODO Auto-generated method stub
                
            }
        
        }
        
    * 编写tld文件
        在WEB-INF下新建文件夹tld,在tld文件夹下新建mytag.tld
        * tld文件是xml文档
        * 扩展名为*.tld
        * 位置:必须放置到WEB-INF目录下
        * 内容:
            <taglib xmlns="http://java.sun.com/xml/ns/javaee"
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd"
                version="2.1">
                <!-- 确定当前标签库的版本 -->
                <tlib-version>1.0</tlib-version>
                <!-- 建议引入当前便签库是,使用的简写   @taglib prefix="my" -->
                <short-name>my</short-name>
                <!-- 为当前标签库配置文件,起一个名称
                    * 内容:自定义,全球唯一
                 -->
                <uri>http://www.yxl.cn/jsp/mytag</uri>
                
                <!-- <my:date / >  注册标签 -->
                <tag>
                    <!-- 确定标签名称 -->
                    <name>date</name>
                    <!-- 确定实现类 -->
                    <tag-class>com.yxl.tag.MyDateTag</tag-class>
                    <!-- 格式化当前标签的body内容
                        * empty:当前标签没有标签体
                     -->
                    <body-content>empty</body-content>
                
                </tag>
                
                
            </taglib>
    * 在JSP页面引入
        * <%@ taglib uri="http://www.yxl.cn/jsp/mytag" prefix="my"%>
    * 测试
        * <my:date />
        
二、案例
    * 需求:<my:maxVal num1="12" num2="13" />
    package com.yxl.tag;

    import java.io.IOException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    import javax.servlet.jsp.JspContext;
    import javax.servlet.jsp.JspException;
    import javax.servlet.jsp.PageContext;
    import javax.servlet.jsp.tagext.JspFragment;
    import javax.servlet.jsp.tagext.JspTag;
    import javax.servlet.jsp.tagext.SimpleTag;
    
    public class MyMaxValueTag implements SimpleTag {
    
        public MyMaxValueTag() {
            System.out.println("默认构造");
        }
    
        private PageContext pageContext;
        private Integer num1;
        private Integer num2;
    
        // num1
        public void setNum1(Integer num) {
            this.num1 = num;
        }
    
        public void setNum2(Integer num) {
            this.num2 = num;
        }
    
        /**
         * 1、被调用的方法,tomcat调用
         */
        public void setJspContext(JspContext pc) {
            // System.out.println(pc);
            // System.out.println("setJspContext");
            this.pageContext = (PageContext) pc;
    
        }
    
        /**
         * 2、tomcat调用 建议,在doTage方法中完成整个tag的功能 需要再doTage方法之前,完成准备工作
         */
        public void doTag() throws JspException, IOException {
            System.out.println(this.num1);
            System.out.println(this.num2);
            // 判断两个数据的大小,然后输出
            if (this.num1 > this.num2) {
                this.pageContext.getOut().print(num1 + "大于" + num2);
            } else if (this.num1 < this.num2){
    
                this.pageContext.getOut().print(num1 + "小于" + num2);
            }
            else{
                this.pageContext.getOut().print(num1 + "等于" + num2);
            }
    
        }
    
        @Override
        public JspTag getParent() {
            // TODO Auto-generated method stub
            return null;
        }
    
        @Override
        public void setJspBody(JspFragment arg0) {
            // TODO Auto-generated method stub
    
        }
    
        @Override
        public void setParent(JspTag arg0) {
            // TODO Auto-generated method stub
    
        }
    
    }
    <taglib xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd"
    version="2.1">
    <!-- 确定当前标签库的版本 -->
    <tlib-version>1.0</tlib-version>
    <!-- 建议引入当前便签库是,使用的简写 @taglib prefix="my" -->
    <short-name>my</short-name>
    <!-- 为当前标签库配置文件,起一个名称 * 内容:自定义,全球唯一 -->
    <uri>http://www.yxl.cn/jsp/mytag</uri>

    <!-- <my:date / > 注册标签 -->
    <tag>
        <!-- 确定标签名称 -->
        <name>date</name>
        <!-- 确定实现类 -->
        <tag-class>com.yxl.tag.MyDateTag</tag-class>
        <!-- 格式化当前标签的body内容 * empty:当前标签没有标签体 -->
        <body-content>empty</body-content>

    </tag>

    <!-- <my:maxValue / > 注册标签 -->
    <tag>
        <!-- 确定标签名称 -->
        <name>maxValue</name>
        <!-- 确定实现类 -->
        <tag-class>com.yxl.tag.MyMaxValueTag</tag-class>
        <!-- 格式化当前标签的body内容 * empty:当前标签没有标签体 -->
        <body-content>empty</body-content>
        <!-- 确定当前标签使用了哪些属性 -->
        <attribute>
            <!-- 设置属性名称 -->
            <name>num1</name>
            <!-- 设置属性是否必须 * true/false * yes/no -->
            <required>true</required>
            <!-- rtexprvalue 运行时表达式的值 * runtime expression value -->
            <rtexprvalue>true</rtexprvalue>
            <!-- 确定标签类型 -->
            <type>java.lang.Integer</type>
        </attribute>

        <attribute>
            <!-- 设置属性名称 -->
            <name>num2</name>
            <!-- 设置属性是否必须 * true/false * yes/no -->
            <required>true</required>
            <!-- rtexprvalue 运行时表达式的值 * runtime expression value -->
            <rtexprvalue>true</rtexprvalue>
        </attribute>
    </tag>
    </taglib>
    
    * 需求:<my:toUpperCase>xxYYdfsdDFwerd</my:toUpperCase>
    标签体
    package com.yxl.tag;

    import java.io.IOException;
    import java.io.StringWriter;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    import javax.servlet.jsp.JspContext;
    import javax.servlet.jsp.JspException;
    import javax.servlet.jsp.PageContext;
    import javax.servlet.jsp.tagext.JspFragment;
    import javax.servlet.jsp.tagext.JspTag;
    import javax.servlet.jsp.tagext.SimpleTag;
    
    
    public class MyToUpperCaseTag implements SimpleTag {
    
        public MyToUpperCaseTag() {
            System.out.println("默认构造");
        }
    
        private PageContext pageContext;
    
        private JspFragment jspBody;
        
        
       
        
        /**
         * 1、被调用的方法,tomcat调用
         */
        public void setJspContext(JspContext pc) {
            
            this.pageContext = (PageContext) pc;
    
        }
        
         public void setJspBody(JspFragment jspBody){
                this.jspBody = jspBody;
         }
    
        /**
         * 2、tomcat调用 建议,在doTage方法中完成整个tag的功能 需要再doTage方法之前,完成准备工作
         */
        public void doTag() throws JspException, IOException {
            StringWriter stringWriter = new StringWriter();
            this.jspBody.invoke(stringWriter);
            String data = stringWriter.toString();
            this.pageContext.getOut().print(data.toUpperCase());
    
        }
    
        @Override
        public JspTag getParent() {
            // TODO Auto-generated method stub
            return null;
        }
    
    
    
        @Override
        public void setParent(JspTag arg0) {
            // TODO Auto-generated method stub
    
        }
    
        
    
        
    
    }
    <!-- <my:toUpperCase / > 转换为大写 -->
    <tag>
        <!-- 确定标签名称 -->
        <name>toUpperCase</name>
        <!-- 确定实现类 -->
        <tag-class>com.yxl.tag.MyToUpperCaseTag</tag-class>
        
        <!-- 格式化当前标签的body内容 * empty:当前标签没有标签体 -->
        <!-- JSP:支持JSP所有的语法,在Tag中使用
        scriptless:对于JSP页面的脚本不支持
        tagdependent:标签体不做处理,原样输出 -->
        <body-content>scriptless</body-content>
        
    </tag>
    <my:toUpperCase>abcd</my:toUpperCase>
    * 需求:循环
    使用extends SimpleTagSupport这种方式实现标签类,SimpleTagSupport已经实现了SimpleTag接口
    三种循环遍历
    <taglib xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd"
    version="2.1">
    <!-- 确定当前标签库的版本 -->
    <tlib-version>1.0</tlib-version>
    <!-- 建议引入当前便签库是,使用的简写 @taglib prefix="my" -->
    <short-name>my</short-name>
    <!-- 为当前标签库配置文件,起一个名称 * 内容:自定义,全球唯一 -->
    <uri>http://www.yxl.cn/jsp/mytag</uri>


     <!-- 
    <my:myeach start="0" end="9" step="1" var="ss">
        ${ss} ** <br/>
    </my:myeach>
     -->
     
     <tag>
         <name>myeach</name>
         <tag-class>com.yxl.tag.MyEachTag</tag-class>
         <body-content>scriptless</body-content>
         
         <attribute>
             <name>start</name>
             <required>true</required>
             <rtexprvalue>true</rtexprvalue>
         </attribute>
         <attribute>
             <name>end</name>
             <required>true</required>
             <rtexprvalue>true</rtexprvalue>
         </attribute>
         <attribute>
             <name>step</name>
             <required>true</required>
             <rtexprvalue>true</rtexprvalue>
         </attribute>
         <attribute>
             <name>var</name>
             <required>true</required>
             <rtexprvalue>true</rtexprvalue>
         </attribute>
     </tag>
     
     
     <!-- 
     <my:myList items="${listObj}" var="yyyyy">
        ${yyyyy}  ## <br/>
    </my:myList>
     
      -->
      
      <tag>
          <name>myList</name>
          <tag-class>com.yxl.tag.MyListTag</tag-class>
          <body-content>scriptless</body-content>
      
          <attribute>
              <name>items</name>
              <required>true</required>
              <rtexprvalue>true</rtexprvalue>
          </attribute>
          <attribute>
              <name>var</name>
              <required>true</required>
              <rtexprvalue>true</rtexprvalue>
          </attribute>
      </tag>
      
      
       <tag>
          <name>forEach</name>
          <tag-class>com.yxl.tag.ForEachTag</tag-class>
          <body-content>scriptless</body-content>
      
          <attribute>
              <name>items</name>
              <required>true</required>
              <rtexprvalue>true</rtexprvalue>
          </attribute>
          <attribute>
              <name>var</name>
              <required>true</required>
              <rtexprvalue>true</rtexprvalue>
          </attribute>
      </tag>
    </taglib>
    package com.yxl.tag;
    
    import java.io.IOException;
    
    import javax.servlet.jsp.JspException;
    import javax.servlet.jsp.tagext.SimpleTagSupport;
    
    public class MyEachTag extends SimpleTagSupport{
        
        /*
         * <my:myeach start="0" end="9" step="1" var="ss">
            ${ss} ** <br/>
        </my:myeach>
         */
        
        private Integer start;
        private Integer end;
        private Integer step;
        private String var;
    
        public void setStart(Integer start) {
            this.start = start;
        }
    
        public void setEnd(Integer end) {
            this.end = end;
        }
    
        public void setStep(Integer step) {
            this.step = step;
        }
    
        public void setVar(String var) {
            this.var = var;
        }
    
        public void doTag() throws JspException, IOException {
            //完成功能:将获得的变量信息,输出到浏览器
            
            for(int i = start ; i <= end ; i +=step){
                //从父类中,获得pagecontext对象
                this.getJspContext().setAttribute(var, i);
                //将el表达式的结果发送到浏览器
                // * el表达式的位置
                // * 如何发送
                this.getJspBody().invoke(null);
                //this.getJspBody().invoke(this.getJspContext().getOut());
            }
            
        }
        
        
        
    
    }
    
    
    
    
    package com.yxl.tag;

    import java.io.IOException;
    import java.util.Iterator;
    import java.util.List;
    
    import javax.servlet.jsp.JspException;
    import javax.servlet.jsp.tagext.SimpleTagSupport;
    
    public class MyListTag extends SimpleTagSupport {
    
        /*
        <my:myList items="${listObj}" var="yyyyy">
            ${yyyyy}  ## <br/>
        </my:myList>
         */
        
        private List items;
        private String var;
        public void setItems(List items) {
            this.items = items;
        }
    
        public void setVar(String var) {
            this.var = var;
        }
    
        @Override
        public void doTag() throws JspException, IOException {
            //完成功能:将获得的list信息遍历输出到浏览器
            Iterator it = items.iterator();
            while(it.hasNext()){
                Object str = it.next();
                //将结果放置到作用域
                this.getJspContext().setAttribute(var, str);
                //将el表达式的结果数据到浏览器
                this.getJspBody().invoke(null);
            }
        }
        
        
    
    }
        
        
    
    package com.yxl.tag;

    import java.io.IOException;
    import java.util.Arrays;
    import java.util.Iterator;
    import java.util.List;
    import java.util.Map;
    
    import javax.servlet.jsp.JspException;
    import javax.servlet.jsp.tagext.SimpleTagSupport;
    
    public class ForEachTag extends SimpleTagSupport {
    
        /*
        <my:myList items="${listObj}" var="yyyyy">
            ${yyyyy}  ## <br/>
        </my:myList>
         */
        
        private Iterator<Object> items;
        private String var;
        public void setItems(Object items) {
            //list
            if(items instanceof List){
                this.items = ((List)items).iterator();
            }
            //map
            if(items instanceof Map){
                this.items = ((Map)items).entrySet().iterator();
            }
            //object[]
            if(items instanceof Object[]){
                this.items = Arrays.asList((Object[])items).iterator();
            }
            
        }
    
        public void setVar(String var) {
            this.var = var;
        }
    
        @Override
        public void doTag() throws JspException, IOException {
            //完成功能:将获得的list信息遍历输出到浏览器
    
            while(items.hasNext()){
                Object str = items.next();
                //将结果放置到作用域
                this.getJspContext().setAttribute(var, str);
                //将el表达式的结果数据到浏览器
                this.getJspBody().invoke(null);
            }
        }
        
        
    
    }
    
    
    <my:myeach start="0" end="9" step="1" var="eeee">
        ${eeee} ** <br/>
    </my:myeach>
    <%
    
        List<String> list = new ArrayList<String>();
        list.add("abc");
        list.add("123");
        list.add("wasd");
    
        pageContext.setAttribute("listObj",list);
    %>
    myList<br/>
    <my:myList items="${listObj}" var="yyyyy">
        ${yyyyy}  ## <br/>
    </my:myList>
    
    <my:forEach items="${listObj}" var="mm">
        ${mm} <br/> 
    </my:forEach>
    
    <hr/>
    
    <%
    
        Map<String,String> map = new HashMap<String,String>();
        map.put("11111","11111");
        map.put("22222","222222");
        map.put("33333","33333");
    
        pageContext.setAttribute("mapObj",map);
    
    %>
    遍历Map<br/>
    
    <my:forEach items="${mapObj}" var="map">
        ${map.key} ---- ${map.value} <br/> 
    </my:forEach>
三、自定义函数
    * 创建类,但方法必须是静态的
    package com.yxl.domain;

    public class Calculator {
        private String firstNum;
        private String operator;
        private String secondNum;
        private String result;
        public String getFirstNum() {
            return firstNum;
        }
        public void setFirstNum(String firstNum) {
            this.firstNum = firstNum;
        }
        public String getOperator() {
            return operator;
        }
        public void setOperator(String operator) {
            this.operator = operator;
        }
        public String getSecondNum() {
            return secondNum;
        }
        public void setSecondNum(String secondNum) {
            this.secondNum = secondNum;
        }
        public String getResult() {
            return result;
        }
        public void setResult(String result) {
            this.result = result;
        }
        public Calculator() {
        }
        
        //计算方法
        public static void calculator(Calculator cal){
            
            //通过运算符,将firstNum和secondNum处理的结果,存放到result
        
            
            
            double first = Double.valueOf(cal.firstNum);
            double second = Double.valueOf(cal.secondNum);
            char ope = cal.operator.charAt(0);
            
            switch (ope) {
                case '+':
                    cal.result = String.valueOf(first + second);
                    break;
                case '-':
                    cal.result = String.valueOf(first - second);
                    break;
                case '*':
                    cal.result = String.valueOf(first * second);
                    
                    break;
                case '/':
                    cal.result = String.valueOf(first / second);
                    break;
        
                default:
                    throw new RuntimeException("非法操作符");
            }
            
        }
    }
        
    * 书写配置文件tld
        新建myFun.tld
        <?xml version="1.0" encoding="UTF-8" ?>
        <taglib xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
            version="2.0">
        
            <tlib-version>1.0</tlib-version>
            <short-name>myfn</short-name>
            <uri>http://www.yxl.cn/mytag/functions</uri>
            <!-- 确定当前函数 myfn:calculator(cal) -->
            <function>
                <name>calculator</name>
                <function-class>com.yxl.domain.Calculator</function-class>
                <!-- 当前使用函数的声明 public static void calculator(Calculator cal) -->
                <function-signature>void calculator(com.yxl.domain.Calculator)</function-signature>
            </function>
        
        </taglib>
    * 引用
        * <%@ taglib uri="http://www.yxl.cn/mytag/functions" prefix="myFn" %>
    * 测试
        <jsp:useBean id="cal" class="com.yxl.domain.Calculator"></jsp:useBean>
        <jsp:setProperty property="firstNum" value="1" name="cal"/>
        <jsp:setProperty property="operator" value="+" name="cal"/>
        <jsp:setProperty property="secondNum" value="4" name="cal"/>
        ${myFn:calculator(cal)}
        ${cal.result}
四、总结
    * 共同点:
        * 需要引入
            * <%@ taglib uri="http://www.yxl.cn/mytag/myeach" prefix="my" %>
        * 都需要配置tld文件
    * 区别:
        * 自定义标签
            * 创建一个类,完成一个功能或一组功能。
            * 可以选择el表达式
        * 自定义函数
            * 创建一个静态方法,完成一个操作。
            * 必须与EL表达式结合使用
                ${fn:xxxx}
原文地址:https://www.cnblogs.com/yxlblogs/p/4158792.html