Posted on 2006-09-29 11:08
城市劣人 閱讀(1996)
評論(0) 編輯 收藏 所屬分類:
Struts 、
Spring
已經轉移到
好·色之徒--我的博客、我的生活1、使用 Spring 的 ActionSupport 類整合 Structs 2、使用 Spring 的 DelegatingRequestProcessor 覆蓋 Struts 的 RequestProcessor 3、將 Struts Action 管理委托給 Spring 框架 首先要建立"裝載應用程序環境" 無論您使用哪種技術,都需要使用 Spring 的 ContextLoaderPlugin 為 Struts 的 ActionServlet 裝載 Spring 應用程序環境。就像添加任何其他插件一樣,簡單地向您的struts-config.xml 文件添加該插件,如下所示:
竅門 1. 使用 Spring 的 ActionSupport 手動創建一個 Spring 環境是一種整合 Struts 和 Spring 的最直觀的方式。為了使它變得更簡單,Spring 提供了一些幫助。為了方便地獲得 Spring 環境,org.springframework.web.struts.ActionSupport 類提供了一個 getWebApplicationContext() 方法。您所做的只是從 Spring 的 ActionSupport 而不是 Struts Action 類擴展您的動作,如清單 1 所示: 清單 1. 使用 ActionSupport 整合 Struts package ca.nexcel.books.actions; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.struts.action.ActionError; import org.apache.struts.action.ActionErrors; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; import org.apache.struts.action.DynaActionForm; import org.springframework.context.ApplicationContext; import org.springframework.web.struts.ActionSupport; import ca.nexcel.books.beans.Book; import ca.nexcel.books.business.BookService; public class SearchSubmit extends ActionSupport { |(1) public ActionForward execute( ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { DynaActionForm searchForm = (DynaActionForm) form; String isbn = (String) searchForm.get("isbn"); //the old fashion way //BookService bookService = new BookServiceImpl(); ApplicationContext ctx = getWebApplicationContext(); |(2) BookService bookService = (BookService) ctx.getBean("bookService"); |(3) Book book = bookService.read(isbn.trim()); if (null == book) { ActionErrors errors = new ActionErrors(); errors.add(ActionErrors.GLOBAL_ERROR,new ActionError ("message.notfound")); saveErrors(request, errors); return mapping.findForward("failure") ; } request.setAttribute("book", book); return mapping.findForward("success"); } } 讓我們快速思考一下這里到底發生了什么。在 (1) 處,我通過從 Spring 的 ActionSupport 類而不是 Struts 的 Action 類進行擴展,創建了一個新的 Action。在 (2) 處,我使用 getWebApplicationContext() 方法獲得一個 ApplicationContext。為了獲得業務服務,我使用在 (2) 處獲得的環境在 (3) 處查找一個 Spring bean。 這種技術很簡單并且易于理解。不幸的是,它將 Struts 動作與 Spring 框架耦合在一起。如果您想替換掉 Spring,那么您必須重寫代碼。并且,由于 Struts 動作不在 Spring 的控制之下,所以它不能獲得 Spring AOP 的優勢。當使用多重獨立的 Spring 環境時,這種技術可能有用,但是在大多數情況下,這種方法不如另外兩種方法合適。 竅門 2. 覆蓋 RequestProcessor 將 Spring 從 Struts 動作中分離是一個更巧妙的設計選擇。分離的一種方法是使用 org.springframework.web.struts.DelegatingRequestProcessor 類來覆蓋 Struts 的 RequestProcessor 處理程序,如清單 2 所示: 清單 2. 通過 Spring 的 DelegatingRequestProcessor 進行整合
|(1) 我利用了
標記來用 DelegatingRequestProcessor 覆蓋默認的 Struts RequestProcessor。下一步是在我的 Spring 配置文件中注冊該動作,如清單 3 所示: 清單 3. 在 Spring 配置文件中注冊一個動作 |(1) 注意:在 (1) 處,我使用名稱屬性注冊了一個 bean,以匹配 struts-config 動作映射名稱。SearchSubmit 動作揭示了一個 JavaBean 屬性,允許 Spring 在運行時填充屬性,如清單 4 所示: 清單 4. 具有 JavaBean 屬性的 Struts 動作 package ca.nexcel.books.actions; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.struts.action.Action; import org.apache.struts.action.ActionError; import org.apache.struts.action.ActionErrors; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; import org.apache.struts.action.DynaActionForm; import ca.nexcel.books.beans.Book; import ca.nexcel.books.business.BookService; public class SearchSubmit extends Action { private BookService bookService; public BookService getBookService() { return bookService; } public void setBookService(BookService bookService) { | (1) this.bookService = bookService; } public ActionForward execute( ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { DynaActionForm searchForm = (DynaActionForm) form; String isbn = (String) searchForm.get("isbn"); Book book = getBookService().read(isbn.trim()); |(2) if (null == book) { ActionErrors errors = new ActionErrors(); errors.add(ActionErrors.GLOBAL_ERROR,new ActionError("message.notfound")); saveErrors(request, errors); return mapping.findForward("failure") ; } request.setAttribute("book", book); return mapping.findForward("success"); } } 在清單 4 中,您可以了解到如何創建 Struts 動作。在 (1) 處,我創建了一個 JavaBean 屬性。DelegatingRequestProcessor自動地配置這種屬性。這種設計使 Struts 動作并不知道它正被 Spring 管理,并且使您能夠利用 Sping 的動作管理框架的所有優點。由于您的 Struts 動作注意不到 Spring 的存在,所以您不需要重寫您的 Struts 代碼就可以使用其他控制反轉容器來替換掉 Spring。 DelegatingRequestProcessor 方法的確比第一種方法好,但是仍然存在一些問題。如果您使用一個不同的 RequestProcessor,則需要手動整合 Spring 的 DelegatingRequestProcessor。添加的代碼會造成維護的麻煩并且將來會降低您的應用程序的靈活性。此外,還有過一些使用一系列命令來代-替 Struts RequestProcessor 的傳聞。 這種改變將會對這種解決方法的使用壽命造成負面的影響。 竅門 3. 將動作管理委托給 Spring 一個更好的解決方法是將 Strut 動作管理委托給 Spring。您可以通過在 struts-config 動作映射中注冊一個代理來實現。代理負責在 Spring 環境中查找 Struts 動作。由于動作在 Spring 的控制之下,所以它可以填充動作的 JavaBean 屬性,并為應用諸如 Spring 的 AOP 攔截器之類的特性帶來了可能。 清單 5 中的 Action 類與清單 4 中的相同。但是 struts-config 有一些不同: 清單 5. Spring 整合的委托方法 清單 5 是一個典型的 struts-config.xml 文件,只有一個小小的差別。它注冊 Spring 代理類的名稱,而不是聲明動作的類名,如(1)處所示。DelegatingActionProxy 類使用動作映射名稱查找 Spring 環境中的動作。這就是我們使用 ContextLoaderPlugIn 聲明的環境。 將一個 Struts 動作注冊為一個 Spring bean 是非常直觀的,如清單 6 所示。我利用動作映射使用 標記的名稱屬性(在這個例子中是 "/searchSubmit")簡單地創建了一個 bean。這個動作的 JavaBean 屬性像任何 Spring bean 一樣被填充: 清單 6. 在 Spring 環境中注冊一個 Struts 動作 動作委托的優點 動作委托解決方法是這三種方法中最好的。Struts 動作不了解 Spring,不對代碼作任何改變就可用于非 Spring 應用程序中。RequestProcessor 的改變不會影響它,并且它可以利用 Spring AOP 特性的優點。 動作委托的優點不止如此。一旦讓 Spring 控制您的 Struts 動作,您就可以使用 Spring 給動作補充更強的活力。例如,沒有 Spring 的話,所有的 Struts 動作都必須是線程安全的。如果您設置 標記的 singleton 屬性為"false",那么不管用何種方法,您的應用程序都將在每一個請求上有一個新生成的動作對象。您可能不需要這種特性,但是把它放在您的工具箱中也很好。-您也可以利用 Spring 的生命周期方法。例如,當實例化 Struts 動作時, 標記的 init-method 屬性被用于運行一個方法。類似地,在從容器中刪除 bean 之前,destroy-method 屬性執行一個方法。這些方法是管理昂貴對象的好辦法,它們以一種與 Servlet 生命周期相同的方式進行管理。 在本文中,您已經學習了將 Struts 動作整合到 Spring 框架中的三種竅門。使用 Spring 的 ActionSupport 來整合 Struts(第一種竅門中就是這樣做的)簡單而快捷,但是會將 Struts 動作與 Spring 框架耦合在一起。如果您需要將應用程序移植到一個不同的框架,則需要重寫代碼。第二種解決方法通過委托 RequestProcessor 巧妙地解開代碼的耦合,但是它的可擴展性不強,并且當 Struts 的 RequestProcessor 變成一系列命令時,這種方法就持續不了很長時間。第三種方法是這三種方法中最好的:將 Struts 動作委托給 Spring 框架可以使代碼解耦,從而使您可以在您的 Struts 應用程序中利用 Spring 的特性(比如日志記錄攔截器)。 綜上所述,也會采用第三種方式來整合。
已經轉移到 好·色之徒--我的博客、我的生活