思想:将获取业务逻辑组件的方式放在父类中实现,而其余的Action则从父类中获取。
采用这个策略的优势:
- 可在不同整合策略中自由切换
- 避免重复创建DelegatingActionProxy实例
- 使业务Action避免代码污染
下面举个例子来诠译这种整合方式,首先是BaseAction的源代码:
java 代码
- public class BaseAction extends ActionSupport
- {
- public Object getBean(String beanName)
- {
- return getWebApplicationContext().getBean(beanName);
- }
- }
该父类仅将ActionSupport的方法再次包装,但产生的优势非常明显,至少可以在实际业务Action中避免调用getWebApplicationContext方法。下面是业务Action的源代码:
java 代码
//新的业务控制器,继承BaseAction类 public class LoginAction extends BaseAction { //将一个ValidBean作为成员变量 private ValidBean vb; public LoginAction() { System.out.println("------------"); } //完成ValidBean的初始化 public void setVb() { vb = (ValidBean)getBean("vb"); } //必须重写该核心方法,该方法actionForm将表单的请求参数封装成值对象 public ActionForward execute(ActionMapping mapping,
ActionForm form, HttpServletRequest request,
HttpServletResponse response)throws Exception { LoginForm loginForm = (LoginForm)form; String username = loginForm.getUsername(); String pass = loginForm.getPass(); setVb(); //下面作服务器端的数据校验 String errMsg = ""; if (username == null || username.equals("")) { errMsg += "您的用户名丢失或没有输入,请重新输入"; } else if(pass == null || pass.equals("")) { errMsg += "您的密码丢失或没有输入,请重新输入"; } else { if (vb.valid(username,pass)) { return mapping.findForward("welcome"); } else { errMsg = "您的用户名和密码不匹配"; } } if (errMsg != null && !errMsg.equals("")) { request.setAttribute("err" , errMsg); return mapping.findForward("input"); } else { return mapping.findForward("welcome"); } } }
ActionForm form, HttpServletRequest request,
HttpServletResponse response)throws Exception { LoginForm loginForm = (LoginForm)form; String username = loginForm.getUsername(); String pass = loginForm.getPass(); setVb(); //下面作服务器端的数据校验 String errMsg = ""; if (username == null || username.equals("")) { errMsg += "您的用户名丢失或没有输入,请重新输入"; } else if(pass == null || pass.equals("")) { errMsg += "您的密码丢失或没有输入,请重新输入"; } else { if (vb.valid(username,pass)) { return mapping.findForward("welcome"); } else { errMsg = "您的用户名和密码不匹配"; } } if (errMsg != null && !errMsg.equals("")) { request.setAttribute("err" , errMsg); return mapping.findForward("input"); } else { return mapping.findForward("welcome"); } } }
从代码中可看出,在实际的业务控制器Action中,完全从Spring的API中分离出来,从而可以避免代码污染。
另外,还有一个最大的好处:实际的业务Action并没有与任何的整合策略耦合。假如需要在不同的整合策略之间切换,其业务Action完全不需要改变。
假设需要将整合策略切换到得用Spring IOC特性,则只需将BaseAction改成如下形式:
java 代码
public class BaseAction { //业务逻辑组件 Object serviceObj; //依赖注入必需的setter方法 public void setServiceObj(Object obj) { this.serviceObj = obj; } /** *根据beanName获取容器中的bean实例 */ public Object getBean(String beanName) { return serviceObj: } }
从代码中可以看出,BaseAction等待容器依赖注入。当BaseAction的子类调用getBean方法时,传入的baseName完全没有作用。因为使用了Spring的依赖注入,Action与业务逻辑组件之间的依赖关系可通过配置文件来设定。
下面的示例采用这种整合策略,而Spring管理Action则采用DelegatingRequestProcessor策略。其struts-config.xml和actionServlet的配置文件如下:
xml 代码
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.2//EN" "http://struts.apache.org/dtds/struts-config_1_2.dtd"> <struts-config> <form-beans> <form-bean name="loginForm" type="cn.LoginForm"/> </form-beans> <action-mappings> <!--这里只定义了一个action,而且没有指定该action的type元素--> <action path="/login" name="loginForm" scope="request" validate="true" input="/login.jsp" > <forward name="input" path="/login.jsp"/> <forward name="welcome" path="/welcome.html"/> </action> </action-mappings> <!--使用DelegatingRequestProcessor替换RequestProcessor--> <controller processorClass="org.springframework.web.struts.DelegatingRequestProcessor"/>
<message-resources parameter="mess"/> <!-- 装载验证的资源文件--> <plug-in className="org.apache.struts.validator.ValidatorPlugIn"> <set-property property="pathnames"
value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml" /> <set-property property="stopOnFirstError" value="true"/> </plug-in> <!-- 装载Spring配置文件,随同应用启动创建ApplicationContext实例--> <plug-in className="org.springframework.web.struts.ContextLoaderPlugIn"> <set-property property="contextConfigLocation" value="/WEB-INF/applicationContext.xml, /WEB-INF/action-servlet.xml"/> </plug-in> </struts-config>
<message-resources parameter="mess"/> <!-- 装载验证的资源文件--> <plug-in className="org.apache.struts.validator.ValidatorPlugIn"> <set-property property="pathnames"
value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml" /> <set-property property="stopOnFirstError" value="true"/> </plug-in> <!-- 装载Spring配置文件,随同应用启动创建ApplicationContext实例--> <plug-in className="org.springframework.web.struts.ContextLoaderPlugIn"> <set-property property="contextConfigLocation" value="/WEB-INF/applicationContext.xml, /WEB-INF/action-servlet.xml"/> </plug-in> </struts-config>
action-servlet的配置文件如下:
xml 代码
<?xml version="1.0" encoding="GB2312"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <!--每个request请求产生新实例,所以将action配置成non-singleton--> <bean name="/login" class="lee.LoginAction" singleton="false"> <!--配置依赖注入--> <property name="vb"> <ref bean="vb"/> </property> </bean> </beans>