程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> Spring Web Flow 2.0入門 - 用Unified EL實現業務邏輯

Spring Web Flow 2.0入門 - 用Unified EL實現業務邏輯

編輯:關於JAVA

到現在為止,這個購物車應用只是實現了頁面之間的跳轉,接下來我們要實現與業務邏輯相關的功能。由於本教程的重點在於介紹如何應用 Spring Web Flow ,所實現的業務比較簡單,與實際應用有較大的距離,請讀者諒解。

業務的邏輯涉及到數據的獲取、傳遞、保存,相關的業務功能函數的調用等內容,這些功能的實現都可用 Java 代碼來完成,但定義 Spring Web Flow 的語法與 Java 是無關的,這就要求 Spring Web Flow 提供與 Java 代碼的整合機制。要了解這種機制,關鍵在於搞清楚兩個問題:

業務邏輯代碼在什麼時候被調用?

業務邏輯代碼在調用後得到的數據如何保存、傳遞?

業務邏輯代碼在什麼時候被調用?

在 Spring Web Flow 中,業務邏輯代碼的執行可由以下三種情形來觸發:

客戶端請求中包含了 _eventId 參數

執行到框架自定義的切入點

執行到 <action-state> 元素

客戶端請求中包含了 _eventId 參數

這種方式一般用在 state 之間的 transition ,通過指定 _eventId 參數的值,表明了客戶的行為,從而導致相應事件的發生,在 Spring Web Flow 的定義文件中可以通過 evaluate 元素來指定要處理的業務邏輯。參看清單21:

清單 21 transition 示例

<transition on="submit">
<evaluate expression="validator.validate()" />
</transition>

清單 21 的代碼表示,當客戶端的請求中包含“ _eventId=submit ”,則 evaluate 元素中 expression 屬性所指明的表達式會被執行,即 validator 對象的validate 方法會得到調用。

執行到框架自定義的切入點

Spring Web Flow 定義了 5 個切入點,通過 flow 定義文件的配置,可在這 5 個切入點插入相關業務邏輯代碼。

表 2 Spring Web Flow 自定義的切入點

切入點名稱 XML 元素名稱 觸發時刻 flow start on-start flow 執行之前 state entry on-entry 進入某個 state 之後,做其他事情之前 view render on-render 在進入 view 的 render 流程之後,在 view 真正 render出來之前 state exit on-exit 在退出 state 之前 flow end on-end flow 執行結束之後

清單 22 給出了在 view render 切入點插入業務邏輯代碼的例子:

清單 22 on-render 元素

<view-state id="viewCart" view="viewCart" >
 <on-render>
  <evaluate expression="productService.getProducts()"
   result="viewScope.products"/>
 </on-render>
</view-state>

執行到 <action-state> 元素

Spring Web Flow 中的這個 <action-state> 是專為執行業務邏輯而設的 state 。如果某個應用的業務邏輯代碼即不適合放在 transition 中由客戶端來觸發,也不適合放在 Spring Web Flow 自定義的切入點,那麼就可以考慮添加 <action-state> 元素專用於該業務邏輯的執行。示例代碼參看清單23:

清單 23 action-state 示例

<action-state id="addToCart">
 <evaluate expression="cart.addItem(productService.getProduct(productId))"/>
 <transition to="productAdded"/>
</action-state>

業務邏輯代碼在調用後得到的數據如何保存、傳遞?

Spring Web Flow 的定義中可直接使用表達式語言( Expression Language ),前面的代碼都是用的 Unified EL ,對於習慣用 OGNL 的開發人員,可通過 flow-builder-services 的配置改成使用 OGNL 。不管是哪一種表達式語言, Spring Web Flow 都提供了一些固定名稱的變量,用於數據的保存、傳遞。在 Spring Web Flow 的解決方案 一節中,已經提到 Spring Web Flow 所著力解決的問題即是數據存取范圍的問題,為此, Spring Web Flow 提供了兩種比較重要的范圍,一是 flow 范圍,另一個是 conversation 范圍。通過 flowScope 和 conversationScope 這兩個變量, Spring Web Flow 提供了在這兩種范圍裡存取數據的方法。清單 24演示了如何將業務邏輯代碼執行的結果存放到flow范圍中。

