首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 程式設計入門

Struts 框架 Model 組件建構指南:ActionForm、Action 與業務邏輯分層

     編輯:Java 程式設計入門

Model 層在 Struts 中的定位

Model 是處理用戶請求、執行業務邏輯、保存處理結果的核心層。在 Struts 架構中,Model 具體表現為:

  • ActionForm:封裝客戶端提交資料(表單資料),執行資料驗證與預處理
  • Action:接收 ActionForm,協調業務邏輯元件,決定導向視圖
  • JavaBean / EJB:真正的業務邏輯與資料存取實作

典型對應關係:一個請求頁面 ↔ 一個 Model 組件(ActionForm + Action),但也支援一個 Model 對應多個頁面請求。若 struts-config.xml 未指定 Action,控制器直接將封裝好資料的 ActionForm 轉向視圖。

JavaBean 作用域與生命週期

Web 應用中 JavaBean 透過「作用域」定義生命週期與可見範圍:

作用域生命週期可見範圍Servlet API 對應
page單一 JSP 請求期間當前 JSP 頁面service 方法區域變數
request單一 HTTP 請求期間當前請求(含 forward/include)Request 屬性
session用戶會話期間同一用戶所有請求Session 屬性
applicationWeb 應用生命週期所有用戶、所有請求ServletContext 屬性

跨層共享 Bean 範例

// Servlet 中儲存
MyBean bean = new MyBean(...);
request.setAttribute("beanKey", bean);

// JSP 中取用
<jsp:useBean id="bean" scope="request" class="com.example.MyBean" />

ActionForm Bean 詳細設計

框架自動化服務

在 struts-config.xml 定義 Form Bean 後,Controller Servlet 自動執行:

  1. 檢查指定作用域(request/session)是否存在實例,不存在則建立新實例
  2. 將請求參數按名稱對應到 Bean 屬性,自動呼叫 setter 方法
  3. 將填充好的 ActionForm 傳遞給 Action 的 execute() 方法

設計原則

  • 粒度靈活:可細至每個表單一個 Bean,粗至整個子系統共用一個 Bean
  • 跨頁面表單:單一邏輯表單跨越多個頁面(如安裝精靈),建議用單一 ActionForm 保存所有欄位,不同頁面提交至同一 Action
  • 僅含屬性與簡單驗證:典型 ActionForm 只有 getter/setter,業務邏輯放在 Action 或商業邏輯 Bean

ActionForm 核心方法

public class MyForm extends ActionForm {
    // 屬性 getter/setter...
    
    // 1. 驗證方法:回傳 ActionErrors,非 null/非空則轉向 input 頁面
    public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) {
        ActionErrors errors = new ActionErrors();
        if (getUsername() == null || getUsername().trim().isEmpty()) {
            errors.add("username", new ActionMessage("error.username.required"));
        }
        return errors;
    }
    
    // 2. 重置方法:將屬性恢復預設值
    public void reset(ActionMapping mapping, HttpServletRequest request) {
        setUsername(null);
        setAge(0);
    }
}

驗證流程控制

  • <action> 元素 validate="true" 時觸發 validate()
  • 驗證失敗 → 儲存錯誤至 request → 轉向 input 指定頁面
  • 複雜業務驗證建議在 Action 或商業邏輯層執行

Action 類別詳細設計

Controller 執行流程

  1. 選擇適當 Action(或預設 Action)
  2. 建立 Action 實例(單例模式,多執行緒共享)
  3. 呼叫 execute() 方法(舊版為 perform())

兩個 execute 方法簽名

// 通用請求
public ActionForward execute(ActionMapping mapping, ActionForm form,
                             ServletRequest request, ServletResponse response)
    throws IOException, ServletException;

// HTTP 專用(常用)
public ActionForward execute(ActionMapping mapping, ActionForm form,
                             HttpServletRequest request, HttpServletResponse response)
    throws IOException, ServletException;

執行緒安全設計原則(關鍵!)

Action 實例被多執行緒共享,嚴禁使用實例/靜態變數儲存請求相關狀態。

錯誤做法正確做法
private String userName; // 實例變數從 request/ActionForm 取得資料
static int counter; // 靜態變數使用 ThreadLocal 或請求屬性
非同步存取共享資源同步區塊保護共享資源存取

Action 常用輔助方法

  • getLocale(request) / setLocale(request, locale):國際化支援
  • getResources():取得訊息資源
  • isCancelled(request):檢測用戶點擊「取消」
  • saveErrors(request, errors):儲存錯誤訊息供視圖顯示

系統狀態 Bean 與商業邏輯 Bean 分層

系統狀態 Bean

代表應用當前狀態的資料容器:

  • 購物車 Bean(每用戶一個,含商品明細)
  • 用戶資料 Bean(信用卡、地址等)
  • 商品目錄、庫存 Bean

小型系統可全記憶體驻留;大型系統對應資料庫實體,常用 Entity EJB 或 JPA 實體類別。

商業邏輯 Bean 設計原則

  1. 封裝功能邏輯:以方法形式暴露業務操作
  2. 環境無關性:不 import javax.servlet.*,不依賴 Web 容器
  3. 參數化介面:接收系統狀態 Bean 作為參數,回傳結果
  4. 可重用性:同邏輯可用於 Web、批次程式、Web Service 等不同入口

Action 作為轉接層

public class OrderAction extends Action {
    public ActionForward execute(ActionMapping mapping, ActionForm form,
                                 HttpServletRequest request, HttpServletResponse response) {
        // 1. 從 ActionForm 取得資料
        OrderForm orderForm = (OrderForm) form;
        
        // 2. 轉換為商業邏輯層參數
        OrderDTO dto = new OrderDTO();
        dto.setUserId(orderForm.getUserId());
        dto.setItems(orderForm.getItems());
        
        // 3. 呼叫商業邏輯 Bean
        OrderService service = ServiceLocator.getOrderService();
        OrderResult result = service.placeOrder(dto);
        
        // 4. 處理結果、設定導向
        if (result.isSuccess()) {
            request.setAttribute("orderId", result.getOrderId());
            return mapping.findForward("success");
        } else {
            saveErrors(request, result.getErrors());
            return mapping.findForward("failure");
        }
    }
}

Model 組件分類總覽

分類代表類別職責典型技術
ActionForm Beanextends ActionForm表單資料封裝、簡單驗證Struts 原生
系統狀態 BeanPOJO / Entity Bean業務資料持久化狀態JPA / Hibernate / EJB
商業邏輯 BeanPOJO / Session Bean核心業務規則、工作流程Spring Bean / EJB
Action Beanextends Action請求協控、視圖導向Struts 原生

最佳實踐建議

  1. ActionForm 僅做資料承載,複雜驗證下沉到 Service 層
  2. Action 保持輕薄,只負責協調與導向,業務邏輯全權委派
  3. 商業邏輯 Bean 零 Web 依賴,便於單元測試與多通道複用
  4. 善用作用域:請求資料用 request,跨步驟流程用 session,全域配置用 application
  5. 考慮遷移至 Spring MVC:Struts 1 已停止維護,現代專案建議採用 Spring MVC + JPA/DAO 模式

總結

Struts Model 層設計核心在於「分層解耦」:ActionForm 處理表現層資料綁定,Action 處理流程控制,商業邏輯 Bean 專注領域邏輯。嚴守執行緒安全、環境無關性、單一職責原則,才能構建可維護、可測試、可擴充的企業級應用。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved