• EL的函数与标签


    1 什么EL函数库

      EL函数库是由第三方对EL的扩展,我们现在学习的EL函数库是由JSTL添加的。下面我们会学习JSTL标签库。

    EL函数库就是定义一些有返回值的静态方法。然后通过EL语言来调用它们!当然,不只是JSTL可以定义EL函数库,我们也可以自定义EL函数库。

      EL函数库中包含了很多对字符串的操作方法,以及对集合对象的操作。例如:${fn:length(“abc”)}会输出3,即字符串的长度。

    2 导入函数库

      因为是第三方的东西,所以需要导入。导入需要使用taglib指令!

    <%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>

    3 EL函数库介绍

    l  String toUpperCase(String input):

    l  String toLowerCase(String input):

    l  int indexOf(String input, String substring):

    l  boolean contains(String input, String substring):

    l  boolean containsIgnoreCase(String input, String substring):

    l  boolean startsWith(String input, String substring):

    l  boolean endsWith(String input, String substring):

    l  String substring(String input, int beginIndex, int endIndex):

    l  String substringAfter(String input, String substring):

    l  substringBefore(String input, String substring):

    l  String escapeXml(String input):

    l  String trim(String input):

    l  String replace(String input, String substringBefore, String substringAfter):

    l  String[] split(String input, String delimiters):

    l  int length(Object obj):

    l  String join(String array[], String separator):

    <%@taglib prefix="fn"   uri="http://java.sun.com/jsp/jstl/functions"   %>

    String[] strs = {"a", "b","c"};

    List list = new ArrayList();

    list.add("a");

    pageContext.setAttribute("arr", strs);

    pageContext.setAttribute("list", list);

    %>

    ${fn:length(arr)   }<br/><!--3-->

    ${fn:length(list)   }<br/><!--1-->

    ${fn:toLowerCase("Hello")   }<br/> <!-- hello -->

    ${fn:toUpperCase("Hello")   }<br/> <!-- HELLO -->

    ${fn:contains("abc",   "a")}<br/><!-- true -->

    ${fn:containsIgnoreCase("abc",   "Ab")}<br/><!-- true -->

    ${fn:contains(arr,   "a")}<br/><!-- true -->

    ${fn:containsIgnoreCase(list,   "A")}<br/><!-- true -->

    ${fn:endsWith("Hello.java",   ".java")}<br/><!-- true -->

    ${fn:startsWith("Hello.java",   "Hell")}<br/><!-- true -->

    ${fn:indexOf("Hello-World",   "-")}<br/><!-- 5 -->

    ${fn:join(arr,   ";")}<br/><!-- a;b;c -->

    ${fn:replace("Hello-World",   "-", "+")}<br/><!-- Hello+World -->

    ${fn:join(fn:split("a;b;c;",   ";"), "-")}<br/><!-- a-b-c -->

     

    ${fn:substring("0123456789",   6, 9)}<br/><!-- 678 -->

    ${fn:substring("0123456789",   5, -1)}<br/><!-- 56789 -->

    ${fn:substringAfter("Hello-World",   "-")}<br/><!-- World -->

    ${fn:substringBefore("Hello-World",   "-")}<br/><!-- Hello -->

    ${fn:trim("     a b c       ")}<br/><!-- a b c -->

    ${fn:escapeXml("<html></html>")}<br/> <!-- <html></html> -->

    4 自定义EL函数库

    l  写一个类,写一个有返回值的静态方法;

    l  编写tld文件,可以参数fn.tld文件来写,把tld文件放到classes下(还可以自定义命名空间);

    l  在页面中添加taglib指令,导入自定义标签库。

    ItcastFuncations.java

    package cn.itcast.el.funcations;

     

    public class ItcastFuncations {

        public static String test() {

           return "传智播客自定义EL函数库测试";

        }

    }

    itcast.tld(放到classes下)

    <?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">

       

      <description>ITCAST 1.0 functions library</description>

      <display-name>ITCAST functions</display-name>

      <tlib-version>1.0</tlib-version>

      <short-name>itcast</short-name>

      <uri>http://www.itcast.cn/jsp/functions</uri>

     

      <function>

        <name>test</name>

        <function-class>cn.itcast.el.funcations.ItcastFuncations</function-class>

        <function-signature>String test()</function-signature>

      </function>

    </taglib>

    index.jsp

    <%@ page language="java"   import="java.util.*" pageEncoding="UTF-8"%>

    <%@ taglib prefix="itcast"   uri="/WEB-INF/classes/itcast.tld" %>

     

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD   HTML 4.01 Transitional//EN">

    <html>

      <body>

        <h1>${itcast:test() }</h1>

      </body>

    </html>

    如果把itcast.tld文件放到classesMETA-INFitcast.tld,那么就可以把

    <%@ taglib prefix="itcast" uri="/WEB-INF/classes/itcast.tld" %>

    修改为

    <%@ taglib prefix="itcast" uri="http://www.itcast.cn/jsp/functions" %>

    对应itcast.tld文件中的<uri>元素内容。

    一般这种方式都是打包成Jar时,在Jar中的META-INF目录中存放TLD文件。

    自定义标签

    Tag

    1 什么是自定义标签

      尽管JSP本身,以及第三方提供了很多标签库,但因为业务需要,我们有时还是需要自定义标签。因为JSP页面中不可以存在Java代码,所以我们需要自定义标签!

     2 标签的真身

    其实我们现在应该可以了解了,真的是万物皆对象。JSP可以是一个对象,当然标签也可以是一个对象。其实在页面中使用的标签就是对一个对象的方法调用!

    标签:

    l  标签处理类:都有自己的标签处理类!所有标签处理类都必须去实现Tag或SimpleTag接口;

    l  TLD(Tag Library Description):一个TLD文件中可以部署多个标签!JSP会通过TLD文件找到标签! (webappsexamplesWEB-INFjsp2,这里有模板)

    3 Hello Tag!

    写一个类:MyTag,实现Tag接口。Tag接口中一共6个方法!我们只需要去实现两个方法即可,其他的方法当它不存在!

    l  setPageContext(PageContext):为本类添加PageContext属性,在本方法中把参数赋给本类属性。没错,就是用来保存PageContext中,因为doStartTag()方法中要用PageContext;

    l  int doStartTag():使用pageContext获取out对象,然后使用out向页面打印:“Hello Tag!”。本方法还有一个返回值,返回0就行了(先不用管返回值是干什么的)!

    l  TLD:TLD文件中的一个<tag>对应一个标签的部署信息!现在中需要照猫画虎就OK了!没错,TLD是一个XML文件!(可以到webappsexamplesWEB-INFjsp2中查找TLD文件)

    MyTag.java

    package cn.itcast.tags;

     

    import java.io.IOException;

     

    import javax.servlet.jsp.JspException;

    import javax.servlet.jsp.PageContext;

    import javax.servlet.jsp.tagext.Tag;

     

    public class MyTag implements Tag  {

        private PageContext pageContext ;

        public void setPageContext(PageContext   pageContext) {

           this.pageContext = pageContext;

        }

        public int doStartTag() throws JspException {

           try {

               this.pageContext.getOut().write("Hello   Tag!"); 

           } catch (IOException e) {

               throw new JspException(e);

           }

           return 0 ;

        }

        public void setParent(Tag t) {}

        public Tag getParent() {return null;}

        public int doEndTag() throws JspException {return 0;}

        public void release() {  }

    }

     mytld.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   web-jsptaglibrary_2_0.xsd"

        version="2.0">

     

        <description>xixi</description>

        <tlib-version>1.0</tlib-version>

        <jsp-version>2.0</jsp-version>

        <short-name>hello tag</short-name>

        <uri></uri>

        <small-icon></small-icon>

     

        <tag>

          <name>helloTag</name> 

          <tag-class>cn.itcast.tags.MyTag</tag-class>

          <body-content>empty </body-content>

        </tag>

    </taglib>

     把mytld.tld文件放到/WEB-INF/classes/mytld.tld路径。

    index.jsp

    <%@taglib prefix="it"   uri="/WEB-INF/classes/mytld.tld" %>

    ……

    <body>

        <h1><it:helloTag/> </h1>

    </body>

    4 标签的生命周期

      在开始聊标签的生命周期之前,我们先来看看TLD的加载过程。

    首次加载TLD文件

    当index.jsp第一次被执行时,Tomcat会把index.jsp编译成index_jsp.java。在这个过程中,Tomcat会根据“<%@ taglib uir=”/WEB-INF/classes/mytld.tld”…%>”去加载mytld.tld文件。这个加载TLD文件的过程只执行一次,以后就不会再执行了。

    实例化标签处理器对象

    通过TLD找到标签的处理器类,然后实例化处理器对象,并把处理器对象放到“标签池”中。也就是说,每个标签的处理器类只会有一个实例!因为下一次访问这个标签就直接从池中获取处理器对象,而不需要再去创建了。

    标签生命周期方法

    l  调用setPageContext()方法,把当前页面的PageContext传递给标签处理器类;

    l  调用setParent()方法,给标签器传递父标签。如果没有父标签就传递null;

    l  在执行到开始标签时,调用doStartTag()方法,doStartTag()方法返回值:

    • 0(Tag.SKIP_BODY):表示忽略标签体内容;
    • 1(Tag.EVAL_BODY_INCLUDE):表示显示标签体内容;

    l  在执行到标签标签时,调用doEndTag()方法,doEndTag()方法返回值:

    • 5(Tag.SKIP_PAGE):表示忽略标签后面的页面东西;
    • 6(Tag.EVAL_PAGE)表示显示标签后面的页面东西。

    l  release()方法会在重启Tomcat时被执行,即Tomcat从标签器池中移除标签时会调用这个方法。


    必须实现Tag接口

    添加PageContext属性

    保存参数pageContext,在doStartTag()方法中方便使用。

    使用pageContext获取输出流,然后使用流对象向浏览器打印Hello Tag!字符串。注意:如果没有在setPageContext()方法中保存参数,那么在doStartTag()方法中就会抛出空指针异常。

    返回0表示不执行标签体。现在不用理会它!

    这一部分是对当前标签库的声明!都是一些无需关心的东西。

    l  当前标签库的描述;

    l  当前标签库的版本;

    l  支持JSP的版本;

    l  标签库的名称(用于在工具上显示标签);

    l  uri:这个东西是有用的,后面再讲;

    l  小图标也是为了在工具上显示用的;

    标签的名称

    标签处理类

    标签体是空类型

    it与taglib指令中的prefix对应;helloTag与tld文件中的<name>对应!

    SimpleTag

     1 SimpleTag是什么

    标签处理类必须实现JspTag接口,而JspTag接口有两个子接口:Tag和SimpleTag。更加确切的说:标签处理类必须实现Tag或SimpleTag接口。

    JSP2.0之后,SUN提供了SimpleTag接口,通过SimpleTag接口来实现标签处理类要比Tag这种传统方式方便很多,所以现在我们可以大声与Tag说再见了。

    SimpleTag接口内容如下:

    l  void doTag():标签执行方法;

    l  JspTag getParent():获取父标签;

    l  void setParent(JspTag parent):设置父标签

    l  void setJspContext(JspContext context):设置PageContext

    l  void setJspBody(JspFragment jspBody):设置标签体对象;

    2 继承SimpleTagSupport

    public class HelloTag extends SimpleTagSupport {

        public void doTag() throws   JspException, IOException {

           this.getJspContext().getOut().write("<p>Hello   SimpleTag!</p>")[向页面输出!注意,不能向页面输出<%%>东西!] ;

        }

    }

    3 <body-content>

    <body-content>元素的可选值有:

    l  empty:不能有标签体内容。

    l  JSP:标签体内容可以是任何东西:EL、JSTL、<%=%>、<%%>,以及html;但不建议使用Java代码段,SimpleTag已经不再支持使用<body-content>JSP</body-content>;

    l  scriptless:标签体内容不能是Java代码段,但可以是EL、JSTL等;

    l  tagdependent:标签体内容不做运算,由标签处理类自行处理,无论标签体内容是EL、JSP、JSTL,都不会做运算。

    4 不执行标签下面的页面内容

    我们知道,在使用Tag接口来编写标签时,可以跳过标签下面的JSP页面内容。在SimpleTag中也是可以的,这需要在doTag()方法中抛出SkipPageException。

    SkipPageException是JspException的子类,当doTag()方法抛出该异常时,JSP真身不会打印异常信息,而是跳转页面内容!

    5 带有属性的标签

    l  在处理类中添加属性,以及getter/setter方法;

    l  在TLD中部属相关属性。

     forEach

    功能:模仿JSTL中的<c:forEach>标签。

    forEach标签属性:

    l  items:Object类型,可以是Collection、Map,或者数组(用到了数组反射);

    l  begin:Integer类型,表示从哪个下标位置开始遍历;

    l  end:Integer类型,表示遍历到哪个下标位置结束;

    l  var:String类型,使用var指定的值来保存当前项到PageContext中;

    l  step:Integer类型,表示步长;

    l  varStatus:String类型,使用varStatus的值来保存当前循环的循环状态。

    jsp页面  设置一个集合

    <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
    <%@ taglib uri="http://www.itzl.com/myjstl/mytagTest" prefix="mytag"%>
    <
    <html>
      <head></head>
      <body>
         <%
        /* List list = new ArrayList();
        list.add("aaa");
        list.add("bbb");
        list.add("ccc");
        request.setAttribute("list", list); */
        /* Map map=new HashMap();
        map.put("a1", "qwe");
        map.put("a2", "asd");
        map.put("a3", "zxc");
        request.setAttribute("map", map);
        */ 
        int arr[]={1,2,3};
        request.setAttribute("arr", arr);
        %>
        <mytag:ForEach items="${arr}" var="v">
        ${v}
        </mytag:ForEach>
    
      </body>
    </html>

    实现

    package cn.zl.web.el;
    
    import java.io.IOException;
    import java.lang.reflect.Array;
    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.Map;
    
    import javax.servlet.jsp.JspException;
    import javax.servlet.jsp.PageContext;
    import javax.servlet.jsp.tagext.JspFragment;
    import javax.servlet.jsp.tagext.SimpleTagSupport;
    
    import cn.zl.web.jsp.VarStatuts;
    
    public class ForEachSimpleTag extends SimpleTagSupport {
    
            private Integer begin;
            private Integer end;
            private Integer step;
            private Object items;
            private String var;
            private String varStatus;
            private Collection collection = new ArrayList(); 
            public void setBegin(Integer begin) {
                this.begin = begin;
            }
            public void setEnd(Integer end) {
                this.end = end;
            }
            public void setStep(Integer step) {
                this.step = step;
            }
            public void setItems(Object items) {
                this.items = items;
            }
            public void setVar(String var) {
                this.var = var;
            }
            public void setVarStatus(String varStatus) {
                this.varStatus = varStatus;
            }
            private Object[] toArray (Object items) throws JspException {
                if(items == null ) {
                    throw new NullPointerException("items不存在!");
                }
                if(items instanceof Collection) {
                    return ((Collection)items).toArray() ;
                } else if(items instanceof Map) {
                    return ((Map)items).entrySet().toArray() ;
                } else if(items.getClass().isArray()) {
                    //return (Object[])items ;
                    int length = Array.getLength(items);//得到数组长度
                    for (int i = 0; i < length; i++) {
                        //取数组中的每个元素
                        Object obj = Array.get(items, i);// 取第i个元素
                        collection.add(obj);//将数组中的元素加入到集合中
                        
                }
                    return collection.toArray();
                }            
                throw new JspException("items不是数组,不是集合!") ;
            }
            public void doTag() throws JspException, IOException {
                Object[] objs = this.toArray(items) ;
                if(begin == null) {
                    begin = 0;
                } 
                if(end == null) {
                    end = objs.length - 1;
                } 
                if(step == null) {
                    step = 1;
                } 
                PageContext pageContext = (PageContext) this.getJspContext();
                JspFragment body = this.getJspBody();
                for(int i = begin; i <= end; i+=step ) {
                    Object item = objs[i];
                    if(varStatus != null ) {
                        VarStatuts vs = new VarStatuts();
                        vs.setFirst(i == begin);
                        vs.setLast(i == end);
                        vs.setIndex(i);
                        vs.setCount(i+1);
                        vs.setCurrent(objs[i]) ;
                        pageContext.setAttribute(varStatus, vs) ;
                    }
                    if(var != null) {
                        pageContext.setAttribute(var, item); 
                    }
                    body.invoke(null); 
                }
                if(var != null) {
                    pageContext.removeAttribute(var);
                }
                if(varStatus != null) {
                    pageContext.removeAttribute(varStatus);
                } 
            }
        }

    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">
        <description>A tag library exercising SimpleTag handlers.</description>
        <tlib-version>1.0</tlib-version>
        <short-name>mytag</short-name>
        <!--命名空间   (别名)-->
        <uri>http://www.itzl.com/myjstl/mytagTest</uri>
        <!-- el 自定义函数       -->
       
      <tag><!-- 配置文件 -->
            <name>ForEach</name>
            <tag-class>cn.zl.web.el.ForEachSimpleTag</tag-class>
            <body-content>scriptless</body-content>
            <attribute>
                <name>items</name><!-- 属性名称 -->
                <required>true</required><!-- 改属性是否必须,true代表必须 -->
                <rtexprvalue>true</rtexprvalue><!-- 是否支持表达式 -->
            </attribute>
            <attribute>
                <name>var</name><!-- 属性名称 -->
                <required>false</required><!-- 改属性是否必须,true代表必须 -->
                <rtexprvalue>false</rtexprvalue><!-- 是否支持表达式 -->
            </attribute>
        </tag>
       
    </taglib>
  • 相关阅读:
    使用curl命令操作elasticsearch
    Elasticsearch + logstash + kibana 配置
    Solr6.2.0 + zookeeper 集群配置
    Elasticsearch + logstash中文指南
    ELK+kafka构建日志收集系统
    基于docker+etcd+confd + haproxy构建高可用、自发现的web服务
    mongodb配置
    Docker的私有仓库
    GitLab + Jenkins + Docker + Kubernetes。
    ansible 安装使用
  • 原文地址:https://www.cnblogs.com/lulu638/p/4257710.html
Copyright © 2020-2023  润新知