使用了struts和spring一段時間.但是對其中他們的整合也用了好幾次.就這次機會總結下經驗並整理下思緒.
整合方式1:
最原始而易懂的方式:
Action繼承spring提供的類org.springframework.web.struts.MappingDispatchActionSupport
Action中的代碼:
Java代碼
public class UserAction extends MappingDispatchActionSupport {
public ActionForward login(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
String uname = request.getParameter("uname");
String upass = request.getParameter("upass");
//使用其自帶的一個方法實例化ApplicationContext對象
ApplicationContext context = this.getWebApplicationContext();
userService=(UserService)context.getBean("userService");
User user = userService.findByName(uname, upass);
if (user==null) {
request.setAttribute("error", "對不起,您輸入的用戶名或者密碼錯誤!");
return mapping.findForward("failure");
} else {
request.getSession().setAttribute("user", user);
return mapping.findForward("success");
}
}
}
public class UserAction extends MappingDispatchActionSupport {
public ActionForward login(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
String uname = request.getParameter("uname");
String upass = request.getParameter("upass");
//使用其自帶的一個方法實例化ApplicationContext對象
ApplicationContext context = this.getWebApplicationContext();
userService=(UserService)context.getBean("userService");
User user = userService.findByName(uname, upass);
if (user==null) {
request.setAttribute("error", "對不起,您輸入的用戶名或者密碼錯誤!");
return mapping.findForward("failure");
} else {
request.getSession().setAttribute("user", user);
return mapping.findForward("success");
}
}
}
struts-config.xml代碼:
Java代碼
<action path="/login" parameter="login"
type="com.addresslist.action.UserAction" scope="request">
<forward name="success" path="/page/index.htm"></forward>
</action>
<action path="/login" parameter="login"
type="com.addresslist.action.UserAction" scope="request">
<forward name="success" path="/page/index.htm"></forward>
</action>
你會發現使用這種方法的話.直接可以保持你原先struts的配置.只需要改變一下你相應的Action類繼承MappingDispatchActionSupport.
其中缺點就是:你的Action將會和Spring耦合在一起.當你有多個Action類都繼承MappingDispatchActionSupport的話你將會每次都需要調用getWebApplicationContext()獲取ApplicationContext的實例.這樣如果你想放棄使用spring的話.所要修改的代碼量將非常大
整合方式2:
啓動Spring再在相應的Action類中實例化ApplicationContext
spring有三種啓動方式,使用ContextLoaderServlet,ContextLoaderListener和ContextLoaderPlugIn.
我的測試使用的ContextLoaderListener
web.xml的配置:
Java代碼
<!--
//可以選擇使用ContextLoaderServle
<servlet>
<servlet-name>springInitServlet</servlet-name>
<servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class>
// 如果使用要注意這裏設置開啓的優先級要比Struts的ActionServlet高
<load-on-startup>2</load-on-startup>
</servlet>
-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<!-- 使用ContextLoaderListener -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!--
//可以選擇使用ContextLoaderServle
<servlet>
<servlet-name>springInitServlet</servlet-name>
<servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class>
// 如果使用要注意這裏設置開啓的優先級要比Struts的ActionServlet高
<load-on-startup>2</load-on-startup>
</servlet>
-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<!-- 使用ContextLoaderListener -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
與整合1主要的變化是使用了 <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
形成spring的環境
struts-config.xml代碼:
Java代碼
<action path="/login" parameter="login"
type="com.addresslist.action.UserAction" scope="request">
<forward name="success" path="/page/index.htm"></forward>
</action>
<!--
可以選擇使用
<plug-in
className="org.springframework.web.struts.ContextLoaderPlugIn">
<set-property property="contextConfigLocation"
value="/WEB-INF/applicationContext.xml" />
</plug-in>
-->
<action path="/login" parameter="login"
type="com.addresslist.action.UserAction" scope="request">
<forward name="success" path="/page/index.htm"></forward>
</action>
<!--
可以選擇使用
<plug-in
className="org.springframework.web.struts.ContextLoaderPlugIn">
<set-property property="contextConfigLocation"
value="/WEB-INF/applicationContext.xml" />
</plug-in>
-->
Action的代碼:
Java代碼
public class UserAction extends MappingDispatchAction {
public UserService getFileService(){
//這裏使用了WebApplicationContextUtils工具類實例化ApplicationContext
ApplicationContext ac=WebApplicationContextUtils.getWebApplicationContext(this.getServlet().getServletContext());
return (UserService) ac.getBean("userService");
}
public ActionForward login(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
String uname = request.getParameter("uname");
String upass = request.getParameter("upass");
User user = getFileService().findByName(uname, upass);
if (user==null) {
request.setAttribute("error", "對不起,您輸入的用戶名或者密碼錯誤!");
return mapping.findForward("failure");
} else {
request.getSession().setAttribute("user", user);
return mapping.findForward("success");
}
}
}
public class UserAction extends MappingDispatchAction {
public UserService getFileService(){
//這裏使用了WebApplicationContextUtils工具類實例化ApplicationContext
ApplicationContext ac=WebApplicationContextUtils.getWebApplicationContext(this.getServlet().getServletContext());
return (UserService) ac.getBean("userService");
}
public ActionForward login(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
String uname = request.getParameter("uname");
String upass = request.getParameter("upass");
User user = getFileService().findByName(uname, upass);
if (user==null) {
request.setAttribute("error", "對不起,您輸入的用戶名或者密碼錯誤!");
return mapping.findForward("failure");
} else {
request.getSession().setAttribute("user", user);
return mapping.findForward("success");
}
}
}
WebApplicationContextUtils(參考於http://tech.ddvip.com/2007-08/118764954132510_8.html)
當 Web 應用集成 Spring 容器後,代表 Spring 容器的EebApplicationContext 對象將以
WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE 爲鍵存放在 ServletContext 屬性列表中。您當然可以直接通過以下語句獲取 WebApplicationContext:
WebApplicationContext wac = (WebApplicationContext)servletContext.
getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
但通過位於 org.springframework.web.context.support 包中的WebApplicationContextUtils 工具類獲取 WebApplicationContext 更方便:
WebApplicationContext wac =WebApplicationContextUtils.
getWebApplicationContext(servletContext);
當 ServletContext 屬性列表中不存在 WebApplicationContext 時,getWebApplicationContext() 方法不會拋出異常,它簡單地返回 null。如果後續代碼直接訪問返回的結果將引發一個 NullPointerException 異常,而 WebApplicationContextUtils 另一個 getRequiredWebApplicationContext(ServletContext sc) 方法要求 ServletContext 屬性列表中一定要包含一個有效的 WebApplicationContext 對象,否則馬上拋出一個 IllegalStateException 異常。我們推薦使用後者,因爲它能提前發現錯誤的時間,強制開發者搭建好必備的基礎設施。
通過該方式整合我們只需要進行啓動Spring和在相應的Action類獲取WebApplicationContext .這樣子對Spring的耦合降低
整合方式3:將動作管理委託給 Spring
將Struts的動作管理委託給Spring.使用Struts-config.xml的動態映射中註冊一個代理.
代理負責在Spring中找到Struts的動作.由於動作在Spring的控制之下.所以Spring可以對Action進行javaBean的注入和Spring的一些Aop使用
需要發生改變的配置有:
Struts-config.xml:
Java代碼
<struts-config>
<data-sources />
<form-beans />
<global-exceptions />
<global-forwards />
<action-mappings>
<!--這裏使用了org.springframework.web.struts.DelegatingAction-->
<action path="/login" parameter="login" type="org.springframework.web.struts.DelegatingActionProxy">
<forward name="success" path="/page/index.htm"/>
<forward name="failure" path="/page/fail.htm"/>
</action>
</action-mappings>
<message-resources
parameter="com.addresslist.properties.ApplicationResources" />
<!--這裏使用ContextLoaderPlugIn建立Spring的環境-->
<plug-in
className="org.springframework.web.struts.ContextLoaderPlugIn">
<set-property property="contextConfigLocation"
value="/WEB-INF/applicationContext.xml" />
</plug-in>
<struts-config>
<data-sources />
<form-beans />
<global-exceptions />
<global-forwards />
<action-mappings>
<!--這裏使用了org.springframework.web.struts.DelegatingAction-->
<action path="/login" parameter="login" type="org.springframework.web.struts.DelegatingActionProxy">
<forward name="success" path="/page/index.htm"/>
<forward name="failure" path="/page/fail.htm"/>
</action>
</action-mappings>
<message-resources
parameter="com.addresslist.properties.ApplicationResources" />
<!--這裏使用ContextLoaderPlugIn建立Spring的環境-->
<plug-in
className="org.springframework.web.struts.ContextLoaderPlugIn">
<set-property property="contextConfigLocation"
value="/WEB-INF/applicationContext.xml" />
</plug-in>
Action中的代碼:
Java代碼
public class UserAction extends MappingDispatchAction {
//使用普遍依賴注入方式
UserService userService;
public void setUserService(UserService userService) {
this.userService = userService;
}
public ActionForward login(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
String uname = request.getParameter("uname");
String upass = request.getParameter("upass");
//直接使用userService
User user = userService.findByName(uname, upass);
if (user==null) {
request.setAttribute("error", "對不起,您輸入的用戶名或者密碼錯誤!");
return mapping.findForward("failure");
} else {
request.getSession().setAttribute("user", user);
return mapping.findForward("success");
}
}
}
public class UserAction extends MappingDispatchAction {
//使用普遍依賴注入方式
UserService userService;
public void setUserService(UserService userService) {
this.userService = userService;
}
public ActionForward login(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
String uname = request.getParameter("uname");
String upass = request.getParameter("upass");
//直接使用userService
User user = userService.findByName(uname, upass);
if (user==null) {
request.setAttribute("error", "對不起,您輸入的用戶名或者密碼錯誤!");
return mapping.findForward("failure");
} else {
request.getSession().setAttribute("user", user);
return mapping.findForward("success");
}
}
}
這個配置只於傳統的struts-config的配置.這裏使用的是Spring的註冊代理.而不是直接使用相應Action類的完整類名.
這裏使用的ContextLoaderPlugIn.聲明的環境。通過DelegatingActionProxy使用動作映射名/login在Spring環境中找到相應的Action.所以我們需要在Spring環境中註冊一個Struts的動作:
Java代碼
<bean name="/login" class="com.addresslist.action">
<property name="userService" ref="userService"></property>
</bean>
<bean name="/login" class="com.addresslist.action">
<property name="userService" ref="userService"></property>
</bean>
這個方法可以說是多數人認可最好的方法:
這個方法的使用只在配置文件中着手不需要對源碼進行修改.將struts動作放置到Spring中使得其享受了Spring提供的各種好處.一旦讓 Spring 控制您的 Struts 動作,您就可以使用 Spring 給動作補充更強的活力。例如,沒有 Spring 的話,所有的 Struts 動作都必須是線程安全的。如果您設置 <bean> 標記的 singleton 屬性爲“false”,那麼不管用何種方法,您的應用程序都將在每一個請求上有一個新生成的動作對象。您也可以利用 Spring 的生命週期方法。例如,當實例化 Struts 動作時,<bean> 標記的 init-method 屬性被用於運行一個方法。類似地,在從容器中刪除 bean 之前,destroy-method 屬性執行一個方法.
整合方式4:
使用 org.springframework.web.struts.DelegatingRequestProcessor 類來覆蓋 Struts 的 RequestProcessor 處理程序
只需要在struts-config.xml中配置:
Java代碼
<action-mappings>
<action path="/login" parameter="login" type="com.addresslist.action.UserAction">
<forward name="success" path="/page/index.htm"/>
<forward name="failure" path="/page/fail.htm"/>
</action>
<!--下面controller配置是核心-->
<controller processorClass="org.springframework.web.struts.
DelegatingRequestProcessor"/>
<plug-in
className="org.springframework.web.struts.ContextLoaderPlugIn">
<set-property property="contextConfigLocation"
value="/WEB-INF/applicationContext.xml" />
</plug-in>
<action-mappings>
<action path="/login" parameter="login" type="com.addresslist.action.UserAction">
<forward name="success" path="/page/index.htm"/>
<forward name="failure" path="/page/fail.htm"/>
</action>
<!--下面controller配置是核心-->
<controller processorClass="org.springframework.web.struts.
DelegatingRequestProcessor"/>
<plug-in
className="org.springframework.web.struts.ContextLoaderPlugIn">
<set-property property="contextConfigLocation"
value="/WEB-INF/applicationContext.xml" />
</plug-in>
Struts中的action配置則無需配置type屬性(即使配置了type屬性也不起任何作用,除非在spring的配置文件裏找不到對應的name屬性值)
其他的配置和類使用和整合方式3一樣.
這個設計方式是使用Spring提供的一個RequestProcessor來進行工作.這裏如果對struts工作流程比較熟悉的話就指定struts1.2真正工作的核心是RequestProecssor和Action.
這裏使用Spring的DelegatingRequestProcessor替換了struts的RequestProcessor.可以使得struts享受到Spring的控制容器.網上人都不建議使用這種方法.因爲考慮到效率和方法使用壽命的問題.所以我也比較少用.
總結語:
通過以上的總結。大概瞭解了struts和Spring整合的幾種方式.
原文來自:雨楓技術教程網 http://www.fengfly.com
原文網址:http://www.fengfly.com/plus/view-168039-1.html