思想:将获取业务逻辑组件的方式放在父类中实现,而其余的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>