现在的位置: 首页 > 综合 > 正文

Spring与Struts1的集成

2013年02月25日 ⁄ 综合 ⁄ 共 11695字 ⁄ 字号 评论关闭

Spring和Struts整合的价值在于将Struts使用的BO或DAO 乃至Action交给Spring管理,从而充分利用Spring强大的IoC和AOP 特性。

无论使用哪种方式整合,都需要为 Struts装载 Spring 应用上下文环境。有以下三种方式:



1) 在struts-config.xml中使用Struts Plugin

<plug-in className="org.springframework.web.struts.ContextLoaderPlugIn">


<set-property property="contextConfigLocation"   

   value="/WEB-INF/classes/applicationContext.xml,/WEB-INF/action-servlet.xml"/>

</plug-in>

2) 在web.xml中使用ContextLoaderListener

<context-param>

      <param-name>contextConfigLocation</param-name>

      <param-value>/WEB-INF/classes/applicationContext.xml</param-value>

</context-param>

<listener>

      <listener-class>

           org.springframework.web.context.ContextLoaderListener

      </listener-class>

</listener>

3) 在web.xml中使用ContextLoaderServlet

<context-param>

      <param-name>contextConfigLocation</param-name>

      <param-value>/WEB-INF/classes/applicationContext.xml</param-value>

</context-param>

<servlet>

     <servlet-name>SpringContextServlet</servlet-name>

     <servlet-class>

         org.springframework.web.context.ContextLoaderServlet

     </servlet-class>

     <load-on-startup>1</load-on-startup>

</servlet>

注意:

用Struts PlugIn的方式加载Spring配置文件有可能导致DWR无法取得Spring中定义的bean,因为DWR有可能先于Struts被访问使用,而此时Struts配置文件还未加载!

因此,在Spring、Struts和DWR 集成时,应该在web.xml中通过ContextLoaderLisenter或ContextLoaderServlet加载Spring配置文件。

最佳实践是使用Struts PlugIn的方式加载Struts Action配置文件/WEB-INF/action-servlet.xml,而使用ContextLoaderLisenter或ContextLoaderServlet方式加载Spring配置文件applicationContext.xml,通过两次加载完成Spring所有配置文件的加载。

至少有四种Spring与Struts整合方式:

       

1.      手工创建Spring 环境整合 Spring和Struts

   为了Web应用环境可以和Spring的IoC容器很好的结合,Spring提供了专门用于Web应用

环境中的Spring容器——WebApplicationContext。使用ContextLoaderPlugIn装载 Spring 应

用程序环境时,ContextLoaderPlugIn会自动创建一个WebApplicationContext对象,并加载

相应的配置文件,然后将其保存在ServletContext中。之后所有的Servlet或Action便都可以过

ServletContext访问该WebApplicationContext实例并从中获取BO或DAO Bean。



ServletContext servletContext=this.getServlet().getServletContext();

WebApplicationContext ctx=

        WebApplicationContextUtils.getWebApplicationContext(servletContext);

UserInfoDAO userInfoDAO=(UserInfoDAO)ctx.getBean("userInfoDAO");

2.      使用 Spring 的 ActionSupport 类整合 Struts

org.springframework.web.struts.ActionSupport 类提供了一个 getWebApplicationContext() 方法可以获取到WebApplicationContext实例,您所做的只是从 Spring 的 ActionSupport 而不是 Struts Action 类扩展您的动作:



public class AddActionSupport extends ActionSupport {

    public ActionForward execute(ActionMapping mapping, ActionForm form,

            HttpServletRequest request, HttpServletResponse response) {

        AddForm addForm = (AddForm) form;

        UserInfo user=new UserInfo();

        user.setUserName(addForm.getName());

        user.setUserPwd(addForm.getPassword());

        UserInfoDAO userInfoDAO=

                           (UserInfoDAO)getWebApplicationContext().getBean("userInfoDAO");


        userInfoDAO.save(user);

        return mapping.findForward("success");

    }

}

        结论:第1、2种整合方式由Spring来管理BO或DAO Bean,实现了表示层和业务逻辑层的解耦,但Struts的Action和Spring耦合在了一起,违反了Spring“非侵入”性原则;另外,Action类负责查找由Spring管理的Bean,也违背了Spring控制反转(IoC)的原则。以下第3、4种整合方式实现了由Spring来管理Struts Action,实现了Struts和Spring的解耦,从而解决了以上问题。

3.      使用 Spring 的 DelegatingRequestProcessor 覆盖 Struts 的 RequestProcessor

用Spring的DelegatingRequestProcessor重载Struts 默认的 RequestProcessor。这样当收到一个针对Action的请求时,DelegatingRequestProcessor会自动从Spring Context中查找对应的Action Bean。

在struts-config.xml中添加:

<controller processorClass="org.springframework.web.struts.DelegatingRequestProcessor"/>

4.      【最佳方案】使用DelegatingActionProxy将Struts Action 管理全权委托给 Spring 框架

即:使用spring的aop动态代理机制



Action 的创建和对象的依赖注入全部由IOC容器来完成,使用Spring的DelegatingAcionProxy来帮助

实现代理的工作。DelegatingActiongProxy继承于org.apache.struts.action.Action 。此时需要将struts-

config.xml中所有Action类别全部配置为 org.springframework.web.struts.DelegatingActionProxy:

<action

      attribute="loginForm"

      input="/login.jsp"

      name="loginForm"

      path="/login"

      scope="request"

      type="org.springframework.web.struts.DelegatingActionProxy">

      <forward name="error" path="/error.html" />

      <forward name="success" path="/success.html" />

</action>

3、4两种方式都需要在WEB-INF下新建一个action-servlet.xml作为Spring context文件,创建Struts Action Bean,并对Action进行BO或DAO Bean注入:

<!--name 的取值一定要和Struts 配置文件action 中的path 的值相对应-->

<bean name="/login" class="cn.qdqn.ssh.struts.action.LoginAction">

      <property name="userBO">

       <ref bean="userBO"/>

      </property>

</bean>

结论:

以上2种方式实现了由Spring管理Struts的Action,从而可以利用Spring在Struts Action中轻松的注入BO或DAO,还可以将 Spring 的 AOP 拦截器应用于Struts 动作,用最小的代价处理横切关注点。

第3种整合方式只需要配置一个<controller>,不需要改动Struts Action配置信息,但Struts的 RequestProcessor只能被重载一次,如果在应用中还要进行编码等其它功能RequestProcessor重载时,此种方式将异常繁琐。

第4种整合方式可以避免RequestProcessor的占用,但必须将struts-config.xml中所有Action类别全部配置为 org.springframework.web.struts.DelegatingActionProxy。

源自:http://fengqinyun168.blog.163.com/blog/static/114628027200931710350646/

spring和struts1.x的整合有三种方法:本人习惯使用其中的一种,在这里做一下简要的介绍,如果对其他整合方法感兴趣的话,可以查阅相关资料。

低耦合的Struts集成Spring的实例 (以简单的学生管理系统为例)

我们在集成Spring和struts的时候,往往习惯于使用spring提供的ActionSupport,然后使用getWebApplicationContext()方法获得spring的bean,这样固然方便,但有一个弊端,就是我们的struts action依赖了spring的api,增加了耦合,现在什么都流行高内聚,低耦合,spring为我们提供了代理的Struts action,这样,我们在struts-config.xml不再为path设置真正的action,而是设计spring的代理Action,然后由spring的代理action,去寻找在spring
bean 容器中的真正的action,这样,我们的action是一个完全没有依赖于spring的action ,具体实现请看以下代码:

public class StudentAction extends DispatchAction {

private StudentDao studentDao;
private GradeDao gradeDao;
  
public StudentDao getStudentDao() {
  return studentDao;
}

public void setStudentDao(StudentDao studentDao) {
  this.studentDao = studentDao;
}
 
public GradeDao getGradeDao() {
  return gradeDao;
}

public void setGradeDao(GradeDao gradeDao) {
  this.gradeDao = gradeDao;
}

public ActionForward loadadd(ActionMapping mapping, ActionForm form,
   HttpServletRequest request, HttpServletResponse response)
   throws Exception {
     List<Grade> list = gradeDao.list();
     request.setAttribute("list", list);
  return mapping.findForward("loadadd");
}

public ActionForward add(ActionMapping mapping, ActionForm form,
   HttpServletRequest request, HttpServletResponse response)
   throws Exception {
  StudentForm sf = (StudentForm)form;
  Student stu = sf.getStu();
 
  String gradeId = request.getParameter("gradeId");
  Grade grade = new Grade();
  grade.setGradeId(Integer.parseInt(gradeId));
 
  stu.setGrade(grade);
 
  studentDao.add(stu);
  return mapping.findForward("add");
}

public ActionForward loadedit(ActionMapping mapping, ActionForm form,
   HttpServletRequest request, HttpServletResponse response)
   throws Exception {
  String id = request.getParameter("id");
  Student stu = studentDao.getStu(Integer.parseInt(id));
  request.setAttribute("stu", stu);
  List<Grade> list = gradeDao.list();
     request.setAttribute("list", list);
  return mapping.findForward("loadedit");
}

public ActionForward edit(ActionMapping mapping, ActionForm form,
   HttpServletRequest request, HttpServletResponse response)
   throws Exception {
  StudentForm sf = (StudentForm)form;
  Student stu = sf.getStu();
 
  String gradeId = request.getParameter("gradeId");
  Grade grade = new Grade();
  grade.setGradeId(Integer.parseInt(gradeId));
 
  stu.setGrade(grade);
 
  studentDao.edit(stu);
  return mapping.findForward("edit");
}

public ActionForward delete(ActionMapping mapping, ActionForm form,
   HttpServletRequest request, HttpServletResponse response)
   throws Exception {
  String id = request.getParameter("id");
  studentDao.delete(Integer.parseInt(id));
  return mapping.findForward("delete");
}

public ActionForward list(ActionMapping mapping, ActionForm form,
   HttpServletRequest request, HttpServletResponse response)
   throws Exception {
  List<Student> list = studentDao.list();
  request.setAttribute("list", list);
   return mapping.findForward("list");
}

public ActionForward search(ActionMapping mapping, ActionForm form,
   HttpServletRequest request, HttpServletResponse response)
   throws Exception {
  String gradeId= request.getParameter("gradeId");
  Map<String, String> map = new HashMap<String, String>();
  map.put("gradeId", gradeId);
  List<Student> list  = studentDao.search(map);
  request.setAttribute("list", list);
  return mapping.findForward("search");
}
}

Dao接口的实现类:

public class StudentDaoImpl extends HibernateDaoSupport implements StudentDao {

public void add(Student stu) {
  getHibernateTemplate().save(stu);
}

public void delete(int id) {
  getHibernateTemplate().delete(
    getHibernateTemplate().get(Student.class, id));
}

public void edit(Student stu) {
  getHibernateTemplate().update(stu);
}

public Student getStu(int id) {
  return (Student) getHibernateTemplate().get(Student.class, id);
}

public List<Student> list() {
  return getHibernateTemplate().loadAll(Student.class);
}

public List<Student> search(Map<String, String> map) {
  List<Student> list = null;
  String gradeId = map.get("gradeId");
  String hql = "from Student where 1=1 ";
 
  if (gradeId != null && !"".equals(gradeId)) {
   hql += " and gradeId=" + gradeId;
  }
list =  getHibernateTemplate().find(hql);
  return list;
}

}

现在书写struts-config.xml文件:

<struts-config>
  <data-sources />
  <form-beans>
      <form-bean name="studentForm" type="com.ssh.form.StudentForm" />
      <form-bean name="gradeForm" type="com.ssh.form.GradeForm" />
  </form-beans>
  <global-exceptions />
  <global-forwards />
  <action-mappings>
       <action path="/student"
               type="org.springframework.web.struts.DelegatingActionProxy"
               parameter="cmd"
               name="studentForm"
               scope="request">
            <forward name="loadadd" path="/student_add.jsp" />
            <forward name="add" path="/student.do?cmd=list" redirect="true" />
            <forward name="loadedit" path="/student_edit.jsp" />
            <forward name="edit" path="/student.do?cmd=list" redirect="true" />
            <forward name="delete" path="/student.do?cmd=list" redirect="true" />
            <forward name="list" path="/student_list.jsp" />
            <forward name="search" path="/student_list.jsp" />
          
       </action>
       <action path="/grade"
               type="org.springframework.web.struts.DelegatingActionProxy"
               parameter="cmd"
               name="gradeForm"
               scope="request">
            <forward name="loadadd" path="/grade_add.jsp" />
            <forward name="add" path="/grade.do?cmd=list" redirect="true" />
            <forward name="loadedit" path="/grade_edit.jsp" />
            <forward name="edit" path="/grade.do?cmd=list" redirect="true" />
            <forward name="delete" path="/grade.do?cmd=list" redirect="true" />
            <forward name="list" path="/grade_list.jsp" />
            <forward name="search" path="/grade_list.jsp" />
          
       </action>
  </action-mappings>
  <message-resources parameter="ApplicationResources" />
<plug-in className="org.springframework.web.struts.ContextLoaderPlugIn">
     <set-property property="contextConfigLocation" value="classpath:applicationContext-*.xml"/>
  </plug-in>
</struts-config>

applicationContext.xml配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

<!-- 声明dao的实现类 -->
<bean id="studentDao" class="com.ssh.dao.impl.StudentDaoImpl">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>
<bean id="gradeDao" class="com.ssh.dao.impl.GradeDaoImpl">
      <property name="sessionFactory" ref="sessionFactory" />
</bean>
<!-- 与struts的整合 -->
<bean name="/student"
class="com.ssh.action.StudentAction
">
   <property name="studentDao" ref="studentDao" />
   <property name="gradeDao" ref="gradeDaoProxy" />
</bean>
<bean name="/grade" class="com.ssh.action.GradeAction">
   <property name="gradeDao" ref="gradeDao" />
</bean>
</beans>

需要说明的是,由于spring dtd规定id不能有"/",所以我们用name定义path,并且,spring bean的name要和struts-config.xml中的path一致

使用DelegatingActionProxy的好处就在于你可以用不用任何spring特定的类编写Struts Action,这个方法也有不足之处,就是不太直观,因为所有路径都映射到同一个类了

对于这种情况,spring也有解决方法,就是使用请求委托

首先,为struts-config.xml增加controller

  <!-- 使用请求委托 -->
<controller processorClass="org.springframework.web.struts.DelegatingRequestProcessor">
</controller>
然后,修改我们的path定义位 <action path="/listStudentAction" type="action.ListStudentActionAction"/>

这样,又和我们单独使用struts的时候一样了,但内部还是让spring取代理我们的真正的action

需要说明的是,这里的type其实是个摆设,完全可以使用 <action path="/listStudentAction"/>,写上是为了解决我们上面提到的“不够直观的”的问题

抱歉!评论已关闭.