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

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

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

 package cn.wzbrilliant.el;

 public class ElFunction {
public static String toUpperCase(String str){
return str.toUpperCase();
}
}

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

 <?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>/WEB-INF/myfn.tld</uri> <function><!-- 定义函数 -->
<name>toUpper</name> <!-- 调用名称 -->
<function-class>cn.wzbrilliant.el.ElFunction</function-class> <!-- 类全名 -->
<function-signature>java.lang.String toUpperCase( java.lang.String )</function-signature>
</function> </taglib>

<tlib-version>值随意

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

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

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

 <jsp-config>
<taglib>
<taglib-uri>/WEB-INF/myfn.tld</taglib-uri>
<taglib-location>/WEB-INF/myfn.tld</taglib-location>
</taglib>
</jsp-config>

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

<taglib-location> tld文件的位置

④ 在JSP中使用

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

使用方式如下:

 <%
pageContext.setAttribute("p", "abcdef");
%> ${myfn:toUpper(h) } <br/>
${myfn:toUpper("abcdef") }

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

二、EL自定义标签开发

自定义标签属于JSP技术

1、标签的作用

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

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

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

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

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

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

 package cn.wzbrilliant.el;

 import java.io.IOException;

 import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.SimpleTagSupport; public class SimpleTag extends SimpleTagSupport { @Override
public void doTag() throws JspException, IOException {
// JspFragment jf=getJspBody();
// jf.invoke(getJspContext().getOut()); getJspBody().invoke(null); } }

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

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

 package cn.wzbrilliant.el;

 import java.io.IOException;

 import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.SimpleTagSupport; public class SimpleTag extends SimpleTagSupport { @Override
public void doTag() throws JspException, IOException {
PageContext pageContext=(PageContext)getJspContext();
String ip=pageContext.getRequest().getRemoteAddr();
pageContext.getOut().write(ip);
} }

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

 <?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>mytag</short-name>
<uri>/WEB-INF/mytag.tld</uri> <tag><!-- 描述标签 -->
<description>Show Remote Address</description>
<name>remoteIp</name><!-- 标签名称 -->
<tag-class>cn.wzbrilliant.el.SimpleTag</tag-class>
<body-content>empty</body-content><!-- 指示标签的主体内容:没有就写empty -->
</tag> </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文件和名称空间进行映射对应。

 <jsp-config>
<taglib>
<taglib-uri>/WEB-INF/mytag.tld</taglib-uri>
<taglib-location>/WEB-INF/mytag.tld</taglib-location>
</taglib>
</jsp-config>

此处配置与EL函数相同

⑤ 在JSP中使用

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

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

3.简单标签的原理:

三、自定义标签实例:

①实现JSTL中forEach标签的功能

类代码如下:

 package cn.wzbrilliant.el;

 import java.io.IOException;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set; import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.SimpleTagSupport; public class ForEachTag extends SimpleTagSupport {
private String var;
private Collection items; public void setItems(Object items) {
if(items instanceof List){
this.items=(List)items;
}else if(items instanceof Set){
this.items=(Set)items;
}else if(items instanceof Map){
this.items=((Map)items).entrySet();
}else if(items.getClass().isArray()){
this.items=new ArrayList();
int length=Array.getLength(items);
for(int i=0;i<length;i++){
this.items.add(Array.get(items, i));
}
}else{
throw new RuntimeException("对不起,不支持的类型");
}
}
public void setVar(String var) {
this.var = var;
}
@Override
public void doTag() throws JspException, IOException {
PageContext pageContext=(PageContext) getJspContext();
for(Object obj:items){
pageContext.setAttribute(var, obj);
getJspBody().invoke(null);
}
} }

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

 <tag><!-- forEach标签 -->
<description>for each</description>
<name>forEach</name>
<tag-class>cn.wzbrilliant.el.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>

使用方法:

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

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

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

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

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

父标签choose实现类:

 package cn.wzbrilliant.el;

 import java.io.IOException;

 import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.SimpleTagSupport; public class ChooseTag extends SimpleTagSupport {
private boolean flag=false; protected boolean isFlag(){
return flag;
} protected void setFlag(boolean flag){
this.flag=flag;
} @Override
public void doTag() throws JspException, IOException { getJspBody().invoke(null);
} }

子标签when实现类:

 package cn.wzbrilliant.el;

 import java.io.IOException;

 import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.SimpleTagSupport; public class WhenTag extends SimpleTagSupport {
private boolean test; public void setTest(boolean test){
this.test=test;
} @Override
public void doTag() throws JspException, IOException {
if(test){
ChooseTag parent=(ChooseTag)getParent();
parent.setFlag(true);
getJspBody().invoke(null);
}
} }

子标签otherwise实现类:

 package cn.wzbrilliant.el;

 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 parent=(ChooseTag)getParent();
if(!parent.isFlag()){
getJspBody().invoke(null);
}
} }