清單 24 flowScope 示例

<evaluate expression="productService.getProducts()" result="flowScope.products" />

Spring Web Flow 還提供了大量其他的變量,以方便數據的存取。如 viewScope 范圍即是從進入 view-state 至退出 view-state 結束, requestScope 即和一般的 request 范圍沒什麼區別,等等。另外還有一些用於獲取 flow 以外數據的變量,如 requestParameters 、 messageContext 等等。具體變量的列表可參看 Spring Web Flow自帶的文檔。

為示例應用添加商品

接下來,我們要在示例應用的 viewCart.jsp 頁面中添加商品,可按以下步驟操作:

添加 Product 類

添加 ProductService 類

修改 shopping.xml 文件

修改 viewCart.jsp 頁面

添加 Product 類

Product 類是個普通的 JavaBean ,用於定義商品( Product )的一般屬性,同時也提供了構造方法。由於會把 Product 存放於 conversationScope 中, Product 實現了 Serializable 接口。具體見清單25:

清單 25 Product 類

package samples.webflow;
import java.io.Serializable;
public class Product implements Serializable {
  private static final long serialVersionUID = 1951520003958305899L;
  private int id;
  private String description;
  private int price;

  public Product(int id, String description, int price) {
    this.id = id;
    this.description = description;
    this.price = price;
  }
  /*省略getter和setter*/
}

添加 ProductService 類

ProductService 主要提供商品列表,並能根據商品的 id 查找出該商品,由於示例較簡單,這裡只添加了三條紀錄。見清單 26:

清單 26 ProductService 類

package samples.webflow;
/*省略import語句*/
@Service("productService")
public class ProductService {
  /*products 用於存放多個商品 */
  private Map<Integer, Product> products = new HashMap<Integer, Product>();

  public ProductService() {
    products.put(1, new Product(1, "Bulldog", 1000));
    products.put(2, new Product(2, "Chihuahua", 1500));
    products.put(3, new Product(3, "Labrador", 2000));
  }

  public List<Product> getProducts() {
    return new ArrayList<Product>(products.values());
  }

  public Product getProduct(int productId) {
    return products.get(productId);
  }
}

Service 注解表示 Spring IoC 容器會初始化一個名為 productService 的 Bean ,這個 Bean 可在 Spring Web Flow 的定義中直接訪問。

修改 shopping.xml 文件

要在 viewCart 頁面中顯示商品,只需在 view-state 元素的 on-render 切入點調用 productService 的 getProducts 方法,並將所得結果保存到 viewScope 中即可。見清單27:

清單 27 shopping.xml 需修改的部分

<view-state id="viewCart" view="viewCart" >
 <on-render>
  <evaluate expression="productService.getProducts()" result="viewScope.products"/>
 </on-render>
 <transition on="submit" to="viewOrder"> </transition>
</view-state>

修改 viewCart.jsp 頁面

清單 27 表明 productService 的 getProducts 方法所得的結果會存放在 viewScope 中名為 products 的變量中, jsp 頁面的代碼可直接訪問該變量。見清單 28:

清單 28 修改後的 viewCart.jsp 頁面

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>View Cart</title>
</head>
<body>
<h1>View Cart</h1>
<h2>Items in Your Cart</h2>
<a href="${flowExecutionUrl}&_eventId=submit">Submit</a>
<h2>Products for Your Choice</h2>
<table>
<c:forEach var="product" items="${products}">
<tr>
<td>${product.description}</td>
<td>${product.price}</td>
</tr>
</c:forEach>
</table>
</body>
</html>

運行應用程序

圖 5 viewCart.jsp 頁面效果

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved