• EL函数以及自定义标签的应用


    一、EL函数(调用普通类的静态方法)


    编写步骤(自定义EL函数的编写步骤即自定义标签的编写步骤):

    ①编写一个普通的java类,提供一个静态方法,功能自定,例如下:

    1 package cn.wzbrilliant.el;
    2 
    3 public class ElFunction {
    4     public static String toUpperCase(String str){
    5         return str.toUpperCase();
    6     }
    7 }

    ②在JavaWeb应用的WEB-INF目录下建立一个扩展名是tld(taglib definition)的XML文件。内容如下:

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <taglib xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     3     xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
     4     version="2.0">
     5     <tlib-version>1.0</tlib-version>
     6     <short-name>myfn</short-name>
     7     <uri>/WEB-INF/myfn.tld</uri>
     8     
     9     <function><!-- 定义函数 -->
    10         <name>toUpper</name> <!-- 调用名称 -->
    11         <function-class>cn.wzbrilliant.el.ElFunction</function-class> <!-- 类全名 -->
    12         <function-signature>java.lang.String toUpperCase( java.lang.String )</function-signature>
    13     </function>
    14     
    15 </taglib>

    <tlib-version>值随意

    <short-name>一般与文件名、前缀名称相同,方便查找,不相同也可。

    <uri>值随意,只要与web.xml中的uri想对应即可


    ③(可选步骤)前提是把tld文件放到了WEB-INF目录下。
    告知应用,tld文件和tld中的uri的对应。修改web.xml,增加以下内容:

    1 <jsp-config>
    2         <taglib>
    3             <taglib-uri>/WEB-INF/myfn.tld</taglib-uri>
    4             <taglib-location>/WEB-INF/myfn.tld</taglib-location>
    5         </taglib>
    6 </jsp-config>

    <taglib> 代表一个标签库,可以多个

    <taglib-location> tld文件的位置


    ④ 在JSP中使用

    用taglib指令,引入自定义的EL函数库: <%@ taglib uri="/WEB-INF/myfn.tld" prefix="myfn"%> 

    使用方式如下:

    1 <%
    2         pageContext.setAttribute("p", "abcdef");
    3 %>
    4 
    5 ${myfn:toUpper(h) } <br/>
    6 ${myfn:toUpper("abcdef") }

    代码第五行和第六行都可输出"ABCDEF"。

    二、EL自定义标签开发

    自定义标签属于JSP技术

    1、标签的作用

    移除掉JSP中的Java脚本(<%%>)

    2、编写自定义标签的步骤(自定义EL函数,步骤相同)

    自定义标签分为两种,传统标签简单标签

    这里只介绍简单标签的开发:

    ①编写一个类,直接或间接实现javax.servlet.jsp.tagext.Tag接口

    这里继承SimpleTagSupport类,例子如下: 

     1 package cn.wzbrilliant.el;
     2 
     3 import java.io.IOException;
     4 
     5 import javax.servlet.jsp.JspException;
     6 import javax.servlet.jsp.tagext.SimpleTagSupport;
     7 
     8 public class SimpleTag extends SimpleTagSupport {
     9 
    10     @Override
    11     public void doTag() throws JspException, IOException {
    12 //        JspFragment jf=getJspBody();
    13 //        jf.invoke(getJspContext().getOut());
    14         
    15         getJspBody().invoke(null);
    16         
    17     }
    18     
    19 }

    JspFragment对象的invoke方法将标签内容输入到给定的流中,如果为null,例如上面代码,则其作用与注释部分代码相同。

    下面以一个获取远程IP地址的代码为例:

     1 package cn.wzbrilliant.el;
     2 
     3 import java.io.IOException;
     4 
     5 import javax.servlet.jsp.JspException;
     6 import javax.servlet.jsp.PageContext;
     7 import javax.servlet.jsp.tagext.SimpleTagSupport;
     8 
     9 public class SimpleTag extends SimpleTagSupport {
    10 
    11     @Override
    12     public void doTag() throws JspException, IOException {
    13         PageContext pageContext=(PageContext)getJspContext();
    14         String ip=pageContext.getRequest().getRemoteAddr();
    15         pageContext.getOut().write(ip);
    16     }
    17     
    18 }

    在WEB-INF目录下建立一个扩展名为tld(Tag Libary Definition)的xml文件。

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <taglib xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     3     xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
     4     version="2.0">
     5 
     6     <tlib-version>1.0</tlib-version>
     7     <short-name>mytag</short-name>
     8     <uri>/WEB-INF/mytag.tld</uri>
     9 
    10     <tag><!-- 描述标签 -->
    11         <description>Show Remote Address</description>
    12         <name>remoteIp</name><!-- 标签名称 -->
    13         <tag-class>cn.wzbrilliant.el.SimpleTag</tag-class>
    14         <body-content>empty</body-content><!-- 指示标签的主体内容:没有就写empty -->
    15     </tag>
    16 
    17 </taglib>

    标签内容与EL函数中tld文件中相似。可以添加多个标签。具体如下:

    taglib:根元素

        tlib-version:版本号
        short-name:引用标签时的短名称。一般与tld文件的文件名一致,好找。
        uri:标签绑定的名称空间。只是一个名字,没有实际的意义。

        tag:定义标签元素

            name:标签的名称。

            tag-class:标签的实现类的全名称。

            body-content:指示标签的主体内容的类型。

                    可选值:empty:没有主体内容。适用于传统和简单标签。

                        JSP:说明JSP文件中能出现什么,标签主体内容中就能出现什么。适用于传统标签。

                        scriptless:说明标签的主体内容不能是java脚本。适用于简单标签。

                        tagdependent:说明标签的主体内容是原封不动的传递给标签处理类的,而不是传递的运算结果


            attribute:定义标签的属性

            name:属性名。对应标签处理类中的setter方法

            required:是否是必须的属性

            rtexprvalue:是否支持表达式(EL或java表达式)。默认是false。


    ③(可选的)在web.xml中对tld文件和名称空间进行映射对应。

    1 <jsp-config>
    2         <taglib>
    3             <taglib-uri>/WEB-INF/mytag.tld</taglib-uri>
    4             <taglib-location>/WEB-INF/mytag.tld</taglib-location>
    5         </taglib>
    6 </jsp-config>

    此处配置与EL函数相同

    ⑤ 在JSP中使用

    首先引入: <%@ taglib uri="/WEB-INF/mytag.tld" prefix="mytag"%> 

    使用方法:在jsp页面中使用: <mytag:remoteIp />  即可输出访问服务器的远程的ip地址

    3.简单标签的原理:

    三、自定义标签实例:

    ①实现JSTL中forEach标签的功能

    类代码如下:

     1 package cn.wzbrilliant.el;
     2 
     3 import java.io.IOException;
     4 import java.lang.reflect.Array;
     5 import java.util.ArrayList;
     6 import java.util.Collection;
     7 import java.util.List;
     8 import java.util.Map;
     9 import java.util.Set;
    10 
    11 import javax.servlet.jsp.JspException;
    12 import javax.servlet.jsp.PageContext;
    13 import javax.servlet.jsp.tagext.SimpleTagSupport;
    14 
    15 public class ForEachTag extends SimpleTagSupport {
    16     private String var;
    17     private Collection items;
    18     
    19     public void setItems(Object items) {
    20         if(items instanceof List){
    21             this.items=(List)items;
    22         }else if(items instanceof Set){
    23             this.items=(Set)items;
    24         }else if(items instanceof Map){
    25             this.items=((Map)items).entrySet();
    26         }else if(items.getClass().isArray()){
    27             this.items=new ArrayList();
    28             int length=Array.getLength(items);
    29             for(int i=0;i<length;i++){
    30                 this.items.add(Array.get(items, i));
    31             }
    32         }else{
    33             throw new RuntimeException("对不起,不支持的类型");
    34         }
    35     }
    36     public void setVar(String var) {
    37         this.var = var;
    38     }
    39     @Override
    40     public void doTag() throws JspException, IOException {
    41         PageContext pageContext=(PageContext) getJspContext();
    42         for(Object obj:items){
    43             pageContext.setAttribute(var, obj);
    44             getJspBody().invoke(null);
    45         }
    46     }
    47     
    48 }

    mytag.tld文件中添加如下内容:

     1 <tag><!-- forEach标签 -->
     2         <description>for each</description>
     3         <name>forEach</name>
     4         <tag-class>cn.wzbrilliant.el.ForEachTag</tag-class>
     5         <body-content>scriptless</body-content>
     6         <attribute>
     7             <name>items</name>
     8             <required>true</required>
     9             <rtexprvalue>true</rtexprvalue>
    10         </attribute>
    11         <attribute>
    12             <name>var</name>
    13             <required>true</required>
    14             <rtexprvalue>true</rtexprvalue>
    15         </attribute>
    16 </tag>

    使用方法:

    1  <%
    2     int[] arr = new int[] {1,2,3,4};
    3 
    4     pageContext.setAttribute("p", arr);
    5  %>
    6         
    7  <mytag:forEach items="${p}" var="v">
    8             ${v}<br>
    9  </mytag:forEach>

    与JSTL中forEach标签使用无异,如此便可遍历数组、集合的元素。

    ②实现JSTL中when  otherwise功能(与if-else结构相似)

    实现用到了父标签。父标签的作用:用于子标签之间数据的传递。

    该例使用了三个标签,分别为choose(父标签),when,otherwise,用三个类实现。

    父标签choose实现类:

     1 package cn.wzbrilliant.el;
     2 
     3 import java.io.IOException;
     4 
     5 import javax.servlet.jsp.JspException;
     6 import javax.servlet.jsp.tagext.SimpleTagSupport;
     7 
     8 public class ChooseTag extends SimpleTagSupport {
     9     private boolean flag=false;
    10     
    11     protected boolean isFlag(){
    12         return flag;
    13     }
    14     
    15     protected void setFlag(boolean flag){
    16         this.flag=flag;
    17     }
    18 
    19     @Override
    20     public void doTag() throws JspException, IOException {
    21 
    22         getJspBody().invoke(null);
    23     }
    24     
    25     
    26 }

    子标签when实现类:

     1 package cn.wzbrilliant.el;
     2 
     3 import java.io.IOException;
     4 
     5 import javax.servlet.jsp.JspException;
     6 import javax.servlet.jsp.tagext.SimpleTagSupport;
     7 
     8 public class WhenTag extends SimpleTagSupport {
     9     private boolean test;
    10     
    11     public void setTest(boolean test){
    12         this.test=test;
    13     }
    14 
    15     @Override
    16     public void doTag() throws JspException, IOException {
    17         if(test){
    18             ChooseTag parent=(ChooseTag)getParent();
    19             parent.setFlag(true);
    20             getJspBody().invoke(null);
    21         }
    22     }
    23     
    24     
    25 }

    子标签otherwise实现类:

     1 package cn.wzbrilliant.el;
     2 
     3 import java.io.IOException;
     4 
     5 import javax.servlet.jsp.JspException;
     6 import javax.servlet.jsp.tagext.SimpleTagSupport;
     7 
     8 public class OtherwiseTag extends SimpleTagSupport {
     9 
    10     @Override
    11     public void doTag() throws JspException, IOException {
    12         ChooseTag parent=(ChooseTag)getParent();
    13         if(!parent.isFlag()){
    14             getJspBody().invoke(null);
    15         }
    16     }
    17     
    18 }

    mytag.tld中添加如下内容:

     1 <tag><!-- choose标签 -->
     2         <description>when otherwise</description>
     3         <name>choose</name>
     4         <tag-class>cn.wzbrilliant.el.ChooseTag</tag-class>
     5         <body-content>scriptless</body-content>
     6 </tag>
     7     
     8 <tag><!-- when标签 -->
     9         <description>when otherwise</description>
    10         <name>when</name>
    11         <tag-class>cn.wzbrilliant.el.WhenTag</tag-class>
    12         <body-content>scriptless</body-content>
    13                 <attribute>
    14             <name>test</name>
    15             <required>true</required>
    16             <rtexprvalue>true</rtexprvalue>
    17         </attribute>
    18 </tag>
    19     
    20 <tag><!-- otherwise标签 -->
    21         <description>when otherwise</description>
    22         <name>otherwise</name>
    23         <tag-class>cn.wzbrilliant.el.OtherwiseTag</tag-class>
    24         <body-content>scriptless</body-content>
    25 </tag>        

    使用方法,在jsp中:

     1 <%
     2     pageContext.setAttribute("p", arr);
     3 %>
     4 
     5         
     6 <mytag:choose>
     7     <mytag:when test="${empty p }">
     8             there is empty
     9     </mytag:when>
    10     <mytag:otherwise>
    11             <mytag:forEach items="${p }" var="v">
    12                     <br>${v}
    13             </mytag:forEach>
    14     </mytag:otherwise>
    15 </mytag:choose>

    html显示文本中html代码的过滤 

    例如留言板中,有时候需要将html代码原样输出,而不解析。

    实现类代码如下:

     1 package cn.wzbrilliant.el;
     2 
     3 import java.io.IOException;
     4 import java.io.StringWriter;
     5 
     6 import javax.servlet.jsp.JspException;
     7 import javax.servlet.jsp.tagext.SimpleTagSupport;
     8 
     9 public class HtmlTextFilterTag extends SimpleTagSupport {
    10 
    11     @Override
    12     public void doTag() throws JspException, IOException {
    13         StringWriter sw=new StringWriter();
    14         getJspBody().invoke(sw);
    15         String content=sw.toString();
    16         content = filter(content);
    17         getJspContext().getOut().write(content);
    18     }
    19 
    20     private String filter(String message) {
    21         if (message == null)
    22             return (null);
    23 
    24         char content[] = new char[message.length()];
    25         message.getChars(0, message.length(), content, 0);
    26         StringBuffer result = new StringBuffer(content.length + 50);
    27         for (int i = 0; i < content.length; i++) {
    28             switch (content[i]) {
    29             case '<':
    30                 result.append("&lt;");
    31                 break;
    32             case '>':
    33                 result.append("&gt;");
    34                 break;
    35             case '&':
    36                 result.append("&amp;");
    37                 break;
    38             case '"':
    39                 result.append("&quot;");
    40                 break;
    41             default:
    42                 result.append(content[i]);
    43             }
    44         }
    45         return (result.toString());
    46     }
    47 }

    mytag.tld中添加如下内容:

    1 <tag><!-- 文本中Html代码过滤标签 -->
    2         <description>htmlfilter</description>
    3         <name>htmlfilter</name>
    4         <tag-class>cn.wzbrilliant.el.HtmlTextFilterTag</tag-class>
    5         <body-content>scriptless</body-content>
    6 </tag>

    使用方式:在jsp页面中输出文本数据时添加此标签便可将文本中html代码原样输出,而不解析。

    ④防盗链标签

    防止别的网站、应用盗链,可以利用EL自定义标签,将请求转向其他URI(自定义的广告等等)

    实现代码如下:

     1 package cn.wzbrilliant.el;
     2 
     3 import java.io.IOException;
     4 
     5 import javax.servlet.http.HttpServletRequest;
     6 import javax.servlet.http.HttpServletResponse;
     7 import javax.servlet.jsp.JspException;
     8 import javax.servlet.jsp.PageContext;
     9 import javax.servlet.jsp.tagext.SimpleTagSupport;
    10 
    11 public class RefererTag extends SimpleTagSupport {
    12     private String site;
    13     private String redirectPath;
    14 
    15     public void setSite(String site) {
    16         this.site = site;
    17     }
    18 
    19     public void setRedirectPath(String redirectPath) {
    20         this.redirectPath = redirectPath;
    21     }
    22 
    23     @Override
    24     public void doTag() throws JspException, IOException {
    25         PageContext pageContext = (PageContext) getJspContext();
    26         HttpServletRequest request = (HttpServletRequest) pageContext.getRequest();
    27         HttpServletResponse response = (HttpServletResponse) pageContext.getResponse();
    28         String referer = request.getHeader("referer");
    29         if (referer != null && !referer.startsWith(site)) {
    30             String path;
    31             if (redirectPath.startsWith("/")) {
    32                 path = request.getContextPath() + redirectPath;
    33             } else {
    34                 String uri=request.getRequestURI();
    35                 path=uri.substring(0, uri.lastIndexOf("/")+1)+redirectPath;
    36             }
    37             response.sendRedirect(path);
    38         }
    39     }
    40 
    41 }

    mytag.tld中添加如下内容:

     1 <tag><!-- 防盗链 -->
     2         <description>referer</description>
     3         <name>referer</name>
     4         <tag-class>cn.wzbrilliant.el.RefererTag</tag-class>
     5         <body-content>empty</body-content>
     6         <attribute>
     7             <name>site</name>
     8             <required>true</required>
     9             <rtexprvalue>true</rtexprvalue>
    10         </attribute>
    11         <attribute>
    12             <name>redirectPath</name>
    13             <required>true</required>
    14             <rtexprvalue>true</rtexprvalue>
    15         </attribute>
    16 </tag>

    使用方法:在防盗链的页面头部添加: <mytag:referer site="http://localhost:8080/JavaWeb" redirectPath="error.jsp"/> ,其中site值为本应用的URI,redirectPath是将外部应用的请求转发的目标地址,可以是相对路径,也可以是绝对路径。

    四、JSTL中的核心标签库(替换掉JSP中的Java脚本)

    c:if

    作用:判断是否为true,如果为true,那么标签的主体内容就会显示。
    属性:test:必须的。要求必须是boolean的。支持表达式(EL或Java表达式)
       var:保存test运算结果的变量
       scope: 保存的域范围。默认是page

    c:forEach

    遍历:数组、List、Set、Map
    属性:items:要遍历的目标对象。支持表达式
       var:变量名。指向当前遍历的集合中的一个元素
       begin:开始的索引(含)
       end:结束的索引(含)
       step:步长。默认是1
       varStatus:取一个名字,引用了一个对象。该对象有以下方法:
            int getIndex():当前记录的索引号。从0开始
            int getCount():当前记录的顺序。从1开始
            boolean isFirst():是否是第一条记录
            boolean isLast():是否是最后一条记录

  • 相关阅读:
    jquery流行的插件收集
    简单遮罩层
    生成任意位数随机验证码
    30个图片浏览插件收集
    [转载]12个jQuery Lightbox效果插件
    jqzoom图片放大镜效果
    23个超流行的jQuery相册插件收集
    在suse上创建UDEV Rules For RAC OCR And Voting Devices
    /etc/fstab文件中的一些参数
    Oracle提供的自治事务记录日志的方法
  • 原文地址:https://www.cnblogs.com/z941030/p/4767712.html
Copyright © 2020-2023  润新知