【el表达式】
EL全名为Expression Language EL主要作用:
获取数据:
EL表达式主要用于替换JSP页面中的脚本表达式,以从各种类型的web域中检索java对象、获取数据。(某个web域中的对象,访问javabean的属性、访问list集合、访问map集合、访问数组)
执行运算:
利用EL表达式可以在JSP页面中执行一些基本的关系运算、逻辑运算和算术运算,以在JSP页面中完成一些简单的运算。${user==null}
获取web开发常用对象
EL表达式定义了一些隐式对象,web开发人员可以很轻松获得对web常用对象的引用,从而获得这些对象中的数据。
调用Java方法
EL表达式允许用户开发定义EL函数,已在JSP页面中通过EL表达式调用Java类的方法。
【获取数据】
使用EL表达式获取数据语法:"${标识符}"
EL表达式语句在执行时,会调用pageContext.findAttribute方法,使用标识符为关键字,分别从page、request、session、application四个域中查找相应对象,找到则返回相应对象,找不到则返回""(注意,不是null,而是空字符串)。
示例:${user}
基本用法如下:
< body > < % //分别在4个域对象中存储数据 pageContext.setAttribute("name1", "唐僧"); session.setAttribute("name2", "猪八戒"); application.setAttribute("name3", "孙悟空"); request.setAttribute("name4", "哆啦A梦"); %> < pre > name1 =${name1} name2 =${name2} name3${name3} name4${name4} </ pre > < h3 > 演示使用er表达式:支持对象的导航 </ h3 > < % User user = new User(); user.setUsername("哆啦A梦"); user.setAge(14); Friend f = new Friend(); f.setName("大雄"); Cat[] ct = new Cat[2]; ct[0]=new Cat("胖虎","黑色"); ct[1]=new Cat("小夫","绿色"); f.setCats(ct); user.setFriend(f); session.setAttribute("user", user); %> < pre > //注意,这样的方式获取的值,相对应的属性必须提供get方法。 获取"哆啦A梦"的名字:${user.username} 或者这样获取:${user["username"]} 获取"年龄":${user["age"] } 获取哆啦A梦朋友的名字:${user.friend.name } 或者这样获取:${user["friend"]["name"] } 获取朋友的第一只猫:${user.friend.cats[0].name } 或者这样获取:${user["friend"]["cats"][0]["name"]} </ pre > < h3 > ER表达式对运算符的支持: </ h3 > < pre > 3+4 =${3+4 } 5*9 =${5*9 } 6/4 =${6/4 } 5/3 =${5/3 } < % session.setAttribute("n", 10); % > n+5 =${n+5 } n/10 =${n/10 } 对一元运算符号的支持:${-n } 对比较运算符的支持:${n> 10 }||${ n ==10 }||${n gt 9 }||${n eq 11 } 对逻辑运算符的支持:${n> 5 && n < 10 }||${n > 5 || n < 10 } 对善缘运算符的支持:${n> 5?"真的":"假的" } < % pageContext.setAttribute("gdy", null); List< String > list = new ArrayList < String > (); list.add("aaaa"); list.add("bbbb"); list.add("cccc"); pageContext.setAttribute("list", list); %> 对empty(是否为null)运算符的支持:${empty gdy }||${not empty gdy } 获取集合中的全部数据${list} 获取集合中的第一个数据${list[0]} </ pre > </ body >
【EL的11个隐式对象】(注意:容易和jsp的隐式对象混淆)
EL表达式 表示类型 备注 对应的jsp内置对象 pageContext javax.servlet.jsp.PageContext 和jsp的内置对象完全一样 pageContext requestScope java.util.Map<String,Object> 代表者ServletRequest中的那个Map 没有 pageScope java.util.Map<String,Object> 代表者PageContext中的那个Map 没有 sessionScope java.util.Map<String,Object> 代表者HttpSession中的那个Map 没有 applicationScope java.util.Map<String,Object> 代表者ServletContext中的那个Map 没有 param java.util.Map<String,String> 代表一个请求参数 没有 paramValues java.util.Map<String,String[]> 代表重命名的请求参数 没有 header java.util.Map<String,String> 代表一个请求消息头 没有 headerValues java.util.Map<String,String[]> 代表重命名的请求消息头 没有 initParam java.util.Map<String,String> 代表web.xml中配置文件的全局参数 没有 cookie java.util.Map<String,Cookie> 获取cookie值的key,是cookie的name,Value是cokie对象本身 没有
param可以直接获取客户端传递过来的值。
例如:
< body > < form action = "${pageContext.request.contextPath }/jsp/ER/JER03.jsp" > 姓名:< input type = "text" name = "username" /> < br > < input type = "submit" value = "提交" /> </ form > </ body >
JER03.jsp通过param获取传递过来的值代码为:
< body > preage获取姓名为:${param.username } </ body >
paramValues可以获取请求参数中同名的数据
用法如下:
< body > < % request.setCharacterEncoding("UTF-8"); % > < form action = "${pageContext.request.contextPath }/jsp/ER/JER03.jsp" method = "post" > 姓名:< input type = "text" name = "username" /> 姓名2< input type = "text" name = "username" /> < br > < input type = "submit" value = "提交" /> </ form > </ body >
JER03.jsp中通过paramValues获取方法为:
< body > < % request.setCharacterEncoding("UTF-8"); % > preage获取姓名为:${param.username }||${param["username"] } < br > el表达式获取表单中同名控件的数据:${paramValues.username[0] }||${paramValues.username[1] } </ body >
el内置对象header获取请求头中的数据Host:${header["Host"] }
el内置对象initParam获取web.xml中的全局配置name1:${initParam.name1 }
el内置对象cookie获取浏览器携带的cookie :${cookie }</br>
el内置对象cookie获取浏览器携带的cookie Jsessionid的key:${cookie.JSESSIONID.name }</br>
el内置对象cookie获取浏览器携带的cookie Jsessionid的value:${cookie.JSESSIONID.value }</br>
【EL表达式-----自定义函数】
自定义函数类代码为:
package com.gdy.jjsp; public class JSELFunction { public static String upper(String str){ return str.toUpperCase(); } }
注意:要想在el表达式中使用自定义函数类中的方法,必须要满足一下几点
1.使用的方法在类函数中必须是静态方法。
2.必须使用后缀为.tld的文件中定义函数,在引用该函数的jsp页面中使用<%@ taglib uri="在tld文件中定义的地址" prefix="名字可以自己定义" %>引入在tld文件中定义的规范。
3.tld文件(即:标签库的描述文件)必须在WEB-INF文件夹里面。但不能在WEB-INF/lib文件夹里面。
在.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 > 描述,注释 </ description > < display-name > gdfunn </ display-name > < tlib-version > 1.1 </ tlib-version > < short-name > gdyfun </ short-name > < uri > com.gdy.function </ uri > < function > < name > upper </ name > < function-class > com.gdy.jjsp.JSELFunction </ function-class > < function-signature > java.lang.String upper(java.lang.String) </ function-signature > </ function > </ taglib >
在页面中引入在tld文件中定义的类的代码为:
< %@ taglib uri = "com.gdy.function" prefix = "fun" % >
在jsp页面中调用的代码为:
< body > < h3 > EL表达式自定义函数${fun:upper("abcD") } </ h3 > </ body >
整个jsp页面源码为:
< %@ page language = "java" import = "java.util.*" pageEncoding = "UTF-8" % > < %@ taglib uri = "com.gdy.function" prefix = "fun" % > < % String path = request .getContextPath(); String basePath = request .getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> < html > < head > < base href = "<%=basePath%>" > < title > EL表达式 </ title > < meta http-equiv = "pragma" content = "no-cache" > < meta http-equiv = "cache-control" content = "no-cache" > < meta http-equiv = "expires" content = "0" > < meta http-equiv = "keywords" content = "keyword1,keyword2,keyword3" > < meta http-equiv = "description" content = "This is my page" > </ head > < body > < h3 > EL表达式自定义函数${fun:upper("abcD") } </ h3 > </ body > </ html >
注意点:
1.在页面${fun:upper("abcD")}表达式中fun是由taglib引入tld的类时后面prefix字段的值决定的,名字可以在引入时自己随便修改。
2.在taglib引入表达式中uri=“com.gdy.function”的值是在tld文件中 <uri>com.gdy.function</uri>属性定义的,该属性的值可以自己随便定义。
3.在tld文件中 <!-- name表示页面上函数的名字 --> <name>upper</name> <!-- function-class定义包名加类名。引用那个内的那个方法 --> <function-class>com.gdy.jjsp.JSELFunction</function-class> <!-- 返回参数和调用方法里面的数据类型都必须用包名和类名全些 --> <function-signature>Java .lang.String upper(java.lang.String)</function-signature>
代码中的<function-class>定义了需要在EL表达式中使用的自定义方法的类。而<function-signature>标签定义了该方法的出入参数和返回参数。注意的是入参和出参的类型必须要使用全路径。
在<name>方法中定义了jsp页面引用该方法后调用该方法时的调用名称。可以和自己定义的类方法名称不一致。但jsp引入方法是必须要使用<name>标签中定义的方法名调用。
由于EL表达式不支持字符串的任何运算,所以在EL表达式中使用自定义函数来解决
自定义标签简介 自定义标签主要用于移除Jsp页面中的java代码。 使用自定义标签移除jsp页面中的java代码,只需要完成以下两步骤 1.编写一个狮蝎Tag接口的java类型(标签接口处理器)。 2.编写标签库描述符(tld)文件,在tld文件中吧标签处理器进行描述。
【EL表达式-----自定义标签】 功能:使用自己定义的标签: 例如要实现使用自己定义的标签来打印出当前时间 自定义的标签为:<my:showTime /> 注意:在定义自定义标签处理类,类必须要继承SimpleTag接口。或者继承实现了SimpleTag接口的类,当页面匹配到自定义标签后,会执行自定义处理类的toTag()方法。
自定义处理类代码为:
package com.gdy.jjsp; import java.io.IOException; import java.util.Date; import javax.servlet.jsp.JspException; import javax.servlet.jsp.JspWriter; import javax.servlet.jsp.PageContext; import javax.servlet.jsp.tagext.SimpleTagSupport; public class JERSimpleTag extends SimpleTagSupport{ @Override public void doTag() throws JspException, IOException { Date dt=new Date(); PageContext pagecontext=(PageContext)getJspContext(); JspWriter out = pagecontext.getOut(); out.write(dt.toLocaleString()); } }
后缀为tld文件的定义关联方法为:
<? xml version = "1.0" encoding = "UTF-8" ?> <!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> < taglib > < tlib-version > 1.0 </ tlib-version > < jsp-version > 1.2 </ jsp-version > < short-name > mygettime </ short-name > < uri > com.gdy.gettime </ uri > < tag > < name > showTime </ name > < tag-class > com.gdy.jjsp.JERSimpleTag </ tag-class > <!-- 主体内容 (即页面自己定义的标签之间的内容) 注意:body-content:的取值内容 JSP:不要考虑。(给传统标签处理类用的) empty:传统和简单标签都能用的。开始标签和结束标签没有主体内容时用。 scriptless:给简单标签用的。开始标签和结束标签有主体内容时用。但是内容不能有< % tagdependent:给简单标签用的。告诉标签处理类,主体内容是普通的文本 --> < body-content > empty </ body-content > <!-- 定义标签属性 < attribute > < name > var </ name > < required > false </ required > < rtexprvalue > false </ rtexprvalue > </ attribute > --> </ tag > </ taglib >
页面jsp引入代码为:
< %@ taglib uri = "com.gdy.gettime" prefix = "my" % >
jsp页面全部代码为:
< %@ page language = "java" import = "java.util.*" pageEncoding = "UTF-8" % > < %@ taglib uri = "com.gdy.function" prefix = "fun" % > < %@ taglib uri = "http://java.sun.com/jsp/jstl/functions" prefix = "gdy" % > < %@ taglib uri = "com.gdy.gettime" prefix = "my" % > < % String path = request .getContextPath(); String basePath = request .getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> < html > < head > < base href = "<%=basePath%>" > < title > EL表达式 </ title > < meta http-equiv = "pragma" content = "no-cache" > < meta http-equiv = "cache-control" content = "no-cache" > < meta http-equiv = "expires" content = "0" > < meta http-equiv = "keywords" content = "keyword1,keyword2,keyword3" > < meta http-equiv = "description" content = "This is my page" > </ head > < body > < h3 > EL表达式自定义函数${fun:upper("abcD") } </ h3 > </ br > < h3 > ${gdy:toUpperCase("aaaaa") } </ h3 > < br /> < hr > < h3 > El表达式之自定义标签 </ h3 > 自定义标签:|< my:showTime /> </ body > </ html >
注意:tld文件的路径和自定义方法的tld文件路径存放规则一样。
自定义标签执行原理
SimpleTag 接口中的方法:
void doTag():由服务器调用。在JSP中遇到标签时调用。
JspTaggetParent():由程序员调用。获取该标签的父标签对象。没有返回null
以下三个方法的共同特点:由服务器调用,在调用doTag之前就调完了。
voidsetJspBody(JspFragment jspBody):由服务器调用。传入标签的内容。
voidsetJspContext(JspContext pc):由服务器调用。传入当前页面的pageContext对象
voidsetParent(JspTag parent):由服务器调用。传入你的爹。没爹传入null
自定义标签的详细功能(基本功)
1.控制页面中某部分内容不显示
2.控制结束标签后的JSP内容不执行
3.控制主体内容重复执行:带属性的标签开发
4.获取标签主体内容,改变后再输出
示例1:控制页面中某部分内容不显示
类的后台代码为:
package com.gdy.jjsp; import java.io.IOException; import javax.servlet.jsp.JspException; import javax.servlet.jsp.tagext.SimpleTagSupport; public class JERSimpleTag02 extends SimpleTagSupport { @Override public void doTag() throws JspException, IOException { } }
tld文件绑定方法为:
< tag > < name > Hide </ name > < tag-class > com.gdy.jjsp.JERSimpleTag02 </ tag-class > < body-content > tagdependent </ body-content > </ tag >
jsp页面引用和调用方法为:
< %@ taglib uri = "com.gdy.gettime" prefix = "my" % >
< body > < h3 > 演示ER表达式 自定义标签隐藏内容 </ h3 > 哈哈,隐藏内容在这< my:Hide > 你看不到我 </ my:Hide > </ body >
页面显示效果为:
示例2:控制结束标签后的JSP内容不执行 java类代码为:
package com.gdy.jjsp; import java.io.IOException; import javax.servlet.jsp.JspException; import javax.servlet.jsp.SkipPageException; import javax.servlet.jsp.tagext.JspFragment; import javax.servlet.jsp.tagext.SimpleTagSupport; public class JERSimpleTag03 extends SimpleTagSupport { @Override public void doTag() throws JspException, IOException { JspFragment body = getJspBody(); body.invoke(null ); throw new SkipPageException(); } }
pld文件关联代码为:
< tag > < name > HideEnd </ name > < tag-class > com.gdy.jjsp.JERSimpleTag03 </ tag-class > < body-content > tagdependent </ body-content > lt;/tag>
jsp页面相关代码为:
< %@ taglib uri = "com.gdy.gettime" prefix = "my" % >
< body > < h3 > 演示ER表达式 自定义标签隐藏内容 </ h3 > 哈哈,隐藏内容在这< my:Hide > 你看不到我 </ my:Hide > < hr > < h4 > 控制结束标签后的JSP内容不执行 </ h4 > 结束标签后的内容不执行< my:HideEnd > 【标签里面内容】 </ my:HideEnd > 【标签后面内容】 </ body >
显示结果为:
页面查看源码为:
可以看到在</my:HideEnd>标签后面的内容都没有输出。
示例3 控制主题的部分内容重复执行
java类代码为:
package com.gdy.jjsp; import java.io.IOException; import javax.servlet.jsp.JspException; import javax.servlet.jsp.tagext.SimpleTagSupport; public class JERSimpleTag04 extends SimpleTagSupport { private int num; public void setNum( int num) { this .num = num; } @Override public void doTag() throws JspException, IOException { for ( int i= 0 ;i< this .num;i++){ getJspBody().invoke(null ); } } }
tld文件配置信息为:
< tag > < name > HideCopy </ name > < tag-class > com.gdy.jjsp.JERSimpleTag04 </ tag-class > < body-content > scriptless </ body-content > < attribute > < name > num </ name > < required > true </ required > < rtexprvalue > true </ rtexprvalue > </ attribute > </ tag >
jsp页面调用代码为:
< hr > < h4 > 控制标签的主体内容重复执行 </ h4 > < my:HideCopy num = "${'8'}" > 我要循环--------- </ br > </ my:HideCopy > < hr >
显示结果为:
示例4:获取主体内容,改变后输出
java处理类代码为:
package com.gdy.jjsp; import java.io.IOException; import java.io.StringWriter; import javax.security.auth.message.callback.PrivateKeyCallback.Request; import javax.servlet.jsp.JspContext; import javax.servlet.jsp.JspException; import javax.servlet.jsp.tagext.JspFragment; import javax.servlet.jsp.tagext.SimpleTagSupport; public class JERSimpleTag05 extends SimpleTagSupport { @Override public void doTag() throws JspException, IOException { JspFragment body = getJspBody(); StringWriter sw=new StringWriter(); body.invoke(sw); String str=sw.toString(); str=str.toUpperCase()+"我已经改变" ; getJspContext().getOut().write(str); } }
tld文件绑定内容为:
< tag > < name > HideTH </ name > < tag-class > com.gdy.jjsp.JERSimpleTag05 </ tag-class > < body-content > tagdependent </ body-content > </ tag >
jsp页面代码为:
< %@ taglib uri = "com.gdy.gettime" prefix = "my" % >
< h4 > 获取标签的主体内容,改变后再输出 </ h4 > 获取标签的主体内容改变后再输出:< my:HideTH > 我是主体内容aaabbbccc </ my:HideTH >
web显示结果为:
示例5:模拟实现if else功能标签
jsp页面代码为:
< %@ taglib uri = "com.gdy.gettime" prefix = "my" % >
< body > < h5 > 控制标签的主体内容是否输出(if else 语句功能) </ h5 > < my:choose > < my:when test = "${5>3}" > 真的 </ my:when > < my:otherwise > 假的 </ my:otherwise > </ my:choose > < br /> < my:choose > < my:when test = "${5<3}" > 真的 </ my:when > < my:otherwise > 假的 </ my:otherwise > </ my:choose > </ body >
tld关联代码为:
<? xml version = "1.0" encoding = "UTF-8" ?> <!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> < taglib > < tlib-version > 1.0 </ tlib-version > < jsp-version > 1.2 </ jsp-version > < short-name > mygettime </ short-name > < uri > com.gdy.gettime </ uri > < tag > < name > choose </ name > < tag-class > com.gdy.jjsp.JERChoose </ tag-class > < body-content > scriptless </ body-content > </ tag > < tag > < name > when </ name > < tag-class > com.gdy.jjsp.JERWhen </ tag-class > < body-content > scriptless </ body-content > < attribute > < name > test </ name > < required > true </ required > < rtexprvalue > true </ rtexprvalue > </ attribute > </ tag > < tag > < name > otherwise </ name > < tag-class > com.gdy.jjsp.JEROtherwise </ tag-class > < body-content > scriptless </ body-content > </ tag > </ taglib >
com.gdy.jjsp.JERChoose内代码为:
package com.gdy.jjsp; import java.io.IOException; import javax.servlet.jsp.JspException; import javax.servlet.jsp.tagext.SimpleTagSupport; public class JERChoose extends SimpleTagSupport{ private boolean flag= true ; public boolean isFlag() { return flag; } public void setFlag( boolean flag) { this .flag = flag; } @Override public void doTag() throws JspException, IOException { getJspBody().invoke(null ); } }
com.gdy.jjsp.JERWhen类代码为:
package com.gdy.jjsp; import java.io.IOException; import javax.servlet.jsp.JspException; import javax.servlet.jsp.tagext.SimpleTagSupport; public class JERWhen extends SimpleTagSupport{ private boolean test; public void setTest( boolean test){ this .test=test; } @Override public void doTag() throws JspException, IOException { if (test){ getJspBody().invoke(null ); JERChoose choose=(JERChoose)getParent(); choose.setFlag(false ); } } }
com.gdy.jjsp.JEROtherwise类代码为:
package com.gdy.jjsp; import java.io.IOException; import javax.servlet.jsp.JspException; import javax.servlet.jsp.tagext.SimpleTagSupport; public class JEROtherwise extends SimpleTagSupport { @Override public void doTag() throws JspException, IOException { JERChoose choose=(JERChoose)getParent(); if (choose.isFlag()){ getJspBody().invoke(null ); } } }
页面显示结果为: