Spring与Struts对Model-View-Controller模式均提供了很好的支持。相比之下,Struts是一个比较单纯的MVC框架,在实际应用中,开发人员更喜欢使用Struts完成MVC的设计,因而在有必要对Spring与Struts进行整合。
整合的关键点在于:将Struts中Action的实例生成不再由Struts自己负责,而交于Spring容器去管理。因此,进行整合的一个技术前提是Struts中作为Controller的ActionServlet必须能够装载Spring的应用程序环境,而Spring的org.springframework.web.struts.ContextLoaderPlugin恰好提供了这种支持。在Struts的配置文件struts-config.xml中,将ContextLoaderPlugin注册即可,示例如下:
<?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN" "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd"> <struts-config> ... <plug-in className=”org.springframework.web.struts.ContextLoaderPlugin”> <set-property property=”contextConfigLocation” value=”/WEB-INF/config.xml”/> </plug-in> ... </struts-config>
其中的config.xml是Spring的配置文件。
之后,我门可以采用三种方式之一来整合Spring和Struts:
1.Struts的Action继承Spring的ActionSupport类,并在Action中获取Spring的ApplicationContext。这是最简单的一种整合方式,但有三个缺点:第一,Struts与Spring紧密耦合,不能改换到其他IoC容器;第二,难以使用Spring AOP特性;第三,对于需要使用DispatchAction的Struts应用无能为力。
2.在Struts的配置文件中,以Spring的DelegatingRequestProcessor类代替Struts的RequestProcessor类,并在Spring的配置文件中定义与Struts配置文件中<action-mappings>对应的bean,从而将Struts的Action与Spring分开,并把Struts的动作置于Spring的控制之下。这种整合方式的优点是将不再依赖Spring这个特定的IoC容器,但必须依赖Struts的RequestProcessor类。
3.通过Spring的DelegatingActionProxy类代理Struts的动作,即在Struts配置文件中,定义<action-mappings>的type属性全部改为DelegatingActionProxy,而不是具体的类名,并在Spring配置文件中定义与Struts动作映射对应的bean,从而将Struts的Action与Spring分开,并把Struts的动作置于Spring的控制之下。无疑,这是最灵活的一种整合方式。
下面就通过HelloWorld示例来分析一下第三种整合方式的实施步骤。
Step 1:修改Struts的配置文件struts-config.xml <?xml version="1.0" encoding="ISO-8859-1" ?> <!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.2//EN" "http://jakarta.apache.org/struts/dtds/struts-config_1_2.dtd"> <struts-config> <form-beans> <form-bean name="helloWorld" type="com.strutstest.action.HelloWorld"/> </form-beans> <action-mappings> <!--注意此处的type属性定义为DelegatingActionProxy 类--> <action path="/helloWorld" type="org.springframework.web.struts.DelegatingActionProxy" name="helloWorld" validate="true" input="/WEB-INF/jsp/input.jsp"> <forward name="index" path="/WEB-INF/jsp/index.jsp"/> <forward name="show" path="/WEB-INF/jsp/show.jsp"/> </action> <action path="/input" type="org.apache.struts.actions.ForwardAction" parameter="/WEB-INF/jsp/input.jsp"/> </action-mappings> <!--注册ContextLoaderPlugIn --> <plug-in className="org.springframework.web.struts.ContextLoaderPlugIn"> <set-property property="contextConfigLocation" value="/WEB-INF/config.xml" /> </plug-in> <message-resources parameter="messages"/> </struts-config>
Step 2:修改Spring的配置文件config.xml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd"> <beans> <bean id=”helloWorldService” class=”com.strutstest.service.impl.HelloWorldServiceImpl”> </bean> <!--注意此处的映射必须与Struts中的动作对应--> <bean name=”/helloWorld” class=”com.strutstest.action.HelloWorldAction”> <property name=”helloWorldService”> <ref bean=”helloWorldService”/> </property> </bean> </beans>
Step 3:定义作为Model的Action Form类及相应接口、实现
定义Action Form: package com.strutstest.action;
import javax.servlet.http.HttpServletRequest;
import org.apache.struts.action.ActionError;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMapping;
public class HelloWorld extends ActionForm {
private String msg = null;
public void setMsg(String msg) {
this.msg = msg;
}
public String getMsg() {
return this.msg;
}
public void reset(ActionMapping mapping, HttpServletRequest req) {
this.msg = null;
}
public ActionErrors validate(ActionMapping mapping,
HttpServletRequest request) {
ActionErrors errors = new ActionErrors();
if("".equals(getMsg())) {
errors.add("msg",new ActionError("error"));
}
return errors;
}
}
定义HelloWorld类的接口:
package com.strutstest.service;
import com.strutstest.action.HelloWorld;
public interface HelloWorldService {
public abstract String addMsg(HelloWorld helloWorld);
}
定义接口的实现:
package com.strutstest.service.impl; import com.strutstest.action.HelloWorld; import com.strutstest.service.HelloWorldService; public class HelloWorldServiceImpl implements HelloWorldService { public String addMsg(HelloWorld helloWorld) { helloWorld.setMsg("Hello World... " + helloWorld.getMsg()); return helloWorld.getMsg(); } }
Step 4:定义Action
package com.strutstest.action; import java.io.IOException; import java.util.HashMap; import java.util.Map; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.log4j.Logger; import org.apache.struts.action.*; import org.apache.struts.actions.DispatchAction; import org.springframework.context.ApplicationContext; import org.springframework.web.struts.ActionSupport; import com.strutstest.service.HelloWorldService; public class HelloWorldAction extends Action { private Logger logger = Logger.getLogger(this.getClass().getName()); //依赖注入 private HelloWorldService helloWorldService; public HelloWorldService getHelloWorldService () { return helloWorldService; } public void setHelloWorldService (HelloWorldService helloWorldService) { this.helloWorldService = helloWorldService; } public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { String msg = getHelloWorldService().addMsg((HelloWorld)form); request.setAttribute("helloWorld", msg); return mapping.findForward("show"); } }
Step 5:定义视图
定义用户输入界面input.jsp:
<%@ taglib uri="/tags/struts-html" prefix="html" %> <%@ taglib uri="/tags/struts-bean" prefix="bean" %> <%@page contentType="text/html;charset=GBK"%> <html:html locale="true"> <head> <title><bean:message key="title"/></title> <html:base/> </head> <html:messages id="msg"> <bean:write name="msg"/> </html:messages> <body> <form name="HelloWorld" action="/myStruts/helloWorld.do" method="post"> <bean:message key="welcome"/><input type="text" name="msg" value=""/><br> <input type="submit" name="method" value="<bean:message key="submit"/>"/> </form> </body> </html:html>
定义系统响应界面show.jsp:
<%@ taglib uri="/tags/struts-html" prefix="html" %> <%@ taglib uri="/tags/struts-bean" prefix="bean" %> <%@page contentType="text/html;charset=GBK"%> <html:html locale="true"> <head> <title><bean:message key="title"/></title> <html:base/> </head> <body bgcolor="white"> <html:errors/> <html:messages id="msg"> <bean:write name="msg"/> </html:messages> <% String str = (String)request.getAttribute("helloWorld"); %> <body> <font color=”blue”> <bean:message key="input"/>"${helloWorld}"<br> </font> </body> </html:html>
整合的关键点在于:将Struts中Action的实例生成不再由Struts自己负责,而交于Spring容器去管理。因此,进行整合的一个技术前提是Struts中作为Controller的ActionServlet必须能够装载Spring的应用程序环境,而Spring的org.springframework.web.struts.ContextLoaderPlugin恰好提供了这种支持。在Struts的配置文件struts-config.xml中,将ContextLoaderPlugin注册即可,示例如下:
<?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN" "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd"> <struts-config> ... <plug-in className=”org.springframework.web.struts.ContextLoaderPlugin”> <set-property property=”contextConfigLocation” value=”/WEB-INF/config.xml”/> </plug-in> ... </struts-config>
其中的config.xml是Spring的配置文件。
之后,我门可以采用三种方式之一来整合Spring和Struts:
1.Struts的Action继承Spring的ActionSupport类,并在Action中获取Spring的ApplicationContext。这是最简单的一种整合方式,但有三个缺点:第一,Struts与Spring紧密耦合,不能改换到其他IoC容器;第二,难以使用Spring AOP特性;第三,对于需要使用DispatchAction的Struts应用无能为力。
2.在Struts的配置文件中,以Spring的DelegatingRequestProcessor类代替Struts的RequestProcessor类,并在Spring的配置文件中定义与Struts配置文件中<action-mappings>对应的bean,从而将Struts的Action与Spring分开,并把Struts的动作置于Spring的控制之下。这种整合方式的优点是将不再依赖Spring这个特定的IoC容器,但必须依赖Struts的RequestProcessor类。
3.通过Spring的DelegatingActionProxy类代理Struts的动作,即在Struts配置文件中,定义<action-mappings>的type属性全部改为DelegatingActionProxy,而不是具体的类名,并在Spring配置文件中定义与Struts动作映射对应的bean,从而将Struts的Action与Spring分开,并把Struts的动作置于Spring的控制之下。无疑,这是最灵活的一种整合方式。
下面就通过HelloWorld示例来分析一下第三种整合方式的实施步骤。
Step 1:修改Struts的配置文件struts-config.xml <?xml version="1.0" encoding="ISO-8859-1" ?> <!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.2//EN" "http://jakarta.apache.org/struts/dtds/struts-config_1_2.dtd"> <struts-config> <form-beans> <form-bean name="helloWorld" type="com.strutstest.action.HelloWorld"/> </form-beans> <action-mappings> <!--注意此处的type属性定义为DelegatingActionProxy 类--> <action path="/helloWorld" type="org.springframework.web.struts.DelegatingActionProxy" name="helloWorld" validate="true" input="/WEB-INF/jsp/input.jsp"> <forward name="index" path="/WEB-INF/jsp/index.jsp"/> <forward name="show" path="/WEB-INF/jsp/show.jsp"/> </action> <action path="/input" type="org.apache.struts.actions.ForwardAction" parameter="/WEB-INF/jsp/input.jsp"/> </action-mappings> <!--注册ContextLoaderPlugIn --> <plug-in className="org.springframework.web.struts.ContextLoaderPlugIn"> <set-property property="contextConfigLocation" value="/WEB-INF/config.xml" /> </plug-in> <message-resources parameter="messages"/> </struts-config>
Step 2:修改Spring的配置文件config.xml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd"> <beans> <bean id=”helloWorldService” class=”com.strutstest.service.impl.HelloWorldServiceImpl”> </bean> <!--注意此处的映射必须与Struts中的动作对应--> <bean name=”/helloWorld” class=”com.strutstest.action.HelloWorldAction”> <property name=”helloWorldService”> <ref bean=”helloWorldService”/> </property> </bean> </beans>
Step 3:定义作为Model的Action Form类及相应接口、实现
定义Action Form: package com.strutstest.action;
import javax.servlet.http.HttpServletRequest;
import org.apache.struts.action.ActionError;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMapping;
public class HelloWorld extends ActionForm {
private String msg = null;
public void setMsg(String msg) {
this.msg = msg;
}
public String getMsg() {
return this.msg;
}
public void reset(ActionMapping mapping, HttpServletRequest req) {
this.msg = null;
}
public ActionErrors validate(ActionMapping mapping,
HttpServletRequest request) {
ActionErrors errors = new ActionErrors();
if("".equals(getMsg())) {
errors.add("msg",new ActionError("error"));
}
return errors;
}
}
定义HelloWorld类的接口:
package com.strutstest.service;
import com.strutstest.action.HelloWorld;
public interface HelloWorldService {
public abstract String addMsg(HelloWorld helloWorld);
}
定义接口的实现:
package com.strutstest.service.impl; import com.strutstest.action.HelloWorld; import com.strutstest.service.HelloWorldService; public class HelloWorldServiceImpl implements HelloWorldService { public String addMsg(HelloWorld helloWorld) { helloWorld.setMsg("Hello World... " + helloWorld.getMsg()); return helloWorld.getMsg(); } }
Step 4:定义Action
package com.strutstest.action; import java.io.IOException; import java.util.HashMap; import java.util.Map; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.log4j.Logger; import org.apache.struts.action.*; import org.apache.struts.actions.DispatchAction; import org.springframework.context.ApplicationContext; import org.springframework.web.struts.ActionSupport; import com.strutstest.service.HelloWorldService; public class HelloWorldAction extends Action { private Logger logger = Logger.getLogger(this.getClass().getName()); //依赖注入 private HelloWorldService helloWorldService; public HelloWorldService getHelloWorldService () { return helloWorldService; } public void setHelloWorldService (HelloWorldService helloWorldService) { this.helloWorldService = helloWorldService; } public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { String msg = getHelloWorldService().addMsg((HelloWorld)form); request.setAttribute("helloWorld", msg); return mapping.findForward("show"); } }
Step 5:定义视图
定义用户输入界面input.jsp:
<%@ taglib uri="/tags/struts-html" prefix="html" %> <%@ taglib uri="/tags/struts-bean" prefix="bean" %> <%@page contentType="text/html;charset=GBK"%> <html:html locale="true"> <head> <title><bean:message key="title"/></title> <html:base/> </head> <html:messages id="msg"> <bean:write name="msg"/> </html:messages> <body> <form name="HelloWorld" action="/myStruts/helloWorld.do" method="post"> <bean:message key="welcome"/><input type="text" name="msg" value=""/><br> <input type="submit" name="method" value="<bean:message key="submit"/>"/> </form> </body> </html:html>
定义系统响应界面show.jsp:
<%@ taglib uri="/tags/struts-html" prefix="html" %> <%@ taglib uri="/tags/struts-bean" prefix="bean" %> <%@page contentType="text/html;charset=GBK"%> <html:html locale="true"> <head> <title><bean:message key="title"/></title> <html:base/> </head> <body bgcolor="white"> <html:errors/> <html:messages id="msg"> <bean:write name="msg"/> </html:messages> <% String str = (String)request.getAttribute("helloWorld"); %> <body> <font color=”blue”> <bean:message key="input"/>"${helloWorld}"<br> </font> </body> </html:html>