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.0tlib-version>
 6     <short-name>myfnshort-name>
 7     <uri>/WEB-INF/myfn.tlduri>
 8     
 9     <function>
10         <name>toUppername> 
11         <function-class>cn.wzbrilliant.el.ElFunctionfunction-class> 
12         <function-signature>java.lang.String toUpperCase( java.lang.String )function-signature>
13     function>
14     
15 taglib>

值随意

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

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


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

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

 代表一个标签库,可以多个

 tld文件的位置

 


④ 在JSP中使用

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

使用方式如下:

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

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

 

二、EL自定义标签开发

 

自定义标签属于JSP技术

 

1、标签的作用

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

 

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

 

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

EL函数以及自定义标签的应用_第1张图片

 

 

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

 

①编写一个类,直接或间接实现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.0tlib-version>
 7     <short-name>mytagshort-name>
 8     <uri>/WEB-INF/mytag.tlduri>
 9 
10     <tag>
11         <description>Show Remote Addressdescription>
12         <name>remoteIpname>
13         <tag-class>cn.wzbrilliant.el.SimpleTagtag-class>
14         <body-content>emptybody-content>
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.tldtaglib-uri>
4             <taglib-location>/WEB-INF/mytag.tldtaglib-location>
5         taglib>
6 jsp-config>

此处配置与EL函数相同

 

⑤ 在JSP中使用

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

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

 

3.简单标签的原理:

EL函数以及自定义标签的应用_第2张图片

 

三、自定义标签实例:

 

①实现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){
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>
 2         <description>for eachdescription>
 3         <name>forEachname>
 4         <tag-class>cn.wzbrilliant.el.ForEachTagtag-class>
 5         <body-content>scriptlessbody-content>
 6         <attribute>
 7             <name>itemsname>
 8             <required>truerequired>
 9             <rtexprvalue>truertexprvalue>
10         attribute>
11         <attribute>
12             <name>varname>
13             <required>truerequired>
14             <rtexprvalue>truertexprvalue>
15         attribute>
16 tag>

 

使用方法:

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

与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>
 2         <description>when otherwisedescription>
 3         <name>choosename>
 4         <tag-class>cn.wzbrilliant.el.ChooseTagtag-class>
 5         <body-content>scriptlessbody-content>
 6 tag>
 7     
 8 <tag>
 9         <description>when otherwisedescription>
10         <name>whenname>
11         <tag-class>cn.wzbrilliant.el.WhenTagtag-class>
12         <body-content>scriptlessbody-content>
13                 <attribute>
14             <name>testname>
15             <required>truerequired>
16             <rtexprvalue>truertexprvalue>
17         attribute>
18 tag>
19     
20 <tag>
21         <description>when otherwisedescription>
22         <name>otherwisename>
23         <tag-class>cn.wzbrilliant.el.OtherwiseTagtag-class>
24         <body-content>scriptlessbody-content>
25 tag>        

 

使用方法,在jsp中:

 1 <%
 2     pageContext.setAttribute("p", arr);
 3 %>
 4 
 5         
 6 
 7     
 8             there is empty
 9     
10     
11             
12                     
${v} 13
14
15

 

 

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("<");
31                 break;
32             case '>':
33                 result.append(">");
34                 break;
35             case '&':
36                 result.append("&");
37                 break;
38             case '"':
39                 result.append(""");
40                 break;
41             default:
42                 result.append(content[i]);
43             }
44         }
45         return (result.toString());
46     }
47 }

 

 

mytag.tld中添加如下内容:

1 
2         htmlfilter
3         htmlfilter
4         class>cn.wzbrilliant.el.HtmlTextFilterTagclass>
5         scriptless
6 

 

使用方式:在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>refererdescription>
 3         <name>referername>
 4         <tag-class>cn.wzbrilliant.el.RefererTagtag-class>
 5         <body-content>emptybody-content>
 6         <attribute>
 7             <name>sitename>
 8             <required>truerequired>
 9             <rtexprvalue>truertexprvalue>
10         attribute>
11         <attribute>
12             <name>redirectPathname>
13             <required>truerequired>
14             <rtexprvalue>truertexprvalue>
15         attribute>
16 tag>

 

使用方法:在防盗链的页面头部添加:  ,其中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():是否是最后一条记录

转载于:https://www.cnblogs.com/z941030/p/4767712.html

你可能感兴趣的:(EL函数以及自定义标签的应用)