天天看點

struts1與spring的內建

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"/>,寫上是為了解決我們上面提到的“不夠直覺的”的問題

源自:http://blog.sina.com.cn/s/blog_6145ed810100dvmf.html

繼續閱讀