您肯定已经听说过控制反转 (IOC) 设计模式因为很长一段时间以来一直在流传关于它的信息如果您在任何功能中使用过 Spring 框架那么您就知道其原理的作用在本文中我利用这一原理把一个 Struts 应用程序注入 Spring 框架您将亲身体会到 IOC 模式的强大
将一个 Struts 应用程序整合进 Spring 框架具有多方面的优点首先Spring 是为解决一些关于 JEE 的真实世界问题而设计的比如复杂性低性能和可测试性等等第二Spring 框架包含一个 AOP 实现允许您将面向方面技术应用于面向对象的代码第三一些人可能会说 Spring 框架只有处理 Struts 比 Struts 处理自己好但是这是观点问题我演示三种将 Struts 应用程序整合到 Spring 框架的方法后具体由您自己决定使用哪一种
我所演示的方法都是执行起来相对简单的但是它们却具有明显不同的优点我为每一种方法创建了一个独立而可用的例子这样您就可以完全理解每种方法请参阅 下载 部分获得完整例子源代码请参阅 参考资料下载 Struts MVC 和 Spring 框架
为什么 Spring 这么了不起?
Spring 的创立者 Rod Johnson 以一种批判的眼光看待 Java? 企业软件开发并且提议很多企业难题都能够通过战略地使用 IOC 模式(也称作依赖注入)来解决当 Rod 和一个具有奉献精神的开放源码开发者团队将这个理论应用于实践时结果就产生了 Spring 框架简言之Spring 是一个轻型的容器利用它可以使用一个外部 XML 配置文件方便地将对象连接在一起每个对象都可以通过显示一个 JavaBean 属性收到一个到依赖对象的引用留给您的简单任务就只是在一个 XML 配置文件中把它们连接好
IOC 和 Spring
IOC 是一种使应用程序逻辑外在化的设计模式所以它是被注入而不是被写入客户机代码中将 IOC 与接口编程应用结合就像 Spring 框架那样产生了一种架构这种架构能够减少客户机对特定实现逻辑的依赖请参阅 参考资料 了解更多关于 IOC 和 Spring 的信息
依赖注入是一个强大的特性但是 Spring 框架能够提供更多特性Spring 支持可插拔的事务管理器可以给您的事务处理提供更广泛的选择范围它集成了领先的持久性框架并且提供一个一致的异常层次结构Spring 还提供了一种使用面向方面代码代替正常的面向对象代码的简单机制
Spring AOP 允许您使用拦截器 在一个或多个执行点上拦截应用程序逻辑加强应用程序在拦截器中的日志记录逻辑会产生一个更可读的实用的代码基础所以拦截器广泛用于日志记录您很快就会看到为了处理横切关注点Spring AOP 发布了它自己的拦截器您也可以编写您自己的拦截器
整合 Struts 和 Spring
与 Struts 相似Spring 可以作为一个 MVC 实现这两种框架都具有自己的优点和缺点尽管大部分人同意 Struts 在 MVC 方面仍然是最好的很多开发团队已经学会在时间紧迫的时候利用 Struts 作为构造高品质软件的基础Struts 具有如此大的推动力以至于开发团队宁愿整合 Spring 框架的特性而不愿意转换成 Spring MVC没必要进行转换对您来说是一个好消息Spring 架构允许您将 Struts 作为 Web 框架连接到基于 Spring 的业务和持久层最后的结果就是现在一切条件都具备了
在接下来的小窍门中您将会了解到三种将 Struts MVC 整合到 Spring 框架的方法我将揭示每种方法的缺陷并且对比它们的优点 一旦您了解到所有三种方法的作用我将会向您展示一个令人兴奋的应用程序这个程序使用的是这三种方法中我最喜欢的一种
三个小窍门
接下来的每种整合技术(或者窍门)都有自己的优点和特点我偏爱其中的一种但是我知道这三种都能够加深您对 Struts 和 Spring 的理解在处理各种不同情况的时候这将给您提供一个广阔的选择范围方法如下
使用 Spring 的 ActionSupport 类整合 Structs
使用 Spring 的 DelegatingRequestProcessor 覆盖 Struts 的 RequestProcessor
将 Struts Action 管理委托给 Spring 框架
装载应用程序环境
无论您使用哪种技术都需要使用 Spring 的 ContextLoaderPlugin 为 Struts 的 ActionServlet 装载 Spring 应用程序环境就像添加任何其他插件一样简单地向您的 strutsconfigxml 文件添加该插件如下所示
<plugin className=
orgspringframeworkwebstrutsContextLoaderPlugIn>
<setproperty property=
contextConfigLocation value=/WEBINF/beansxml/>
</plugin>
前面已经提到过在 下载 部分您能够找到这三个完全可使用的例子的完整源代码每个例子都为一个书籍搜索应用程序提供一种不同的 Struts 和 Spring 的整合方法您可以在这里看到例子的要点但是您也可以下载应用程序以查看所有的细节
窍门 使用 Spring 的 ActionSupport
手动创建一个 Spring 环境是一种整合 Struts 和 Spring 的最直观的方式为了使它变得更简单Spring 提供了一些帮助为了方便地获得 Spring 环境orgspringframeworkwebstrutsActionSupport 类提供了一个 getWebApplicationContext() 方法您所做的只是从 Spring 的 ActionSupport 而不是 Struts Action 类扩展您的动作如清单 所示
清单 使用 ActionSupport 整合 Struts
package canexcelbooksactions;
import javaioIOException;
import javaxservletServletException;
import javaxservlethttpHttpServletRequest;
import javaxservlethttpHttpServletResponse;
import orgapachestrutsactionActionError;
import orgapachestrutsactionActionErrors;
import orgapachestrutsactionActionForm;
import orgapachestrutsactionActionForward;
import orgapachestrutsactionActionMapping;
import orgapachestrutsactionDynaActionForm;
import orgntextApplicationContext;
import orgspringframeworkwebstrutsActionSupport;
import canexcelbooksbeansBook;
import canexcelbooksbusinessBookService;
public class SearchSubmit extends ActionSupport { |()
public ActionForward execute(
ActionMapping mapping
ActionForm form
HttpServletRequest request
HttpServletResponse response)
throws IOException ServletException {
DynaActionForm searchForm = (DynaActionForm) form;
String isbn = (String) searchFormget(isbn);
//the old fashion way
//BookService bookService = new BookServiceImpl();
ApplicationContext ctx =
getWebApplicationContext();|()
BookService bookService =
(BookService) ctxgetBean(bookService); |()
Book book = bookServiceread(isbntrim());
if (null == book) {
ActionErrors errors = new ActionErrors();
errorsadd(ActionErrorsGLOBAL_ERRORnew ActionError
(messagenotfound));
saveErrors(request errors);
return mappingfindForward(failure) ;
}
requestsetAttribute(book book);
return mappingfindForward(success);
}
}
让我们快速思考一下这里到底发生了什么在 () 处我通过从 Spring 的 ActionSupport 类而不是 Struts 的 Action 类进行扩展创建了一个新的 Action在 () 处我使用 getWebApplicationContext() 方法获得一个 ApplicationContext为了获得业务服务我使用在 () 处获得的环境在 () 处查找一个 Spring bean
这种技术很简单并且易于理解不幸的是它将 Struts 动作与 Spring 框架耦合在一起如果您想替换掉 Spring那么您必须重写代码并且由于 Struts 动作不在 Spring 的控制之下所以它不能获得 Spring AOP 的优势当使用多重独立的 Spring 环境时这种技术可能有用但是在大多数情况下这种方法不如另外两种方法合适
窍门 覆盖 RequestProcessor
将 Spring 从 Struts 动作中分离是一个更巧妙的设计选择分离的一种方法是使用 orgspringframeworkwebstrutsDelegatingRequestProcessor 类来覆盖 Struts 的 RequestProcessor 处理程序如清单 所示
清单 通过 Spring 的 DelegatingRequestProcessor 进行整合
<?xml version= encoding=ISO ?>
<!DOCTYPE strutsconfig PUBLIC
//Apache Software Foundation//DTD Struts Configuration //EN
config__dtd>
<strutsconfig>
<formbeans>
<formbean name=searchForm
type=orgapachestrutsvalidatorDynaValidatorForm>
<formproperty name=isbntype=javalangString/>
</formbean>