首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

使用 Spring 更好地处理 Struts 动作(2)技巧

使用 Spring 更好地处理 Struts 动作(2)技巧

窍门 1. 使用 Spring 的 ActionSupport手动创建一个 Spring 环境是一种整合 Struts 和 Spring 的最直观的方式。为了使它变得更简单,Spring 提供了一些帮助。为了方便地获得 Spring 环境,org.springframework.web.struts.ActionSupport类提供了一个 getWebApplicationContext()方法。您所做的只是从 Spring 的 ActionSupport而不是 Struts Action类扩展您的动作,如清单 1 所示:
清单 1. 使用 ActionSupport 整合 Struts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
package ca.nexcel.books.actions;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.ActionError;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.DynaActionForm;
import org.springframework.context.ApplicationContext;
import org.springframework.web.struts.ActionSupport;
import ca.nexcel.books.beans.Book;
import ca.nexcel.books.business.BookService;
public class SearchSubmit extends ActionSupport {   |(1)
public ActionForward execute(
   ActionMapping mapping,
   ActionForm form,
   HttpServletRequest request,
   HttpServletResponse response)
   throws IOException, ServletException {
   DynaActionForm searchForm = (DynaActionForm) form;
   String isbn = (String) searchForm.get("isbn");
        
   //the old fashion way
   //BookService bookService = new BookServiceImpl();
        
   ApplicationContext ctx =
     getWebApplicationContext();    |(2)
   BookService bookService =
     (BookService) ctx.getBean("bookService");   |(3)
        
Book book = bookService.read(isbn.trim());
   if (null == book) {
     ActionErrors errors = new ActionErrors();
     errors.add(ActionErrors.GLOBAL_ERROR,new ActionError
       ("message.notfound"));
     saveErrors(request, errors);
     return mapping.findForward("failure") ;
}
   request.setAttribute("book", book);
   return mapping.findForward("success");
}
}




让我们快速思考一下这里到底发生了什么。在 (1) 处,我通过从 Spring 的 ActionSupport类而不是 Struts 的 Action类进行扩展,创建了一个新的 Action。在 (2) 处,我使用 getWebApplicationContext()方法获得一个 ApplicationContext。为了获得业务服务,我使用在 (2) 处获得的环境在 (3) 处查找一个 Spring bean。
这种技术很简单并且易于理解。不幸的是,它将 Struts 动作与 Spring 框架耦合在一起。如果您想替换掉 Spring,那么您必须重写代码。并且,由于 Struts 动作不在 Spring 的控制之下,所以它不能获得 Spring AOP 的优势。当使用多重独立的 Spring 环境时,这种技术可能有用,但是在大多数情况下,这种方法不如另外两种方法合适。
窍门 2. 覆盖 RequestProcessor将 Spring 从 Struts 动作中分离是一个更巧妙的设计选择。分离的一种方法是使用 org.springframework.web.struts.DelegatingRequestProcessor类来覆盖 Struts 的 RequestProcessor处理程序,如清单 2 所示:
清单 2. 通过 Spring 的 DelegatingRequestProcessor 进行整合
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE struts-config PUBLIC
         "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN"
         "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">
<struts-config>
<form-beans>
   <form-bean name="searchForm"
     type="org.apache.struts.validator.DynaValidatorForm">
              <form-property name="isbn"    type="java.lang.String"/>
   </form-bean>
  
</form-beans>
<global-forwards type="org.apache.struts.action.ActionForward">
    <forward   name="welcome"                path="/welcome.do"/>
    <forward   name="searchEntry"            path="/searchEntry.do"/>
    <forward   name="searchSubmit"           path="/searchSubmit.do"/>
</global-forwards>
<action-mappings>
   <action    path="/welcome" forward="/WEB-INF/pages/welcome.htm"/>
   <action    path="/searchEntry" forward="/WEB-INF/pages/search.jsp"/>
   <action    path="/searchSubmit"
              type="ca.nexcel.books.actions.SearchSubmit"
              input="/searchEntry.do"
              validate="true"
              name="searchForm">
             <forward name="success" path="/WEB-INF/pages/detail.jsp"/>
             <forward name="failure" path="/WEB-INF/pages/search.jsp"/>
   </action>  
</action-mappings>
<message-resources parameter="ApplicationResources"/>
<controller processorClass="org.springframework.web.struts.
  DelegatingRequestProcessor"/> |(1)
<plug-in className="org.apache.struts.validator.ValidatorPlugIn">
   <set-property property="pathnames"
     value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml"/>
</plug-in>
<plug-in className="org.springframework.web.struts.ContextLoaderPlugIn">
   <set-property property="csntextConfigLocation" value="/WEB-INF/beans.xml"/>
</plug-in>

</struts-config>




我利用了 <controller>标记来用 DelegatingRequestProcessor覆盖默认的 Struts RequestProcessor。下一步是在我的 Spring 配置文件中注册该动作,如清单 3 所示:
清单 3. 在 Spring 配置文件中注册一个动作
1
2
3
4
5
6
7
8
9
10
11
12
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="bookService" class="ca.nexcel.books.business.BookServiceImpl"/>
<bean name="/searchSubmit"
   class="ca.nexcel.books.actions.SearchSubmit"> |(1)
    <property name="bookService">
       <ref bean="bookService"/>
    </property>
</bean>
</beans>




注意:在 (1) 处,我使用名称属性注册了一个 bean,以匹配 struts-config 动作映射名称。SearchSubmit动作揭示了一个 JavaBean 属性,允许 Spring 在运行时填充属性,如清单 4 所示:
清单 4. 具有 JavaBean 属性的 Struts 动作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
package ca.nexcel.books.actions;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionError;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.DynaActionForm;
import ca.nexcel.books.beans.Book;
import ca.nexcel.books.business.BookService;
public class SearchSubmit extends Action {
   
private BookService bookService;
public BookService getBookService() {
   return bookService;
}
public void setBookService(BookService bookService) { | (1)
   this.bookService = bookService;
}
public ActionForward execute(
   ActionMapping mapping,
   ActionForm form,
   HttpServletRequest request,
   HttpServletResponse response)
   throws IOException, ServletException {
   DynaActionForm searchForm = (DynaActionForm) form;
   String isbn = (String) searchForm.get("isbn");
        
Book book = getBookService().read(isbn.trim());  |(2)
   if (null == book) {
     ActionErrors errors = new ActionErrors();
     errors.add(ActionErrors.GLOBAL_ERROR,new ActionError("message.notfound"));
     saveErrors(request, errors);
     return mapping.findForward("failure") ;
}
     request.setAttribute("book", book);
     return mapping.findForward("success");
}
}




在清单 4 中,您可以了解到如何创建 Struts 动作。在 (1) 处,我创建了一个 JavaBean 属性。DelegatingRequestProcessor自动地配置这种属性。这种设计使 Struts 动作并不知道它正被 Spring 管理,并且使您能够利用 Sping 的动作管理框架的所有优点。由于您的 Struts 动作注意不到 Spring 的存在,所以您不需要重写您的 Struts 代码就可以使用其他控制反转容器来替换掉 Spring。
DelegatingRequestProcessor方法的确比第一种方法好,但是仍然存在一些问题。如果您使用一个不同的 RequestProcessor,则需要手动整合 Spring 的 DelegatingRequestProcessor。添加的代码会造成维护的麻烦并且将来会降低您的应用程序的灵活性。此外,还有过一些使用一系列命令来代替 Struts RequestProcessor的传闻。 这种改变将会对这种解决方法的使用寿命造成负面的影响。
返回列表