1 struts的action继承自spring的ActionSupport,ActionSupport可以获得spring的ApplicationContext,因此就可以获得注入的业务层组件.
在struts-config.xml中配置ContextLoaderPlugIn(这3中方式都需要它加载spring配置文件,装载spring ioc, 下同略),
- <plug-in className="org.springframework.web.struts.ContextLoaderPlugIn">
- <set-property property="contextConfigLocation" value="/WEB-INF/applicationContext.xml" />
- </plug-in>
写Action:
- public class LoginAction extends ActionSupport{
- public ActionForward execute(ActionMapping arg0, ActionForm arg1,
- HttpServletRequest arg2, HttpServletResponse arg3) throws Exception {
- //获得spring上下文
- ApplicationContext ctx = super.getWebApplicationContext();
- UserService userService = (UserService)ctx.getBean("userService");
- arg2.setAttribute("user", arg1);
- LoginForm user = (LoginForm)arg1;
- if(userService.checkUser(user)){
- return arg0.findForward("success");
- }
- return arg0.findForward("false");
- }
- }
- <action-mappings>
- <action path="/login"
- type="web.action.LoginAction"
- name="loginForm"
- scope="request"
- validate="true"
- input="/login.jsp" >
- <forward name="false" path="/login.jsp" />
- <forward name="success" path="/userdetail.jsp" />
- </action>
- <action path="/welcome" forward="/welcome.jsp" />
- </action-mappings>
可以看到上面的LoginAction需要UserService,但是我们已经不再采用 UserService service = new UserServiceImpl();的写法了.UserService交给spring管理.
applicationContext.xml中配置业务组件UserService,
- <bean id="userService" class="web.service.UserServiceImpl" />
LoginForm,login.jsp和UserService代码都很简单,不说了,下载包中有. 部署测试.
这种做法的好处是简单易上手,最符合常规的思维.不是要spring管理业务组件么? 那就在Action中获得spring上下文即可. 但是这种做法却和spring的api耦合在一起了.离开了spring这个LoginAction就没用了. 还有一点就是这种方式还可以通过ContextLoaderListener来实现,而且不必使Action和spring耦合在一起.具体怎么做就不多说了.在web.xml中配置ContextLoaderListener.在Action中通过WebApplicationContextUtils获得spring上下文从而获得业务组件.
2 第二种做法; 替换请求处理器, 先来思考一下struts处理请求的流程:ActionServlet获得请求*.do, ActionServlet把请求委托给RequestProcessor, RequestProcessor根据请求的path在配置文件中找到对应的Action并实例化它. 调用Action的execute方法返回forward.如果对这个过程有疑问,可以阅读一下ActionServlet和RequestProcessor源代码.
如果可以改写一下请求处理器RequestProcessor, 让它在获得Action实例的时候从spring容器中获得Spring托管的Action,则spring不仅可以管理业务组件,还可以管理Action, 第二种做法正是这样做的.
在struts中配置controller用来替换默认的RequestProcessor,
- <controller processorClass="org.springframework.web.struts.DelegatingRequestProcessor"/>
LoginAction按照struts的写法,继承自Action. 同时对它依赖的组件UserService也不需要获取它的实例.
- public class LoginAction extends Action{
- private UserService userService;
- public UserService getUserService() {
- return userService;
- }
- public void setUserService(UserService userService) {
- this.userService = userService;
- }
- public ActionForward execute(ActionMapping arg0, ActionForm arg1,
- HttpServletRequest arg2, HttpServletResponse arg3) throws Exception {
- System.out.println(arg1);
- arg2.setAttribute("user", arg1);
- LoginForm user = (LoginForm)arg1;
- if(userService.checkUser(user)){
- return arg0.findForward("success");
- }
- return arg0.findForward("false");
- }
- }
在applicationContext.xml中装配LoginAction和UserService,
- <bean id="userService" class="web.service.UserService" />
- <bean name="/login" class="web.action.LoginAction">
- <property name="userService" ref="userService" />
- </bean>
其他配置照旧. 运行, 测试.
3 第三种做法: 使用spring的代理Action DelegatingActionProxy.这种做法是: struts的代码都不要动,不需要覆盖RequestProcessor,LoginAction仍然继承自Action, 只需要在struts-config.xml上改一下action的type:
- <action-mappings>
- <action path="/login"
- type="org.springframework.web.struts.DelegatingActionProxy"
- name="loginForm"
- scope="request"
- validate="true"
- input="/login.jsp" >
- <forward name="false" path="/login.jsp" />
- <forward name="success" path="/userdetail.jsp" />
- </action>
- <action path="/welcome" forward="/welcome.jsp" />
- </action-mappings>
这个DelegatingActionProxy可以查找spring上下文中配置的Action,并执行它的execute方法.