已經(jīng)轉(zhuǎn)移到 好·色之徒--我的博客、我的生活
1、使用 Spring 的 ActionSupport 類整合 Structs 2、使用 Spring 的 DelegatingRequestProcessor 覆蓋 Struts 的 RequestProcessor 3、將 Struts Action 管理委托給 Spring 框架 首先要建立"裝載應(yīng)用程序環(huán)境" 無論您使用哪種技術(shù),都需要使用 Spring 的 ContextLoaderPlugin 為 Struts 的 ActionServlet 裝載 Spring 應(yīng)用程序環(huán)境。就像添加任何其他插件一樣,簡單地向您的struts-config.xml 文件添加該插件,如下所示: 竅門 1. 使用 Spring 的 ActionSupport 手動創(chuàng)建一個 Spring 環(huán)境是一種整合 Struts 和 Spring 的最直觀的方式。為了使它變得更簡單,Spring 提供了一些幫助。為了方便地獲得 Spring 環(huán)境,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"); } } 讓我們快速思考一下這里到底發(fā)生了什么。在 (1) 處,我通過從 Spring 的 ActionSupport 類而不是 Struts 的 Action 類進行擴展,創(chuàng)建了一個新的 Action。在 (2) 處,我使用 getWebApplicationContext() 方法獲得一個 ApplicationContext。為了獲得業(yè)務(wù)服務(wù),我使用在 (2) 處獲得的環(huán)境在 (3) 處查找一個 Spring bean。 這種技術(shù)很簡單并且易于理解。不幸的是,它將 Struts 動作與 Spring 框架耦合在一起。如果您想替換掉 Spring,那么您必須重寫代碼。并且,由于 Struts 動作不在 Spring 的控制之下,所以它不能獲得 Spring AOP 的優(yōu)勢。當使用多重獨立的 Spring 環(huán)境時,這種技術(shù)可能有用,但是在大多數(shù)情況下,這種方法不如另外兩種方法合適。 竅門 2. 覆蓋 RequestProcessor 將 Spring 從 Struts 動作中分離是一個更巧妙的設(shè)計選擇。分離的一種方法是使用 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 中,您可以了解到如何創(chuàng)建 Struts 動作。在 (1) 處,我創(chuàng)建了一個 JavaBean 屬性。DelegatingRequestProcessor自動地配置這種屬性。這種設(shè)計使 Struts 動作并不知道它正被 Spring 管理,并且使您能夠利用 Sping 的動作管理框架的所有優(yōu)點。由于您的 Struts 動作注意不到 Spring 的存在,所以您不需要重寫您的 Struts 代碼就可以使用其他控制反轉(zhuǎn)容器來替換掉 Spring。 DelegatingRequestProcessor 方法的確比第一種方法好,但是仍然存在一些問題。如果您使用一個不同的 RequestProcessor,則需要手動整合 Spring 的 DelegatingRequestProcessor。添加的代碼會造成維護的麻煩并且將來會降低您的應(yīng)用程序的靈活性。此外,還有過一些使用一系列命令來代-替 Struts RequestProcessor 的傳聞。 這種改變將會對這種解決方法的使用壽命造成負面的影響。 竅門 3. 將動作管理委托給 Spring 一個更好的解決方法是將 Strut 動作管理委托給 Spring。您可以通過在 struts-config 動作映射中注冊一個代理來實現(xiàn)。代理負責在 Spring 環(huán)境中查找 Struts 動作。由于動作在 Spring 的控制之下,所以它可以填充動作的 JavaBean 屬性,并為應(yīng)用諸如 Spring 的 AOP 攔截器之類的特性帶來了可能。 清單 5 中的 Action 類與清單 4 中的相同。但是 struts-config 有一些不同: 清單 5. Spring 整合的委托方法 清單 5 是一個典型的 struts-config.xml 文件,只有一個小小的差別。它注冊 Spring 代理類的名稱,而不是聲明動作的類名,如(1)處所示。DelegatingActionProxy 類使用動作映射名稱查找 Spring 環(huán)境中的動作。這就是我們使用 ContextLoaderPlugIn 聲明的環(huán)境。 將一個 Struts 動作注冊為一個 Spring bean 是非常直觀的,如清單 6 所示。我利用動作映射使用 標記的名稱屬性(在這個例子中是 "/searchSubmit")簡單地創(chuàng)建了一個 bean。這個動作的 JavaBean 屬性像任何 Spring bean 一樣被填充: 清單 6. 在 Spring 環(huán)境中注冊一個 Struts 動作 動作委托的優(yōu)點 動作委托解決方法是這三種方法中最好的。Struts 動作不了解 Spring,不對代碼作任何改變就可用于非 Spring 應(yīng)用程序中。RequestProcessor 的改變不會影響它,并且它可以利用 Spring AOP 特性的優(yōu)點。 動作委托的優(yōu)點不止如此。一旦讓 Spring 控制您的 Struts 動作,您就可以使用 Spring 給動作補充更強的活力。例如,沒有 Spring 的話,所有的 Struts 動作都必須是線程安全的。如果您設(shè)置 標記的 singleton 屬性為"false",那么不管用何種方法,您的應(yīng)用程序都將在每一個請求上有一個新生成的動作對象。您可能不需要這種特性,但是把它放在您的工具箱中也很好。-您也可以利用 Spring 的生命周期方法。例如,當實例化 Struts 動作時, 標記的 init-method 屬性被用于運行一個方法。類似地,在從容器中刪除 bean 之前,destroy-method 屬性執(zhí)行一個方法。這些方法是管理昂貴對象的好辦法,它們以一種與 Servlet 生命周期相同的方式進行管理。 在本文中,您已經(jīng)學(xué)習了將 Struts 動作整合到 Spring 框架中的三種竅門。使用 Spring 的 ActionSupport 來整合 Struts(第一種竅門中就是這樣做的)簡單而快捷,但是會將 Struts 動作與 Spring 框架耦合在一起。如果您需要將應(yīng)用程序移植到一個不同的框架,則需要重寫代碼。第二種解決方法通過委托 RequestProcessor 巧妙地解開代碼的耦合,但是它的可擴展性不強,并且當 Struts 的 RequestProcessor 變成一系列命令時,這種方法就持續(xù)不了很長時間。第三種方法是這三種方法中最好的:將 Struts 動作委托給 Spring 框架可以使代碼解耦,從而使您可以在您的 Struts 應(yīng)用程序中利用 Spring 的特性(比如日志記錄攔截器)。 綜上所述,也會采用第三種方式來整合。
已經(jīng)轉(zhuǎn)移到 好·色之徒--我的博客、我的生活
1、使用 Spring 的 ActionSupport 類整合 Structs 2、使用 Spring 的 DelegatingRequestProcessor 覆蓋 Struts 的 RequestProcessor 3、將 Struts Action 管理委托給 Spring 框架 首先要建立"裝載應(yīng)用程序環(huán)境" 無論您使用哪種技術(shù),都需要使用 Spring 的 ContextLoaderPlugin 為 Struts 的 ActionServlet 裝載 Spring 應(yīng)用程序環(huán)境。就像添加任何其他插件一樣,簡單地向您的struts-config.xml 文件添加該插件,如下所示:
已經(jīng)轉(zhuǎn)移到 好·色之徒--我的博客、我的生活