java expression 强制出现_表达式语言 Expression Language

JSP 2.0最重要的特性之一就是表达式语言 (EL),JSP用户可以用它来访问应用程序数据。由于 受到ECMAScript和XPath表达式语言的启发,EL也设计 成可以轻松地编写免脚本的JSP页面。也就是说,页面 不使用任何JSP声明、表达式或者scriptlets。 JSP 2.0最初是将EL应用在JSP标准标签库(JSTL) 1.0规范中。JSP 1.2程序员将标准库导入到他们的应用 程序中,就可以使用EL。JSP 2.0及其更高版本的用户 即使没有JSTL,也能使用EL,但在许多应用程序中, 还是需要JSTL的,因为它里面还包含了与EL无关的其 他标签。 JSP 2.1和JSP 2.2中的EL要将JSP 2.0中的EL与 JSF(JavaServer Faces)中定义的EL统一起来。JSF是 在Java中快速构建Web应用程序的框架,并且是构建在 JSP 1.2之上。由于JSP 1.2中缺乏整合式的表达式语 言,并且JSP 2.0 EL也无法满足JSF的所有需求,因此为 JSF 1.0开发出了一款EL的变体。后来这两种语言变体 合二为一。

一.表达式语言的语法

EL表达式以 ${ 开头,并以 } 结束。EL表达式的结 构如下:

$ { expression}

它们的取值将是从左到右进行,计算结果的类型为 String,并且连接在一起。假如a+b等于8,c+d等于 10,那么这两个表达式的计算结果将是810:

${a+b}${c+d}

表达式${a+b}and${c+d}的取值结果则是8and10

如果在定制标签的属性值中使用EL表达式,那么 该表达式的取值结果字符串将会强制变成该属性需要的 类型:

