为了集成struts,首先要进行Spring上下文的装载,有两种上下文的装载,
(1) 在struts-config.xml中装载Spring上下文,此种装载Spring上下文的方法是利用struts的Plugin机制在 struts-config.xml中声明一个Plugin类org.spring.springframework.web.struts.ContextLoaderPlugIn,代码如下,
<!DOCTYPE struts-config PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 1.3//EN"
"http://struts.apache.org/dtds/struts-config_1_3.dtd">
<struts-config>
<global-forwards>
</global-forwards>
<action-mappings>
<action path="/chartAction" type="lai.chart.ChartAction"
scope="request"
validate="false">
<forward name="diaplay" path="/DisplayChart"/>
</action>
</action-mappings>
<controller processorClass="org.springframework.web.struts.DelegatingRequestProcessor"/>
<message-resources parameter="MessageResources" />
<plug-in className="org.springframework.web.struts.ContextLoaderPlugIn">
<set-property property="contextConfigLocation"
value="/WEB-INF/action-servlet.xml,/WEB-INF/applicationContext.xml"/>
</plug-in>
</struts-config>
(2)在web.xml中装载Spring上下文,此种方法利用J2EE的Servlet2.4规范中的ContextListener机制,代码如下,
在装载了上下文后,我们就可以通过Spring提供的WebApplicationContextUtils工具类,在Web应用的任何场所访问该上下文了,如下,
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<display-name>Spring JPetStore</display-name>
<description>Spring JPetStore sample application</description>
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>/WEB-INF/log4j.properties</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/dataAccessContext-local.xml
/WEB-INF/applicationContext.xml
/WEB-INF/struts-actionmapping.xml
</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
<!--
- Loads the root application context of this web app at startup,
- by default from "/WEB-INF/applicationContext.xml".
- Note that you need to fall back to Spring's ContextLoaderServlet for
- J2EE servers that do not follow the Servlet 2.4 initialization order.
- Use WebApplicationContextUtils.getWebApplicationContext(servletContext)
- to access it anywhere in the web application, outside of the framework.
- The root context is the parent of all servlet-specific contexts.
- This means that its beans are automatically available in these child contexts,
- both for getBean(name) calls and (external) bean references.
-->
<listener>
<listener-class> org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>petstore</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>axis</servlet-name>
<url-pattern>/axis/*</url-pattern>
</servlet-mapping>
</web-app>
如果不支持Servlet2.4则使用Spring提供的ContextLoaderServlet,如下,
<servlet>
<servlet-name>contextLoader</servlet-name>
<servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class>
<load-on-startup>1<load-on-startup>
</servlet>
ApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(servletContext);
另外,还有三种整合手法,分别是
(1)使用Spring的ActionSuport类整合Struts
(2)使用Spring的DelegatingRequestProcessor覆写Struts的RequestProcessor.
(3)使用Spring委托管理Struts的Action
1. 使用 Spring 的 ActionSupport类整合Struts
手动创建一个 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 环境时,这种技术可能有用,但是在大多数情况下,这种方法不如另外两种方法合适。