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

MVC 架構漸進式掌握(三):ActionServlet 核心控制器與 URL 映射機制詳解

     編輯:Java 相關知識

ActionServlet:MVC 的「大腦」與請求分發中樞

在 MVC 架構中,ActionServlet 扮演著前端控制器 的角色:攔截所有符合映射規則的請求,委派具體業務處理給 Action,最後由 ActionRouter 完成視圖導航。本文深度剖析其核心代碼、URL 解析邏輯及類加載器交互細節。

Web.xml 部署配置:.do 後綴映射

<servlet>
    <servlet-name>action</servlet-name>
    <servlet-class>ActionServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>action</servlet-name>
    <url-pattern>*.do</url-pattern>
</servlet-mapping>

JSP 表單提交示例:

<form name="FORM1" method="POST" action="LoginAction.do">
    <!-- 表單字段 -->
</form>

ActionServlet 核心代碼深度解析

public class ActionServlet extends HttpServlet {
    private ActionFactory factory = new ActionFactory();

    public void init(ServletConfig config) throws ServletException {
        // 生命週期:容器啟動時僅執行一次,適合初始化昂貴資源(連接池、配置緩存等)
        super.init(config);
    }

    public void service(HttpServletRequest req, HttpServletResponse res)
            throws IOException, ServletException {
        try {
            // 1. 從請求路徑解析 Action 類全限定名
            String className = getClassname(req); // 如 "actions.LoginAction"
            
            // 2. 從工廠獲取 Action 實例(單例緩存)
            Action action = factory.getAction(className, getClass().getClassLoader());
            
            // 3. 執行業務邏輯,獲取路由結果
            ActionRouter router = action.perform(this, req, res);
            
            // 4. 執行視圖跳轉(轉發/重定向)
            router.route(this, req, res);
        } catch (Exception e) {
            throw new ServletException(e);
        }
    }

    /** 
     * 從請求路徑 /actions/LoginAction.do 提取類名 actions.LoginAction 
     */
    public String getClassname(HttpServletRequest req) {
        String path = req.getServletPath(); // 返回 /actions/LoginAction.do
        int begin = path.lastIndexOf("/") + 1; // 最後一個 '/' 後
        int end = path.lastIndexOf(".");       // 最後一個 '.' 前
        if (begin > 0 && end > begin) {
            return path.substring(begin, end);
        }
        return path; // 兜底
    }
}

關鍵技術點深度剖析

1. Servlet 生命週期與線程模型

  • init():容器加載 Servlet 實例時調用一次,線程安全,適合初始化共享資源。
  • service():每個請求一個線程並發調用。務必確保線程安全——代碼中 factory 為實例變量,但 Hashtable 內部同步,Action 實例需為無狀態或線程安全。
  • destroy():容器卸載前調用,釋放資源。

2. getClass().getClassLoader() 返回什麼?

// 運行時輸出示例
getClass()           -> class ActionServlet
getClassLoader()     -> sun.misc.Launcher$AppClassLoader@92e78c (或 WebAppClassLoader)

此 ClassLoader 負責加載 actions.LoginAction 等業務類。在 Web 容器中,通常是 WebAppClassLoader,實現了 Web 應用級的類隔離。

3. 類加載器層級關係圖

Bootstrap ClassLoader (C++ 實現)
    ↑ 父加載器
Extension ClassLoader (sun.misc.Launcher$ExtClassLoader)
    ↑ 父加載器
AppClassLoader / WebAppClassLoader (sun.misc.Launcher$AppClassLoader)
    ↑ 加載應用類 (WEB-INF/classes, WEB-INF/lib/*.jar)

雙親委派模型:加載類時自下而上委派,找不到再自行加載。優勢:

  • 防止核心類被篡改 (安全性)。
  • 避免重複加載 (性能/內存)。
  • Web 容器通過打破委派 (先自行加載 WEB-INF 再委派父) 實現應用隔離。

4. 為什麼要動態加載 Action 類?

核心動機:解耦與擴展性

  • 配置驅動:新增功能只需寫新 Action 類 + 配置映射,無需修改 Servlet 代碼、重新編譯框架。
  • 熱加載潛力:結合自定義 ClassLoader 可實現運行期類替換(開發調試/插件更新)。
  • 依賴倒置:框架依賴抽象 Action 接口,具體實現由運行時動態確定。

現代框架中的演進

特性ActionServlet (早期 MVC)Spring MVC DispatcherServletStruts 2 / WebWork
URL 映射硬編碼 *.do + 字符串解析HandlerMapping (注解/配置)ActionMapper (命名空間/約定)
Controller 實例化工廠 + 反射單例IoC 容器管理 Bean 生命週期每請求一個 Action 實例 (原型)
類加載顯式 ClassLoader容器默認 + Spring 加載器容器默認
線程模型單例多線程 (需無狀態)單例 Bean (需無狀態)每請求一實例 (天然線程安全)

總結

ActionServlet 以極簡代碼展示了前端控制器模式的精髓:統一入口、動態分發、關注點分離。其 URL 解析邏輯、工廠緩存策略、類加載器交互,均是後續成熟 MVC 框架的原型。透過原理掌握本質,面對 Spring MVC 的 HandlerMapping、HandlerAdapter、ViewResolver 等組件,將不再感到陌生。

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