Introduction to JSF EL 2 – JSF EL 2简介

最后修改: 2016年 7月 11日

中文/混合/英文(键盘快捷键:t)

1. Introduction

1.介绍

Expression Language (EL), is a scripting language that’s seen adoption within many Java frameworks, such as Spring with SpEL and JBoss with JBoss EL.

表达式语言(EL)是一种脚本语言,在许多Java框架中被采用,如Spring与SpEL和JBoss与JBoss EL。

In this article, we’ll focus at the JSF’s implementation of this scripting language – Unified EL.

在这篇文章中,我们将重点讨论JSF对这种脚本语言的实现–统一EL。

EL is currently in version 3.0, a major upgrade that allows the processing engine to be used in standalone mode – for example, on the Java SE platform. Prior versions were dependent on a Jakarta EE-compliant application server or web container. This article discusses EL version 2.2.

EL目前处于3.0版本,这是一个重大的升级,允许处理引擎以独立模式使用–例如,在Java SE平台上。之前的版本依赖于符合Jakarta EE的应用服务器或Web容器。本文讨论的是EL 2.2版本。

2. Immediate and Deferred Evaluation

2.立即评价和推迟评价

The primary function of EL in JSF is to connect the JSF view (usually XHTML markup) and the java-based back-end. The back-end can be user-created managed beans, or container-managed objects like the HTTP session.

JSF中EL的主要功能是连接JSF视图(通常是XHTML标记)和基于java的后端。后端可以是用户创建的管理Bean,也可以是HTTP会话等容器管理的对象。

We will be looking at EL 2.2. EL in JSF comes in two general forms, immediate syntax EL and deferred syntax EL.

我们将看一下EL 2.2。JSF中的EL一般有两种形式,即即时语法EL和延迟语法EL。

2.1. Immediate Syntax EL

2.1.即时语法EL

Otherwise known as JSP EL, this is a scripting format that’s a holdover from the JSP days of java web application development.

也被称为JSP EL,这是一种脚本格式,是java网络应用程序开发的JSP时代的遗留问题。

The JSP EL expressions start with the dollar sign ($), then followed by the left curly bracket ({), then followed by the actual expression, and finally closed with the right curly bracket (}):

JSP的EL表达式以美元符号($)开始,然后是左大括号({),接着是实际表达式,最后以右大括号(})结束。

${ELBean.value > 0}

This syntax:

这个语法。

  1. Is evaluated only once (at the beginning) in the lifecycle of a page. What this means is that the value that is. Being read by the expression in the example above must be set before the page is loaded.
  2. Provides read-only access to bean values.
  3. And as a result, requires adherence to the JavaBean naming convention.

For most uses, this form of EL is not very versatile.

对于大多数用途来说,这种形式的EL的用途不是很广。

2.2. Deferred Execution EL

2.2.推迟执行的EL

Deferred Execution EL is the EL designed for JSF proper. It’s major syntactical difference with JSP EL is that it’s marked with a “#” instead of a “$“.

延迟执行EL是为JSF本身设计的EL。它与JSP EL在语法上的主要区别是,它用”#”而不是”$“标记。

#{ELBean.value > 0}

Deferred EL:

递延EL。

  1. Is in sync with the JSF lifecycle. This means that an EL expression in deferred EL is evaluated at different points in the rendering of a JSF page (at the beginning and the end).
  2. Provides read and write access to bean values. This allows one to set a value in a JSF backing-bean (or anywhere else) using EL.
  3. Allows a programmer to invoke arbitrary methods on an object and depending on the version of EL, pass arguments to such methods.

Unified EL is the specification that unifies both deferred EL and JSP EL, allowing both syntax in the same page.

统一EL是统一了延迟EL和JSP EL的规范,允许在同一页面中使用两种语法。

3. Unified EL

3.统一的EL

Unified EL allows two general flavors of expressions, value expressions and method expressions.

统一EL允许两种类型的表达式,值表达式和方法表达式。

And a quick note – the following sections will show some examples, which are all available in the app (see the Github link at the end) by navigating to:

还有一个简单的说明–下面的章节将展示一些例子,这些例子都可以在应用程序中找到(见结尾的Github链接),可以浏览到。

http://localhost:8080/jsf/el_intro.jsf

3.1. Value Expressions

3.1.价值表达式

A value expression allows us to either read or set a managed bean property, depending on where it’s placed.

