12. 表达式语言(EL)

Web Flow 使用EL访问其数据模型并调用作。 本章应帮助你熟悉EL语法、配置以及你可以参考流程定义中的特殊EL变量。spring-doc.cadn.net.cn

EL在流程中用于多种用途,包括:spring-doc.cadn.net.cn

EL也用于将表单参数绑定到模型对象,反之,也可以从模型对象的属性渲染格式化表单字段。 但使用 Web Flow 配合 JSF 时则不适用。 在这种情况下,标准的 JSF 组件生命周期适用。spring-doc.cadn.net.cn

12.1. 表达式类型

一个重要的概念是,Web Flow中有两种表达式:spring-doc.cadn.net.cn

12.1.1. 标准表达

第一种也是最常见的表达式是标准表达式。 此类表达式由EL直接计算,不必包含在分隔符中,如。 以下示例展示了这样一个标准表达式:\#{}spring-doc.cadn.net.cn

<evaluate expression="searchCriteria.nextPage()" />

前面的表达式是一个标准表达式,调用下一页方法检索标准评估时变量。 如果你尝试用特殊的分隔符(例如),将该表达式包裹起来,你会得到\#{}IllegalArgumentException. 在这种情况下,分隔符被视为冗余的。 唯一可接受的值是表达属性是一个表达式字符串。spring-doc.cadn.net.cn

12.1.2. 模板表达式

第二种表达式是模板表达式。 模板表达式允许将文字文本与一个或多个标准表达式混合使用。 每个标准表达式块都被明确的分隔符包围。 以下示例展示了一个模板表达式:\#{}spring-doc.cadn.net.cn

<view-state id="error" view="error-#{externalContext.locale}.xhtml" />

前面的表达式是一个模板表达式。 评估的结果是一个串,串接了文字文本,例如错误-.xhtml结果为externalContext.locale. 你需要明确的分隔符来划分模板中的标准表达块。spring-doc.cadn.net.cn

请参阅Web Flow XML模式,完整列出接受标准表达式和接受模板表达式的XML属性。 你也可以在 Eclipse 中使用 F2(或其他 IDE 中的等效快捷键)来访问可用的文档,以便输入特定的流程定义属性。

12.2. EL实现

Spring Web Flow 支持以下 EL(表达式语言)实现:spring-doc.cadn.net.cn

12.2.1. 春季EL

Web Flow 使用 Spring 表达式语言(Spring EL)。Spring EL 的创建旨在为 Spring 产品组合中的所有产品提供一种单一且支持良好的表达式语言。 它作为一个独立的罐子分发(org.springframework.expression)在春季框架中。spring-doc.cadn.net.cn

12.2.2. 统一EL

统一EL的使用也意味着依赖于艾尔-阿皮虽然这通常由你的网页容器提供。 虽然 Spring EL 是默认且推荐使用的表达式语言,但你可以用 Unified EL 替代它。 为此,你需要以下 Spring 配置来插入WebFlowELExpressionParser前往流量-构建器-服务:spring-doc.cadn.net.cn

<webflow:flow-builder-services expression-parser="expressionParser"/>

<bean id="expressionParser" class="org.springframework.webflow.expression.el.WebFlowELExpressionParser">
    <constructor-arg>
        <bean class="org.jboss.el.ExpressionFactoryImpl" />
    </constructor-arg>
</bean>

请注意,如果你的应用注册了自定义转换器,务必确保WebFlowELExpressionParser配置为包含这些自定义转换器的转换服务,具体如下:spring-doc.cadn.net.cn

<webflow:flow-builder-services expression-parser="expressionParser" conversion-service="conversionService"/>

<bean id="expressionParser" class="org.springframework.webflow.expression.el.WebFlowELExpressionParser">
    <constructor-arg>
        <bean class="org.jboss.el.ExpressionFactoryImpl" />
    </constructor-arg>
    <property name="conversionService" ref="conversionService"/>
</bean>

