大家都知道,Struts控制器組件負責接受使用者請求,更通模型,以及返回給使用者合適的視圖組件.
控制器將模型層和視圖層分開,這樣分離,可以為同一個模型開發出不同的視圖.
下面時Struts的三大主要組件
ActionServlet組件:充當Struts架構的中央控制器
RequestProcessor組件:充當每個子應用模組的要求處理常式
Action組件:真正來處理一項具體的業務.
一. Struts的init()方法
Struts應用中只存在ActionServlet的一個執行個體,Servlet容器在啟動時,或者使用者首次請求ActionServlet時載入ActionServlet類.在這兩種情況下,servlet容器都會在ActionServlet容器被載入後立即執行它的init()方法,這可以保證ActionServlet處理使用者請求時已經被初始化.
下面根據Init()講述Struts的初始化過程
代碼 public void init() throws ServletException { // Wraps the entire initialization in a try/catch to better handle // unexpected exceptions and errors to provide better feedback // to the developer try { //調用initInternal()方法,初始化Struts架構內的訊息資源,如與系統日誌相關的通知,警告,和錯誤訊息. 1)initInternal(); //調用ininOther()方法,從web.xml檔案中載入ActionServlet的初始化參數,如config參數 2)initOther(); //調用initServlet()方法,從web.xml檔案中載入ActionServlet的URL映射資訊.同時還會註冊web.xml檔案和Struts設定檔所使用的DTD檔案,這些DTD檔案使用者驗證web.xml和struts設定檔的文法.其中方法裡的 digester類負責解析web.xml,對字串servletMapping屬性進行初始化 3) initServlet(); //把ActionServlet執行個體放到ServletContext裡 getServletContext().setAttribute(Globals.ACTION_SERVLET_KEY, this); //初始化一個factory,用於建立moduleConfig initModuleConfigFactory(); //,載入並解析預設struts設定檔/WEB-INF/struts-config.xml,同時建立MoudleConfig執行個體,放到ServletContext中 4)ModuleConfig moduleConfig = initModuleConfig("", config); //載入並初始化預設子應用模組的訊息資源;講解MessageResources對象,把它儲存在ServletContext中. 5)initModuleMessageResources(moduleConfig); //載入並初始化預設子應用模組的資料來源,如果在struts設定檔中沒有定義<data-sources >元素,忽略這一流程. 6)initModuleDataSources(moduleConfig); //載入並初始化預設子應用的所有外掛程式 7)initModulePlugIns(moduleConfig); //凍結moduleConfig(,在方法返回之前不能修改它,否則將拋出異常) moduleConfig.freeze(); //如果還有其他子應用模組,將重複4-7步 Enumeration names = getServletConfig().getInitParameterNames(); while (names.hasMoreElements()) { String name = (String) names.nextElement(); if (!name.startsWith("config/")) { continue; } String prefix = name.substring(6); moduleConfig = initModuleConfig (prefix, getServletConfig().getInitParameter(name)); initModuleMessageResources(moduleConfig); initModuleDataSources(moduleConfig); initModulePlugIns(moduleConfig); moduleConfig.freeze(); } //將各個子模組應用(除了預設的)的首碼存到一個字元數組中,並放到servletcontext中 this.initModulePrefixes(this.getServletContext()); //釋放建立的用於讀取設定檔的digester執行個體,釋放記憶體 this.destroyConfigDigester(); } catch (UnavailableException ex) { throw ex; } catch (Throwable t) { // The follow error message is not retrieved from internal message // resources as they may not have been able to have been // initialized log.error("Unable to initialize Struts ActionServlet due to an " + "unexpected exception or error thrown, so marking the " + "servlet as unavailable. Most likely, this is due to an " + "incorrect or missing library dependency.", t); throw new UnavailableException(t.getMessage()); } }
將各個子模組應用(除了預設的)的首碼存到一個字元數組中,並放到servletcontext中,對於預設的子應用模組,在appclication範圍記憶體放他的MoudleConfig執行個體的key為“org.apache.struts.action.MODULE”,其他模組如/account,存放的key為org.apache.struts.action.MODULE/account,訊息,資料來源和外掛程式等部分存在servletcontext的key和上述方法類似,不在說明.
二.ActionServlet的process方法
當ActionServlet接受到HTTP請求後,在doget()或doPost()方法中都會調用process()方法來處理請求.
代碼 public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { process(request, response); }
代碼 public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { process(request, response); }
下面是process方法,它看上去並不複雜,但他調用的其他方法比較複雜.
代碼 protected void process(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { //根據request裡的資訊從servletContext裡找到相應的子模組ModuleConfig,和它下面的MessageResources,並放到request裡,使其他組件可以方便的供request裡取得應用配置資訊和訊息資源. ModuleUtils.getInstance().selectModule(request, getServletContext()); //取出MoudleConfig執行個體config ModuleConfig config = getModuleConfig(request); //根據config裡這個子模組的資訊,從servletcontext裡,取出這個子模組的RequestProcessor執行個體 RequestProcessor processor = getProcessorForModule(config); //如果processor執行個體為空白,就建立一個.同時放到servletcontext裡. if (processor == null) { processor = getRequestProcessor(config); } //調用RequestProcessor的process方法處理, processor.process(request, response); }
三. 擴充ActionServlet類
從Struts1.1開始,為減輕ActionServlet的負擔,多數功能已經移到RequestProcessor類中,所以基本不用擴充ActionServlet類
如果需要建立自己的ActionServlet,則可以建立一個它的子類.覆蓋init()方法(或其他方法),可以寫一些自己的操作,但要先調用super.init();
定義如下的類:
代碼 package sample; public class ExtendedActionServlet extends ActionServlet { public void init() throws ServletException { super.init(); //do some operations …………… } }
擴充完類後,還應該在web.xml檔案中如下配置:
代碼 <servlet> <servlet-name>sample</servlet-name> <servlet-class>sample.ExtendedActionServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>sample</servlet-name> <url-pattern>/action/*<url-pattern>
上面的/action/*表示負責處理所有以/action為首碼的URL,後面的/表示轉義