mytag.tld中添加如下内容:

 <tag><!-- choose标签 -->
<description>when otherwise</description>
<name>choose</name>
<tag-class>cn.wzbrilliant.el.ChooseTag</tag-class>
<body-content>scriptless</body-content>
</tag> <tag><!-- when标签 -->
<description>when otherwise</description>
<name>when</name>
<tag-class>cn.wzbrilliant.el.WhenTag</tag-class>
<body-content>scriptless</body-content>
<attribute>
<name>test</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag> <tag><!-- otherwise标签 -->
<description>when otherwise</description>
<name>otherwise</name>
<tag-class>cn.wzbrilliant.el.OtherwiseTag</tag-class>
<body-content>scriptless</body-content>
</tag>

使用方法,在jsp中:

 <%
pageContext.setAttribute("p", arr);
%> <mytag:choose>
<mytag:when test="${empty p }">
there is empty
</mytag:when>
<mytag:otherwise>
<mytag:forEach items="${p }" var="v">
<br>${v}
</mytag:forEach>
</mytag:otherwise>
</mytag:choose>

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

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

实现类代码如下:

 package cn.wzbrilliant.el;

 import java.io.IOException;
import java.io.StringWriter; import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.SimpleTagSupport; public class HtmlTextFilterTag extends SimpleTagSupport { @Override
public void doTag() throws JspException, IOException {
StringWriter sw=new StringWriter();
getJspBody().invoke(sw);
String content=sw.toString();
content = filter(content);
getJspContext().getOut().write(content);
} private String filter(String message) {
if (message == null)
return (null); char content[] = new char[message.length()];
message.getChars(0, message.length(), content, 0);
StringBuffer result = new StringBuffer(content.length + 50);
for (int i = 0; i < content.length; i++) {
switch (content[i]) {
case '<':
result.append("&lt;");
break;
case '>':
result.append("&gt;");
break;
case '&':
result.append("&amp;");
break;
case '"':
result.append("&quot;");
break;
default:
result.append(content[i]);
}
}
return (result.toString());
}
}

mytag.tld中添加如下内容:

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

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

④防盗链标签

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

实现代码如下:

 package cn.wzbrilliant.el;

 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.tagext.SimpleTagSupport; public class RefererTag extends SimpleTagSupport {
private String site;
private String redirectPath; public void setSite(String site) {
this.site = site;
} public void setRedirectPath(String redirectPath) {
this.redirectPath = redirectPath;
} @Override
public void doTag() throws JspException, IOException {
PageContext pageContext = (PageContext) getJspContext();
HttpServletRequest request = (HttpServletRequest) pageContext.getRequest();
HttpServletResponse response = (HttpServletResponse) pageContext.getResponse();
String referer = request.getHeader("referer");
if (referer != null && !referer.startsWith(site)) {
String path;
if (redirectPath.startsWith("/")) {
path = request.getContextPath() + redirectPath;
} else {
String uri=request.getRequestURI();
path=uri.substring(0, uri.lastIndexOf("/")+1)+redirectPath;
}
response.sendRedirect(path);
}
} }

mytag.tld中添加如下内容:

 <tag><!-- 防盗链 -->
<description>referer</description>
<name>referer</name>
<tag-class>cn.wzbrilliant.el.RefererTag</tag-class>
<body-content>empty</body-content>
<attribute>
<name>site</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>redirectPath</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</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():是否是最后一条记录

