購物車頁面展示商品列表,用戶點擊 "加入購物車" 觸發子流程,完成後返回主流程刷新展示。
public class CartItem implements Serializable {
private Product product;
private int quantity;
public CartItem(Product product, int quantity) { ... }
public int getTotalPrice() { return quantity * product.getPrice(); }
public void increaseQuantity() { quantity++; }
// Getter/Setter
}
public class Cart implements Serializable {
private Map items = new HashMap<>();
public List getItems() { return new ArrayList<>(items.values()); }
public void addItem(Product product) {
CartItem item = items.get(product.getId());
if (item != null) item.increaseQuantity();
else items.put(product.getId(), new CartItem(product, 1));
}
public int getTotalPrice() {
return items.values().stream()
.mapToInt(i -> i.getProduct().getPrice() * i.getQuantity())
.sum();
}
}
關鍵:Cart 非單例,每用戶一個,存放於 conversationScope。
<flow>
<!-- 啟動時創建購物車放入會話範圍 -->
<var name="mycart" class="samples.webflow.Cart"/>
<on-start>
<set name="conversationScope.cart" value="mycart"/>
</on-start>
<view-state id="viewCart" view="viewCart">
<on-render>
<evaluate expression="productService.getProducts()" result="viewScope.products"/>
</on-render>
<transition on="submit" to="viewOrder"/>
<transition on="addToCart" to="addProductToCart"/>
</view-state>
<!-- 調用子流程 -->
<subflow-state id="addProductToCart" subflow="addToCart">
<transition on="productAdded" to="viewCart"/>
</subflow-state>
<view-state id="viewOrder" .../>
<view-state id="orderConfirmed" .../>
<end-state id="returnToIndex" .../>
</flow>
<flow>
<on-start>
<!-- 從請求參數獲取 productId -->
<set name="requestScope.productId" value="requestParameters.productId"/>
</on-start>
<action-state id="addToCart">
<evaluate expression="cart.addItem(productService.getProduct(productId))"/>
<transition to="productAdded"/>
</action-state>
<end-state id="productAdded"/>
</flow>
<webflow:flow-registry id="flowRegistry" flow-builder-services="flowBuilderServices">
<webflow:flow-location path="/WEB-INF/flows/shopping.xml" id="shopping"/>
<webflow:flow-location path="/WEB-INF/flows/addToCart.xml" id="addToCart"/>
</webflow:flow-registry>
<c:choose>
<c:when test="${empty cart.items}">
<p>Your cart is empty.</p>
</c:when>
<c:otherwise>
<table>
<c:forEach var="item" items="${cart.items}">
<tr>
<td>${item.product.description}</td>
<td>${item.quantity}</td>
<td>${item.product.price}</td>
<td>${item.totalPrice}</td>
</tr>
</c:forEach>
<tr><td>TOTAL:</td><td>${cart.totalPrice}</td></tr>
</table>
</c:otherwise>
</c:choose>
<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>
<td>
<a href="${flowExecutionUrl}&_eventId=addToCart&productId=${product.id}">[add to cart]</a>
</td>
</tr>
</c:forEach>
</table>
conversationScope 跨主/子流程共享 Cartsubflow-state 調用子流程,transition on="productAdded" 接收子流程結束事件end-state id="productAdded" 與主流程 transition 對應requestParameters.productId 傳遞action-state 純業務邏輯執行,無視圖渲染