<bean id="conversionService" class="somepackage.ApplicationConversionService"/>

12.3. EL便携性

一般来说,你会发现Spring EL和Unified EL的语法非常相似。spring-doc.cadn.net.cn

不过,Spring高尔也有一些优势。 例如,Spring EL与Spring 3的类型转换紧密集成,这让你能充分利用其功能。 具体来说,自动检测泛型类型以及格式化注释的使用目前仅支持Spring EL。spring-doc.cadn.net.cn

从统一EL升级到Spring EL时,请注意以下几个小变化:spring-doc.cadn.net.cn

  • 用流中定义表示的表达式必须更改为(注意前置退格字符)。${}\#{}spring-doc.cadn.net.cn

  • 测试当前事件的表达式(例如#{currentEvent == 'submit'}必须将 改为\#{currentEvent.id == '提交'}(注意新增身份证).spring-doc.cadn.net.cn

  • 解析性质(例如:#{currentUser.name}) 可能导致NullPointerException没有任何检查,如\#{currentUser != null ? currentUser.name : null}.一个更好的选择是安全导航操作员:\#{currentUser?.姓名}.spring-doc.cadn.net.cn

有关 Spring EL 语法的更多信息,请参见 Spring 文档中的语言参考部分。spring-doc.cadn.net.cn

12.4. 特殊EL变量

你可以在流程中引用多个隐式变量。spring-doc.cadn.net.cn

请记住这个通用规则: 你应该使用指向数据作用域的变量(flowScope(流控镜),视图范围,请求范围,依此类推)只有在你为某个作用域赋予新变量时才会这样。spring-doc.cadn.net.cn

例如,当将调用结果分配给bookingService.findHotels(searchCriteria)到一个新的变量,称为酒店你必须在它前面加上一个范围变量,让 Web Flow 知道你想把它存储在哪里。 以下示例展示了如何实现:spring-doc.cadn.net.cn

<?xml version="1.0" encoding="UTF-8"?>
<flow xmlns="http://www.springframework.org/schema/webflow" ... >

	<var name="searchCriteria" class="org.springframework.webflow.samples.booking.SearchCriteria" />

	<view-state id="reviewHotels">
		<on-render>
			<evaluate expression="bookingService.findHotels(searchCriteria)" result="viewScope.hotels" />
		</on-render>
	</view-state>

</flow>

然而,当设置已有变量(例如)检索标准在下面的例子中,你应该直接引用该变量,不要在前缀任何作用域变量,具体如下:spring-doc.cadn.net.cn

<?xml version="1.0" encoding="UTF-8"?>
<flow xmlns="http://www.springframework.org/schema/webflow" ... >

	<var name="searchCriteria" class="org.springframework.webflow.samples.booking.SearchCriteria" />

	<view-state id="reviewHotels">
		<transition on="sort">
			<set name="searchCriteria.sortBy" value="requestParameters.sortBy" />
		</transition>
	</view-state>

</flow>

以下是你可以在流程定义中引用的隐式变量列表:spring-doc.cadn.net.cn

12.4.1. 该flowScope(流控镜)变量

你可以使用flowScope(流控镜)来分配一个流变量。 流量示范域在流开始时分配,流结束时被销毁。 默认实现中,流域中存储的任何对象都需要可序列化。 以下列表定义了flowScope(流控镜)变量:spring-doc.cadn.net.cn

<evaluate expression="searchService.findHotel(hotelId)" result="flowScope.hotel" />

12.4.2. 该视图范围变量

你可以使用视图范围用于分配视图变量。 当视图状态进入并销毁,国家退出时。 视图范围只能视图状态. 默认实现中,视图范围内存储的任何对象都需要可序列化。 以下列表定义了视图范围变量:spring-doc.cadn.net.cn

<on-render>
    <evaluate expression="searchService.findHotels(searchCriteria)" result="viewScope.hotels"
              result-type="dataModel" />
</on-render>

12.4.3. 该请求范围变量

你可以使用请求范围来分配请求变量。 请求范围在调用流时分配,流返回时被销毁。 以下列表定义了请求范围变量:spring-doc.cadn.net.cn

<set name="requestScope.hotelId" value="requestParameters.id" type="long" />

12.4.4. 该闪光镜变量

你可以使用闪光镜来分配一个闪烁变量。 Flash Scope在流程开始时被分配,每次视图渲染后清除,流程结束时销毁。 默认实现中,存储在闪存范围中的对象必须可序列化。 以下列表定义了闪光镜变量:spring-doc.cadn.net.cn

<set name="flashScope.statusMessage" value="'Booking confirmed'" />

12.4.5. 该对话范围变量

你可以使用对话范围来分配一个对话变量。 当顶层流程开始时,会话范围被分配,顶层流程结束时则被销毁。 对话范围由顶层流程及其所有子流程共享。 默认实现中,对话范围对象存储在 HTTP 会话中,通常应可序列化以满足典型会话复制的需求。 以下列表定义了对话范围变量:spring-doc.cadn.net.cn

<evaluate expression="searchService.findHotel(hotelId)" result="conversationScope.hotel" />

12.4.6. 该请求参数变量

请求参数变量访问客户端请求参数,具体如下:spring-doc.cadn.net.cn

<set name="requestScope.hotelId" value="requestParameters.id" type="long" />

12.4.7. 该当前事件变量

当前事件变量访问当前的属性事件如下:spring-doc.cadn.net.cn

<evaluate expression="booking.guests.add(currentEvent.attributes.guest)" />

12.4.8. 那currentUser变量

currentUser变量访问已认证的主要如下:spring-doc.cadn.net.cn

<evaluate expression="bookingService.createBooking(hotelId, currentUser.name)"
          result="flowScope.booking" />

12.4.9. 那消息上下文变量

消息上下文变量访问上下文以检索并创建流执行消息,包括错误和成功消息。 参见消息上下文更多信息请参见Javadocs。 以下示例使用了消息上下文变量:spring-doc.cadn.net.cn

<evaluate expression="bookingValidator.validate(booking, messageContext)" />

12.4.10. 那个resourceBundle变量

resourceBundle变量访问消息资源,具体如下:spring-doc.cadn.net.cn

<set name="flashScope.successMessage" value="resourceBundle.successMessage" />

12.4.11. 那flowRequestContext变量

flowRequestContext变量访问请求上下文API,是当前流请求的表示。 更多信息请参见API Javadocsspring-doc.cadn.net.cn

12.4.12. 那个flowExecutionContext变量

flowExecutionContext变量访问FlowExecutionContextAPI,是当前流状态的表示。 更多信息请参见API Javadocsspring-doc.cadn.net.cn

12.4.13. 那个flowExecutionUrl变量

flowExecutionUrl变量访问当前流执行视图状态的上下文相关URI。spring-doc.cadn.net.cn

12.4.14.外部上下文变量

外部上下文变量访问客户端环境,包括用户会话属性。 参见外部语境 更多信息请使用 API JavaDocs。 以下示例使用了外部上下文变量:spring-doc.cadn.net.cn

<evaluate expression="searchService.suggestHotels(externalContext.sessionMap.userProfile)"
          result="viewScope.hotels" />

12.5. 范围搜索算法

如本节前文所述,在分配某个流程范围变量时,必须引用该范围。 以下示例展示了如何实现:spring-doc.cadn.net.cn

<set name="requestScope.hotelId" value="requestParameters.id" type="long" />

当你仅访问某个作用域中的变量时,引用该作用域是可选的,具体如下:spring-doc.cadn.net.cn

<evaluate expression="entityManager.persist(booking)" />

当没有指定范围时,比如使用预订如前所述,使用了范围搜索算法。 算法会在请求、闪现、视图、流和对话等范围内查找该变量。 如果找不到这样的变量,则评估例外被抛出。spring-doc.cadn.net.cn