Spring Web Flow :流程,基于Spring MVC 的DispatchServlet
使用方法
- 配置命名空間,目前不支持java方式的配置
<?xml version="1.0" encoding="UTF-8"?>
<flow xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/webflow"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/webflow
http://www.springframework.org/schema/webflow/spring-webflow.xsd">
- 流程執(zhí)行器,負(fù)責(zé)創(chuàng)建和執(zhí)行流程執(zhí)行器
webflowContext.xml
<webflow:flow-executor id="logoutFlowExecutor" flow-registry="logoutFlowRegistry">
<webflow:flow-execution-attributes>
<webflow:always-redirect-on-pause value="false"/>
<webflow:redirect-in-same-state value="false"/>
</webflow:flow-execution-attributes>
</webflow:flow-executor>
- 配置流程注冊器,加載流程定義,并讓執(zhí)行器能夠使用它們.
webflowContext.xml
<webflow:flow-registry id="logoutFlowRegistry" flow-builder-services="builder" base-path="/WEB-INF/webflow">
<webflow:flow-location-pattern value="/logout/*-webflow.xml"/>
</webflow:flow-registry>
也可以用 <webflow:flow-location path=""/>
指定一個絕對路徑,而不用webflow:flow-location-pattern
和base-path
-
配置服務(wù)構(gòu)造器
webflowContext.xml
<webflow:flow-builder-services id="builder"
development="true"
view-factory-creator="viewFactoryCreator"
expression-parser="expressionParser"/>
- 處理流程請求
cas-servlet.xml
FlowHandlerMapping
幫助DispatchServlet將請求發(fā)送給Spring Web Flow
<!-- logout webflow configuration -->
<bean id="logoutFlowHandlerMapping" class="org.springframework.webflow.mvc.servlet.FlowHandlerMapping"
p:flowRegistry-ref="logoutFlowRegistry" p:order="3">
<property name="interceptors">
<array value-type="org.springframework.web.servlet.HandlerInterceptor">
<ref bean="localeChangeInterceptor"/>
</array>
</property>
</bean>
FlowHandlerMapping
的工作僅僅是將請求重定向給 Spring Web Flow
響應(yīng)請求的是FlowHandlerAdapter
等同于Spring MVC的控制器,處理請求.配置如下:cas-servlet.xml
<bean id="logoutHandlerAdapter" class="org.jasig.cas.web.flow.SelectiveFlowHandlerAdapter"
p:supportedFlowId="logout" p:flowExecutor-ref="logoutFlowExecutor"
p:flowUrlHandler-ref="logoutFlowUrlHandler"/>
<bean id="logoutFlowUrlHandler" class="org.jasig.cas.web.flow.CasDefaultFlowUrlHandler"
p:flowExecutionKeyParameter="RelayState"/>
流程的組件
如果流程是旅行,那么狀態(tài)就是路途上的城鎮(zhèn),風(fēng)景點(diǎn),轉(zhuǎn)移就是公路,流程數(shù)據(jù)就像一路買的紀(jì)念品和記憶
-
狀態(tài)
狀態(tài)類型 | 它是用來做什么的 |
---|---|
視圖(view) | 暫停流程并邀請用戶參與流程 |
行為(Action) | 行為狀態(tài),流程邏輯發(fā)生的地方 |
決策(Decision) | 基于流程數(shù)據(jù)的評估結(jié)果確定流程方向 |
子流程(SubFlow) | 在當(dāng)前的流程上下文中啟動一個新的流程 |
結(jié)束(End) | 流程的最后一站 |
- 視圖狀態(tài):
<view-state id="redirectToFrontApp" view="externalRedirect:#{currentEvent.attributes.logoutUrl}&RelayState=#{flowExecutionContext.key}">
<transition on="next" to="frontLogout" />
</view-state>
屬性解釋
id:在流程內(nèi)標(biāo)識這個狀態(tài),(邏輯視圖名)
view:展現(xiàn)的邏輯視圖名
model:表單所綁定的對象
<view-state id="viewLoginForm" view="casLoginView" model="credential" >
<binder>
<binding property="username" required="true" />
<binding property="password" required="true"/>
<binding property="captcha"/>
<!--
<binding property="rememberMe" />
-->
</binder>
<on-entry>
<set name="viewScope.commandName" value="'credential'"/>
<!--
<evaluate expression="samlMetadataUIParserAction" />
-->
</on-entry>
<!-- <transition on="submit" bind="true" validate="true" to="realSubmit"/> -->
<transition on="submit" bind="true" validate="true" to="validate"/>
</view-state>
- 行為狀態(tài)
例子:
<action-state id="frontLogout">
<evaluate expression="frontChannelLogoutAction" />
<transition on="finish" to="finishLogout" />
<transition on="redirectApp" to="redirectToFrontApp" />
</action-state>
或
<action-state id="validate">
<evaluate expression="captchaVaditeAuthenticationViaFormAction.validate(flowRequestContext, flowScope.credential, messageContext)"/>
<transition on="error" to="initializeLogin"/>
<transition on="valid" to="realSubmit"/>
</action-state>
屬性解釋:
evaluate:行為狀態(tài)要做的事情
expression : 調(diào)用那個Action,并計算結(jié)果.用SpEL表達(dá)式
- 決策狀態(tài)
決定分支
<decision-state id="serviceCheck">
<if test="flowScope.service != null" then="generateServiceTicket" else="viewGenericLoginSuccess"/>
</decision-state>
test
是SpEL表達(dá)式,返回結(jié)果必須是Boolean格式,可以調(diào)指定bean(一般是Action)中的一個方法.
- 子流程狀態(tài)
<subflow-state id="order" subflow="pizza/order">
<input name="order" value="order"/>
<transition on="orderCreated" to=" payment" />
</subflow-state>
- 結(jié)束狀態(tài)
<end-state id="redirectView" view="externalRedirect:#{requestScope.response.url}"/>
或
<end-state id="viewRedirectToUnauthorizedUrlView" view="externalRedirect:#{flowScope.unauthorizedRedirectUrl}"/>
view:如果是externalRedirect:
前綴,將重定向到流程的外部頁面;如果是flowRedirect:
前綴,將重定向到另一個流程中
-
轉(zhuǎn)移
<transition on="finish" to="finishLogout" />
<transition on="front" to="frontLogout" />
Action中返回的寫法
if (needFrontSlo) {
return new Event(this, FRONT_EVENT);
} else {
// otherwise, finish the logout process
return new Event(this, FINISH_EVENT);
}
如果只有to屬性,則是默認(rèn)的轉(zhuǎn)移狀態(tài)
異常轉(zhuǎn)移
<transition to="viewServiceErrorView"
on-exception="org.springframework.webflow.execution.repository.NoSuchFlowExecutionException"/>
全局轉(zhuǎn)移 將重復(fù)寫的共用的轉(zhuǎn)移抽取出來
<global-transitions>
<transition to="viewLoginForm" on-exception="org.jasig.cas.services.UnauthorizedSsoServiceException"/>
<transition to="viewServiceErrorView"
on-exception="org.springframework.webflow.execution.repository.NoSuchFlowExecutionException"/>
<transition to="serviceUnauthorizedCheck" on-exception="org.jasig.cas.services.UnauthorizedServiceException"/>
<transition to="serviceUnauthorizedCheck" on-exception="org.jasig.cas.services.UnauthorizedServiceForPrincipalException" />
</global-transitions>
-
流程數(shù)據(jù)
- 聲明變量
<var name="credential" class="org.jasig.cas.authentication.RememberMeUsernamePasswordCredential" />
或
<evaluate result="viewScope.toppingsList" expression="T(com.springinaction.pizza.domain.Topping).asList()"/>
#viewScope 視圖作用域
或
<set name="flowScope.pizza" value="new com.springinaction.pizza.domain.Pizza()"/>
#flowScope 流程作用域
var定義的可以在流程的任意狀態(tài)訪問.
作用域
范圍 | 生命作用域和 可見性 |
---|---|
Conversation | 最高層級的流程開始創(chuàng)建,被最高層級及其所有子流程共享 |
flow | 只有在創(chuàng)建他的流程中是可見的,var是流程作用域的 |
Request | 請求進(jìn)入流程時創(chuàng)建,流程返回時銷毀 |
Flash | 流程開始時創(chuàng)建,結(jié)束時銷毀,在視圖狀態(tài)渲染后也會被清除 |
View | 進(jìn)入視圖狀態(tài)時創(chuàng)建,當(dāng)這個狀態(tài)退出時銷毀 |
- flowScope
- requestParameters
- flowRequestContext
- requestScope
- requestScope.response.responseType.name() == 'POST'"
開始狀態(tài):默認(rèn)是第一個流程定義文件中的第一個狀態(tài),也可以用 start-state
<on-start>
<evaluate expression="initialFlowSetupAction"/>
</on-start>
<input type="hidden" name="execution" value="${flowExecutionKey}" />
<input type="hidden" name="_eventId" value="submit" />
-### 實(shí)例
-### 保護(hù)Web流程
<view-state id="restricted"> <secured attributes="ROLE_ADMIN" match="all"/>
</view-state>