一个值表达式允许我们读取或设置一个托管Bean的属性,这取决于它的位置。

The following expression reads a managed bean property onto the page:

下面的表达式将一个托管Bean的属性读到了页面上。

Hello, #{ELBean.firstName}

The following expression however, allows us to set a value on the user object:

然而,下面的表达式允许我们在用户对象上设置一个值。

<h:inputText id="firstName" value="#{ELBean.firstName}" required="true"/>

The variable must follow JavaBean naming convention to be eligible for this kind of treatment. For the value of the bean to be committed, the enclosing form just needs to be saved.

变量必须遵循JavaBean的命名规则才有资格得到这种处理。为了使Bean的值被提交,只需要保存包围的表单。

3.2. Method Expressions

3.2.方法表达式

Unified EL provides method expressions to execute public, non-static methods from within a JSF page. The methods may or may not have return values.

统一EL提供方法表达式来执行JSF页面中的公共非静态方法。这些方法可能有也可能没有返回值。

Here’s a quick example:

这里有一个简单的例子。

<h:commandButton value="Save" action="#{ELBean.save}"/>

The save() method being referred to is defined on a backing bean named ELBean.

被提及的save()方法被定义在一个名为ELBean的支持Bean上。

Starting from EL 2.2, you can also pass arguments to the method that’s accessed using EL. This can allow us to rewrite our example thus:

从EL 2.2开始,你也可以向使用EL访问的方法传递参数。这可以让我们这样重写我们的例子。

<h:inputText id="firstName" binding="#{firstName}" required="true"/>
<h:commandButton value="Save"
  action="#{ELBean.saveFirstName(firstName.value.toString().concat('(passed)'))}"/>

What we’ve done here, is to create a page-scoped binding expression for the inputText component and directly pass the value attribute to the method expression.

我们在这里所做的,是为inputText组件创建一个页面范围的绑定表达式,并直接将value属性传递给方法表达式。

Note that the variable is passed to the method without any special notation, curly braces or escape characters.

请注意,变量被传递给方法时没有任何特殊的符号,大括号或转义字符。

3.3. Implicit EL Objects

3.3.隐式EL对象

The JSF EL engine provides access to several container-managed objects. Some of them are:

JSF EL引擎提供对几个容器管理对象的访问。其中一些是。

  • #{Application}: Also available as the #{servletContext}, this is the object representing the web application instance
  • #{applicationScope}: a map of variables accessible web application-wide
  • #{Cookie}: a map of the HTTP Cookie variables
  • #{facesContext}: the current instance of FacesContext
  • #{flash}: the JSF Flash scoped-object
  • #{header}: a map of the HTTP headers in the current request
  • #{initParam}: a map of the context initialization variables of the web application
  • #{param}: a map of the HTTP request query parameters
  • #{request}: the HTTPServletRequest object
  • #{requestScope}: a request-scoped map of variables
  • #{sessionScope}: a session-scoped map of variables
  • #{session}: the HTTPSession object
  • #{viewScope}: a view (page-) scoped map of variables

The following simple example lists all the request headers and values by accessing the headers implicit object:

下面的简单例子通过访问headers implicit对象,列出了所有的请求头和值。

<c:forEach items="#{header}" var="header">
   <tr>
       <td>#{header.key}</td>
       <td>#{header.value}</td>
   </tr>
</c:forEach>

4. What You Can Do in EL

4.你在EL中可以做什么

In its versatility, EL can be featured in Java code, XHTML markup, Javascript and even in JSF configuration files like the faces-config.xml file. Let’s examine some concrete use-cases.

在它的多功能性中,EL可以在Java代码、XHTML标记、Javascript,甚至在JSF配置文件(如faces-config.xml 文件)中出现。让我们来看看一些具体的用例。

4.1. Use EL in Page Markup

4.1.在页面标记中使用EL

EL can be featured in standard HTML tags:

EL可以在标准的HTML标签中出现。

<meta name="description" content="#{ELBean.pageDescription}"/>

4.2. Use EL in JavaScript

4.2.在JavaScript中使用EL

EL will be interpreted when encountered in Javascript or <script> tags:

在Javascript或

<script type="text/javascript"> var theVar = #{ELBean.firstName};</script>

A backing bean variable will be set as a javascript variable here.

一个支持Bean的变量将在这里被设置为一个javascript变量。