EL函数以及自定义标签的应用的更多相关文章

  1. 10.自定义EL函数和自定义标签

    需要在JSP页面中进行一些常见逻辑操作(如对字符串进行操作),首先考虑是否可以用到sun公司提供的EL函数库(fn.tld)和JSTL 核心标签库 如果sun公司的EL函数库没有或者无法满足,就需要自 ...

  2. EL函数和自定义EL函数

    简介 EL原本是JSTL1.0中的技术(所以EL和JSTL感情如此好就是自然的了),但是从JSP2.0开始,EL就分离出来纳入了JSP的标准了.但是EL函数还是和JSTL技术绑定在一起.下面将介绍如何 ...

  3. 【JSP】EL函数和自定义EL函数

    简介 EL原本是JSTL1.0中的技术(所以EL和JSTL感情如此好就是自然的了),但是从JSP2.0开始,EL就分离出来纳入了JSP的标准了.但是EL函数还是和JSTL技术绑定在一起.下面将介绍如何 ...

  4. [原创]java WEB学习笔记42:带标签体的自定义标签,带父标签的自定义标签,el中自定义函数,自定义标签的小结

    本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当 ...

  5. 自定义EL函数、自定义JSTL标签

    自定义EL函数 1.做一个类(静态) package com.maya.el; public class ELBiaoDaoShi { public static String TiHuan(Stri ...

  6. JavaWeb(七):EL表达式、自定义标签和JSTL

    一.EL表达式 语法 el.jsp <%@page import="java.util.Date"%> <%@page import="com.atgu ...

  7. EL表达式 JSTL中的常用EL函数 动态数据的国际化

    ELppt: EL 全名为Expression Language.EL主要作用: 获取数据: •EL表达式主要用于替换JSP页面中的脚本表达式,以从各种类型的web域 中检索java对象.获取数据.( ...

  8. Java Web 自定义标签

    1.   自定义标签 由于在JSP页面中直接嵌入Java代码会导致页面开起来非常混乱,不方便和美工等配合工作,为此,JSP提供了自定义标签技术,可以代替直接嵌入Java代码的方式提供动态逻辑,但自定义 ...

  9. python 全栈开发,Day70(模板自定义标签和过滤器,模板继承 (extend),Django的模型层-ORM简介)

    昨日内容回顾 视图函数: request对象 request.path 请求路径 request.GET GET请求数据 QueryDict {} request.POST POST请求数据 Quer ...

随机推荐

  1. tyvj1125 JR's chop

    描述 JR有很多双筷子.确切的说应该是很多根,因为筷子的长度不一,很难判断出哪两根是一双的.JR家里来了K个客人,JR留下他们吃晚饭.加上JR,JR的girl friend和JR的朋友内涵,共K+3个 ...

  2. soj杂题

    unique()函数是一个去重函数,STL中unique的函数 unique的功能是去除相邻的重复元素(只保留一个),还有一个容易忽视的特性是它并不真正把重复的元素删除.他是c++中的函数,所以头文件 ...

  3. linux内核调度算法(2)--CPU时间片如何分配 转!

    http://blog.csdn.net/russell_tao/article/details/7103012 内核在微观上,把CPU的运行时间分成许多分,然后安排给各个进程轮流运行,造成宏观上所有 ...

  4. jenkins自动化构建iOS应用配置过程中遇到的问题

    最近配置jenkins来自动构建iOS应用,期间遇上不少问题.在这里分享给大家,也给自己留个底,方便下次解决问题. 首先说明下基本情况,我们因为部署jenkins的机器不是Mac,所以不能安装Xcod ...

  5. php之JavaScript

    JS对于大小写敏感 作用:增加跟html页面的交互性. 应用:验证表单.创建cookies(可插入html页面的编程代码)js插入页面后可由所有现代的浏览器执行.应用于<body>< ...

  6. 刷了MIUI的手机在OSX下连接USB调试的方法

    OSX下默认连接不上小米手机或者刷了MIUI的手机. 办法是: 1, 关于本机->系统报告->USB,在其中找到手机设备,然后查看其厂商ID,复制. 2,控制台执行下面这个命令,把其中的0 ...

  7. from collections import OrderedDict

    在python中,dict这个数据结构由于hash的特性,是无序的,这在有时候会给我们带来一些麻烦,幸运的是, collections模块为我们提供了OrderdDict,当你要获取一个有序的字典对象 ...

  8. PHP PDO的FETCH_NUM、FETCH_BOTH、FETCH_ASSOC

    不容易混淆的有:FETCH_CLASS,FETCH_COLUMN,FETCH_OBJ... 数据库的连接准备部分 $dsn = 'mysql:host=127.0.0.1;port=3306;dbna ...

  9. SoapUI 设置 request data with json body

    --背景 使用WCF定义REST风格的WebService,如下: [ServiceContract]    public interface INISTService    {        [Op ...

  10. [jquery]折叠指定条件的表格

    最近在做财务报表时候,一些表格要做特定折叠效果 这里通过2个自定义属性来对表格之间的属性作关联 date-head和date-num,输出表格时候,可以按照这2个自定义属性给某些带父子层级关系的内容指 ...