像${这样的字符顺序就表示是一个EL表达式的开 头。如果需要的只是文本${,则需要在它前面加一个转 义符,如\${。

二.关键字

以下是关键字,它们不能用作标识符:

and eq gt true instanceof

or ne le false empty

not lt ge null div mod

三. [] 和 . 运算符

EL表达式可以返回任意类型的值。如果EL表达式 的结果是一个带有属性的对象,则可以利用[ ]或者.运 算符来访问该属性。“[ ]”和“.”运算符类似; “[ ]”是比较 规范的形式, “.”运算符则比较快捷。 为了访问对象的属性,可以使用以下任意一种形 式:

${object["propertyName"]}

${object.propertyName}

但是,如果propertyName不是有效的Java变量名, 只能使用[ ]运算符。例如,下面这两个EL表达式就可以用来访问隐式对象标题中的HTTP标题host:

${header.host};
${header["host"]};

75a7c79f89ebf3b0ea96b204bee159ee.png

但是,要想访问accept-language标题,则只能使 用“[ ]”运算符,因为accept-language不是一个合法的 Java变量名。如果用“.”运算符访问它,将会导致异常。

${header["accept-language"]};

f36a9513b505feed9c9dc4ef2a275e3f.png

如果对象的属性碰巧返回带有属性的另一个对象, 则既可以用“[ ]” ,也可以用“.”运算符来访问第二个对象 的属性。例如,隐式对象pageContext是表示当前JSP的 PageContext对象。它有request属性,表示 HttpServletRequest。HttpServletRequest带有servletPath 属性。下列几个表达式的结果相同,均能得出 pageContext中HttpServletRequest的servletPath属性值

${pageContext["request"]["servletPath"]}

${pageContext.request["servletPath"]}

${pageContext.request.servletPath}

${pageContext["request"].servletPath}

32e713271a2affb13390b880ffc1c996.png

要访问HttpSession,可以使用以下语法:

${pageContext.session }
${pageContext.session.id }

78219f94f346f017aa0705b3b070f1d7.png

四,取值规则

EL表达式的取值是从左到右进行的。对于expra[expr-b]形式的表达式,其EL表达式的取值方法如下:

如果value-a不是一个Map、List或者 array, 那么,value-a必须是一个JavaBean。在这种情况下,必 须强制value-b为String。如果value-b是value-a的一个可 读属性,则要调用该属性的getter方法,从中返回值。 如果getter方法抛出异常,该表达式就是无效的,否 则,该表达式有效。

五. 访问JavaBean

利用“.”或“[]”运算符,都可以访问 bean 的属性, 其结构如下:

${beanName["propertyName"]}

${beanName.propertyName}

如果该属性是一个带属性的对象,那么同样也可以 利用“.”或“[]”运算符来访问第二个对象的该属性。假如 该属性是一个Map、List或者array,则可以利用和访问 Map值或List成员或array元素的同样规则。

六. EL隐式对象

EL隐式对象

对象

描述

pageContext

这是当前JSP的javax.servlet.jsp.PageContext

initParam

这是一个包含所有环境初始化参数,并用参数名作为key的Map

param

这是一个包含所有请求参数,并用参数名作为key的Map。每个key的值就是指定名称的第一个参数值。因此,如果两个请求参数同名,则只有第一个能够利用param获取值。要想访问同名参数的所有参数值,就得用params代替

paramValues

这是一个包含所有请求参数,并用参数名作为key的Map。每个key的值就是一个字符串数组,其中包含了指定参数名称的所有参数值。就算该参数只有一个值,它也仍然会返回一个带有一个元素的数组

header

这是一个包含请求标题,并用标题名作为key的Map。每个key的值就是指定标题名称的第一个标题。换句话说,如果一个标题的值不止一个,则只返回第一个值。要想获得多个值的标题,得用headerValues对象代替

headerValues

这是一个包含请求标题,并用标题名作为key的Map。每个key的值就是一个字符串数组,其中包含了指定标题名称的所有参数值。就算该标题只有一个值,它也仍然会返回一个带有一个元素的数组

cookie

这是一个包含了当前请求对象中所有Cookie对象的Map。Cookie名称就是key名称,并且每个key都映射到一个Cookie对象

applicationScope

这是一个包含了ServletContext对象中所有属性的Map,并用属性名称作为key

sessionScope

这是一个包含了HttpSession对象中所有属性的Map,并用属性名称作为key

requestScope

这是一个Map,其中包含了当前HttpServletRequest对象中的所有属性,并用属性名称作为key

pageScope

这是一个Map,其中包含了全页面范围内的所有属性。属性名称就是Map的key

1.pageContext

pageContext 对象表示当前页面的javax.servlet.jsp.PageContext. 它包含了所有的其他的JSP隐式对象

JSP隐式对象

对象

EL中的类型

request

javax.servlet.http.HttpServletRequest

response

javax.servlet.http.HttpServletResponse

Out

javax.servlet.jsp.JspWriter

session

javax.servlet.http.HttpSession

application

javax.servlet.ServletContext

config

javax.servlet.ServletConfig

PageContext

javax.servlet.jsp.PageContext

page

javax.servlet.jsp.HttpJspPage

exception

java.lang.Throwable

例如,可以利用以下任意一个表达式来获取当前的 ServletRequest:

${pageContext.request}

${pageContext["request"]

并且,还可以利用以下任意一个表达式来获取请求 方法:

${pageContext["request"]["method"]}

${pageContext["request"].method}

${pageContext.request["method"]}

${pageContext.request.method}

2.initParam

隐式对象initParam用于获取上下文参数的值,例如,为了获取名为password的上下文的值,可以使用以下表达式

${initParam.password}

${initParam["password"]

3.Param

隐式对象param用于获取请求参数值。这个对象表 示一个包含所有请求参数的Map。例如,要获取 userName参数,可以使用以下任意一种表达式:

${param.userName} //获取url ? 号后的param的值

${param["userName"]}

4.ParamValues

利用隐式对象paramValues可以获取一个请求参数 的多个值。这个对象表示一个包含所有请求参数,并以 参数名称作为key的Map。每个key的值是一个字符串数 组,其中包含了指定参数名称的所有值。即使该参数只 有一个值,它也仍然返回一个带有一个元素的数组。例 如,为了获得selectedOptions参数的第一个值和第二个 值,可以使用以下表达式:

${paramValues.selectedOptions[0]}

${paramValues.selectedOptions[1]}

例: url为 http://localhost:8080/jspTest1/NewFile.jsp?text=sss&text=sss2

jsp为 ${paramValues.text[1]}

显示

40cf0d6f81c2e67ef1f5a992dde793b2.png

5. header

隐式对象header表示一个包含所有请求标题的 Map。为了获取header值,要利用header名称作为key。 例如,为了获取accept-language这个header值,可以使 用以下表达式:

${header["accept-language"]

如果header名称是一个有效的Java变量名,如 connection,那么也可以使用“. ”运算符:

${header.connection}

隐式对象headerValues表示一个包含所有请求 head,并以header名称作为key的Map。但是,与head不 同的是,隐式对象headerValues返回的Map返回的是一 个字符串数组。例如,为了获取标题accept-language的 第一个值,要使用以下表达式:

${headerValues["accept-language"][0]}

6. cookie

隐式对象cookie可以用来获取一个cookie。这个对 象表示当前HttpServletRequest中所有cookie的值。例 如,为了获取名为jsessionid的cookie值,要使用以下表 达式:

${cookie.jsessionid.value}

为了获取jsessionid cookie的路径值,要使用以下表 达式:

${cookie.jsessionid.path}

7.applicationScope, sessionScope, requestScope, pageScope

隐式对象applicationScope用于获取应用程序范围级 变量的值。假如有一个应用程序范围级变量myVar,就 可以利用以下表达式来获取这个属性:

${applicationScope.myVar}

例:

jsp页面

${pageScope.today}

显示

59c10aaca6e65c52b639594d9b393828.png

注意,在servlet/JSP编程中,有界对象是指在以下 对象中作为属性的对象:PageContext、 ServletRequest、HttpSession或者ServletContext。隐式对 象sessionScope、requestScope和pageScope与 applicationScope相似。但是,其范围分别为session、 request和page。 有界对象也可以通过没有范围的EL表达式获取。 在这种情况下,JSP 容器将返回PageContext、 ServletRequest、HttpSession或者ServletContext中第一个 同名的对象。执行顺序是从最小范围(PageContext) 到最大范围(ServletContext)。例如,以下表达式将返 回today引用的任意范围的对象:

${today}

七. 使用其他EL运算符

除了“.”和“[]”运算符外,EL还提供了其他运算符: 算术运算符、关系运算符、逻辑运算符、条件运算符以 及empty运算符。使用这些运算符时,可以进行不同的 运算。但是,由于EL的目的是方便免脚本JSP页面的编 程,因此,除了关系运算符外,这些EL运算符的用处 都很有限。

1. 算术运算符

i)算术运算符有5种:

加法(+) 减法(−) 乘法(*) 除法(/和div) 取余/取模(%和mod)

除法和取余运算符有两种形式,与XPath和 ECMAScript是一致的。

ii)注意,EL表达式的计算按优先级从高到低、从左 到右进行。下列运算符是按优先级递减顺序排列的:

* 、/、div、%、mod、 //这一级运算符的优先级相同

+ 、-  //这一级的优先级小于第一级

2.逻辑运算符

逻辑运算符: 和(&&和and) 或(|| 和or) 非(!和not)

3.关系运算符

关系运算符列表

等于(=和eq)

不等于(!=和ne)

大于(>和gt)

大于等于(>=和ge)

小于(

小于等于(<=和le)

例如,表达式${3==4}返回False,${“b”

${statement? A:B} //三目运算符

4.emty运算符

empty运算符用来检查某一个值是否为null或者 empty。下面是一个empty运算符的使用范例

jsp页面

${empty today1}

浏览器显示

4872fc40b2e26af1c713a90b12016110.png

八.  应用EL

示例app04a包含了一个JSP页面,该页面通过EL访 问一个JavaBean(Address,详见清单4.1)并输出该 bean的属性。该bean对象是另一个 JavaBean(Employee,详见清单4.2)的一个属性,并 用EL访问一个Map对象的内容,以及HTTP头部信息和 会话标识。EmployeeServlet 类(详见清单4.3)创建了 所需的对象,并将这些对象放入到ServletRequest中, 然后通过RequestDispatcher跳转到employee.jsp页面。

Address类

package model;public classAddress {privateString streetName;privateString streetNumber;privateString city;privateString state;privateString zipCode;privateString country;public String getStreetName() { return this.streetName ;}public void setStreetName(String streetName) { this.streetName=streetName;}public String getStreetNumber() { return this.streetNumber; }public void setStreetNumber(String streetNumber) { this.streetNumber =streetNumber;}public String getCity() { return this.city; }public void setCity(String city) { this.city =city ; }public String getState() { return this.state; }public void setState(String state) { this.state =state; }public String getZipCode() { return this.zipCode;}public void setZipCode(String zipCode) { this.zipCode =zipCode; }public String getCountry() { return this.country; }public void setCountry(String country) { this.country =country; }

}

Employee类

package model;public classEmployee {private intid;privateString name;privateAddress address;public int getId() { return this.id; }public void setId(int id) { this.id =id ;}public String getName() { return this.name; }public void setName(String name) { this.name =name; }public Address getAddress() { return this.address; }public void setAddress(Address address) { this.address =address; }

}

EmployeeServlet类

package servlet;

import java.io.IOException;

import java.util.HashMap;

import java.util.Map;

import javax.servlet.RequestDispatcher;

import javax.servlet.ServletException;

import javax.servlet.annotation.WebServlet;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import model.*;

@WebServlet(urlPatterns= { "/employee"})public classEmployeeServlet extends HttpServlet{private static final long serialVersionUID = 10L;

@Overridepublic voiddoGet(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {

Address address= newAddress();

address.setStreetName("Rue");

address.setStreetNumber("509ab");

address.setCity("Brossard");

address.setState("Quebec");

address.setZipCode("A1A B2b");

address.setCountry("canada");

Employee employee= newEmployee();

employee.setId(1099);

employee.setName("charles");

employee.setAddress(address);

request.setAttribute("employee",employee);

Map capitals = new HashMap();

capitals.put("China" ,"Beijing");

capitals.put("Austria","Vienna");

capitals.put("Australia","Canberra");

capitals.put("Canada","Ottua");

request.setAttribute("capitals", capitals);/*定义一个对象,该对象接收来自客户端的请求,并将它们发送到服务器上的任何资源(例如servlet,HTML文件或JSP文件)。servlet容器创建RequestDispatcher对象,该对象用作位于特定路径或由特定名称给定的服务器资源的包装器。

此接口旨在包装servlet,但servlet容器可以创建RequestDispatcher 对象以包装任何类型的资源。*/RequestDispatcher rd= request.getRequestDispatcher("/employee.jsp");/*将来自servlet的请求转发到服务器上的另一个资源(servlet,JSP文件或HTML文件)。*/rd.forward(request,response);

}

}

employee.jsp

//employee.jsp

Employee
session id: ${pageContext.session.id }
employee: ${requestScope.employee.name}, ${employee.address.city}
capital: ${capitals["Canada"]}

浏览器显示结果

75c8a3b1cbcd3ce9b6c3f5e6565bd84d.png

请注意,在app04a中使用一个servlet和JSP页面来 显示JavaBean属性和其他值符合现代Web应用程序的推 荐的设计,在第16章中会进一步讨论。 要特别注意在JSP页面的EL表达式中,对于request 域的employee对象的访问,可以是显式的,也可以是隐 式的.

九.如何在就jsp2.0 及其更高版本中配置EL

有了EL、JavaBeans和定制标签,就可以编写免脚 本的JSP页面了。JSP 2.0及其更高的版本中还提供了一 个开关,可以使所有的JSP页面都禁用脚本。现在,软件架构师们可以强制编写免脚本的JSP页面了。 另一方面,在有些情况下,可能还会需要在应用程 序中取消EL。例如,正在使用与JSP 2.0兼容的容器, 却尚未准备升级到JSP 2.0,那么就需要这么做。在这 种情况下,可以关闭EL表达式的计算。

1. 实现免脚本的JSP页面

为了关闭JSP页面中的脚本元素,要使用jspproperty-group元素以及url-pattern和scripting- invalid两 个子元素。url-pattern元素定义禁用脚本要应用的URL 样式。下面示范如何将一个应用程序中所有JSP页面的 脚本都关闭:

web.xml   ---- 主要web.xml修改后要重启服务器

*.jsp

true

true //此项不知到要不要加

true

注意: 在部署描述符中只能有一个jsp-config元素。如果已经为禁用EL而 定义了一个jsp-property-group,就必须在同一个jsp-config元素下,为禁用脚本而编写jsp-property- group。

十. 禁用EL计算

在某些情况下,比如,当需要在JSP 2.0及其更高版 本的容器中部署JSP 1.2应用程序时,可能就需要禁用 JSP页面中的EL计算了。此时,一旦出现EL架构,就不 会作为一个EL表达式进行计算。目前有两种方式可以 禁用JSP中的EL计算。 第一种,可以将page指令的isELIgnored属性设为 True,如下:

第二种,可以在部署描述符中使用jsp-propertygroup元素。jsp-property-group元素是jsp- config元素的 子元素。利用jsp-property-group可以将某些设置应用到 应用程序中的一组JSP页面中。 为了利用 jsp-property-group 元素禁用EL计算,还 必须有url-pattern 和 el-ignored两个子元素。url-pattern 元素用于定义EL禁用要应用的URL样式。el-ignored元 素必须设为True。

下面举一个例子,示范如何在名为noEI.jsp的JSP页 面中禁用EL计算:

/noEl.jsp

true

也可以像下面这样,通过给 url-pattern 元素赋值 *.jsp,来禁用一个应用程序中所有 JSP页面的EL计算:

*.jsp

true

无论是将其page指令的isELIgnored属性设为True, 还是将其URL与子元素el-ignored设为True的jspproperty-group元素中的模式相匹配,都将禁用JSP页面 中的EL计算。假如将一个JSP页面中page指令的 isELIgnored属性设为False,但其URL与在部署描述符 中禁用了EL计算的JSP页面的模式匹配,那么该页面的 EL计算也将被禁用。 此外,如果使用的是与Servlet 2.3及其更低版本兼 容的部署描述符,那么EL计算已经默认关闭,即便使 用的是JSP 2.0及其更高版本的容器,也一样

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java Unified Expression Language(JUEL)是一个基于 Java表达式语言,它提供了一组语法规则和函数库,可以用于在 Java 应用程序中动态地计算、处理和生成字符串、数字、布尔值和对象等数据类型。以下是一些 JUEL 的使用案例: 1. 在 JSP 页面中使用 JUEL 表达式生成动态 HTML 内容: ``` <ul> <c:forEach var="item" items="${items}"> <li>${item.name} - ${item.price}</li> </c:forEach> </ul> ``` 在这个例子中,`${item.name}`和`${item.price}`是 JUEL 表达式,它们会动态地计算出每个商品的名称和价格,并将它们插入到 HTML 中。 2. 在 JSF 应用程序中使用 JUEL 表达式进行表单验证: ``` <h:inputText id="email" value="#{user.email}" required="true" validator="#{emailValidator.validate}"> <f:ajax event="blur" render="emailMessage" /> </h:inputText> <h:message id="emailMessage" for="email" /> ``` 在这个例子中,`#{user.email}`是一个 JUEL 表达式,它会动态地计算出当前用户输入的电子邮件地址,并将它存储在一个名为`email`的属性中。在这个表单中,`email`属性是一个必填字段,所以我们使用了`required="true"`属性来指定它是必填的。同时,我们还使用了一个名为`emailValidator`的验证器来检查用户输入的电子邮件地址是否合法。`emailValidator`是一个包含了验证逻辑的 Java 类,它会在用户提交表单时被调用。 3. 在 Java 应用程序中使用 JUEL 表达式进行动态计算: ``` ExpressionFactory factory = new ExpressionFactoryImpl(); SimpleContext context = new SimpleContext(); context.setVariable("x", factory.createValueExpression(2, int.class)); context.setVariable("y", factory.createValueExpression(3, int.class)); ValueExpression expression = factory.createValueExpression(context, "#{x + y}", int.class); int result = (int) expression.getValue(context); System.out.println(result); // 输出 5 ``` 在这个例子中,我们使用了 JUEL 的 API 来创建了一个包含了表达式`${x + y}`的 JUEL 表达式。然后,我们将变量`x`和`y`绑定到了上下文中,并通过表达式的`getValue()`方法动态地计算表达式的值。最后,我们将计算出的结果输出到了控制台上。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值