4.3. Evaluate Boolean Logic in EL Using Operators

4.3.使用运算符在EL中评估布尔逻辑

EL supports fairly advanced comparison operators:

EL支持相当高级的比较运算符。

  • eq equality operator, equivalent to “==.”
  • lt less than operator, equivalent to “<.”
  • le less than or equal to operator, equivalent to “<=.”
  • gt greater than operator, equivalent to “>.”
  • ge greater than or equal, equivalent to “>=.

4.4. Evaluate EL in a Backing Bean

4.4.评估后盾Bean中的EL

From within the backing bean code, one can evaluate an EL expression using the JSF Application. This opens up a world of possibilities, in connecting the JSF page with the backing bean. You could retrieve implicit EL objects, or retrieve actual HTML page components or their value easily from the backing bean:

在支持Bean的代码中,人们可以使用JSF应用程序评估EL表达式。这为连接JSF页面和支持Bean提供了很多可能性。你可以检索隐含的EL对象,或从后援Bean中检索实际的HTML页面组件或其值。

FacesContext ctx = FacesContext.getCurrentInstance(); 
Application app = ctx.getApplication(); 
String firstName = app.evaluateExpressionGet(ctx, "#{firstName.value}", String.class); 
HtmlInputText firstNameTextBox = app.evaluateExpressionGet(ctx, "#{firstName}", HtmlInputText.class);

This allows the developer a great deal of flexibility in interacting with a JSF page.

这使得开发者在与JSF页面交互时有很大的灵活性。

5. What You Can Not Do in EL

5.你在EL中不能做什么

EL < 3.0 does have some limitations. The following sections discuss some of them.

EL <3.0确实有一些限制。下面几节将讨论其中的一些。

5.1. No Overloading

5.1.没有重载

EL doesn’t support the use of overloading. So in a backing bean with the following methods:

EL不支持使用重载。因此,在一个有以下方法的支持Bean中。

public void save(User theUser);
public void save(String username);
public void save(Integer uid);

JSF EL will not be able to properly evaluate the following expression

JSF EL将无法正确评估以下表达式

<h:commandButton value="Save" action="#{ELBean.save(firstName.value)}"/>

The JSF ELResolver will introspect the class definition of bean, and pick the first method returned by java.lang.Class#getMethods (a method that returns the methods available in a class). The order of the methods returned is not guaranteed and this will inevitably result in undefined behaviour.

JSF的ELResolver将对bean的类定义进行反省,并选择java.lang.Class#getMethods(一种返回类中可用方法的方法)返回的第一个方法。返回方法的顺序是不保证的,这将不可避免地导致未定义的行为。

5.2. No Enums or Constant Values

5.2.没有枚举或常量值

JSF EL < 3.0, doesn’t support the use of constant values or Enums in the script. So, having any of the following

JSF EL < 3.0,不支持在脚本中使用常量值或Enums。因此,有以下任何一种情况

public static final String USER_ERROR_MESS = "No, you can’t do that";
enum Days { Sat, Sun, Mon, Tue, Wed, Thu, Fri };

means that you won’t be able to do the following

意味着你将不能做以下事情

<h:outputText id="message" value="#{ELBean.USER_ERROR_MESS}"/>
<h:commandButton id="saveButton" value="save" rendered="bean.offDay==Days.Sun"/>

5.3. No Built-in Null Safety

5.3.没有内置的空洞安全

JSF EL < v3.0 doesn’t provide implicit null safe access, which some may find odd about a modern scripting engine.

JSF EL < v3.0不提供隐式空安全访问,有些人可能会觉得现代脚本引擎很奇怪。

So if person in the expression below is null, the entire expression fails with an unsightly NPE

因此,如果下面的表达式中的person是空的,整个表达式就会失败,出现难看的NPE

Hello Mr, #{ELBean.person.surname}"

6. Conclusion

6.结论

We’ve examined some of the fundamentals of JSF EL, strengths and limitations.

我们已经研究了JSF EL的一些基本原理、优势和局限性。

This is largely a versatile scripting language with some room for improvement; it’s also the glue that binds the JSF view, to the JSF model and controller.

这主要是一种多功能的脚本语言,有一定的改进空间;它也是JSF视图与JSF模型和控制器之间的粘合剂。

The source code that accompanies this article is available at GitHub.

伴随着这篇文章的源代码可在GitHub获得。