编者按本文叙述了作者在运用Struts过程中来之不易的若干经验和心得如果你是jsp和servlet开发Web应用的Java程序员并且也正在考虑采用基于Struts的构建方法的话那么你会在这里发现很多颇有见地同时也很有价值的信息
只在必要的时候才考虑扩展Struts框架
一个好的framework有很多优点首先它必须能够满足用户的可预见的需求为此 Struts为Web 应用提供了一个通用的架构这样开发人员可以把精力集中在如何解决实际业务问题上其次一个好的framework还必须能够在适当的地方提供扩展接口以便应用程序能扩展该框架来更好的适应使用者的实际需要
如果Struts framework在任何场合任何项目中都能很好的满足需求那真是太棒了但是实际上没有一个框架声称能做到这一点一定会有一些特定的应用需求是框架的开发者们无法预见到的因此最好的办法就是提供足够的扩展接口使得开发工程师能够调整struts来更好的符合他们的特殊要求
在Struts framework中有很多地方可供扩展和定制几乎所有的配置类都能被替换为某个用户定制的版本这只要简单的修改一下Struts的配置文件就可以做到
其他组件如ActionServlet和 RequestProcessor 也能用自定义的版本代替 甚至连Struts 里才有的新特性也是按照扩展的原则来设计的例如在异常处理机制中就允许用户定制异常处理的句柄以便更好的对应用系统发生的错误做出响应
作为框架的这种可调整特性在它更适合你的应用的同时也在很大的程度上影响了项目开发的效果首先由于您的应用是基于一个现有的成熟的稳定的framework如Struts测试过程中发现的错误数量将会大大减少同时也能缩短开发时间和减少资源的投入因为你不再需要投入开发力量用于编写基础框架的代码了
然而 实现更多的功能是要花费更大的代价的我们必须小心避免不必要的滥用扩展性能 Struts是由核心包加上很多工具包构成的它们已经提供了很多已经实现的功能因此不要盲目的扩展Struts框架要先确定能不能采用其他方法使用现有的功能来实现 在决定编写扩展代码前务必要确认Struts的确没有实现你要的功能否则重复的功能会导致混乱将来还得花费额外的精力清除它
使用异常处理声明
要定义应用程序的逻辑流程成熟的经验是推荐在代码之外用配置的方法来实现而不是写死在程序代码中的在JEE中这样的例子比比皆是从实现EJB的安全性和事务性行为到描述JMS消息和目的地之间的关系很多运行时的处理流程都是可以在程序之外定义的
Struts 创建者从一开始就采用这种方法通过配置Struts的配置文件来定制应用系统运行时的各个方面这一点在版本的新特性上得到延续包括新的异常处理功能在Struts framework以前的版本中开发人员不得不自己处理Struts应用中发生的错误情况在最新的版本中情况大大的改观了Struts Framework提供了内置的一个称为 ExceptionHandler 的类 用于系统缺省处理action类运行中产生的错误这也是在上一个技巧中我们提到的framework许多可扩展接口之一
Struts缺省的 ExceptionHandler类会生成一个ActionError对象并保存在适当的范围(scope)对象中这样就允许JSP页面使用错误类来提醒用户出现什么问题如果你认为这不能满足你的需求那么可以很方便的实现你自己的ExcepionHandler类
具体定制异常处理的方法和机制
要定制自己的异常处理机制第一步是继承orgapachestrutsactionExceptionHandler类这个类有个方法可以覆盖一个是excute()另外一个是storeException() 在多数情况下只需要覆盖其中的excute()方法下面是ExceptionHandler类的excute()方法声明
正如你看到的该方法有好几个参数其中包括原始的异常方法返回一个ActionForward对象用于异常处理结束后将controller类带到请求必须转发的地方去
当然您可以实现任何处理但一般而言我们必须检查抛出的异常并针对该类型的异常进行特定的处理缺省的系统的异常处理功能是创建一个出错信息同时把请求转发到配置文件中指定的地方去 定制异常处理的一个常见的例子是处理嵌套异常假设该异常包含有嵌套异常这些嵌套异常又包含了其他异常因此我们必须覆盖原来的execute()方法对每个异常编写出错信息
一旦你创建了自己的ExceptionHandler 类就应该在Struts配置文件中的部分声明这个类以便让Struts知道改用你自定义的异常处理取代缺省的异常处理
可以配置你自己的ExceptionHandler 类是用于Action Mapping特定的部分还是所有的Action对象如果是用于Action Mapping特定的部分就在元素中配置如果想让这个类可用于所有的Action对象可以在 元素中指定例如假设我们创建了异常处理类CustomizedExceptionHandler用于所有的Action类 元素定义如下所示
在元素中可以对很多属性进行设置在本文中最重要的属性莫过于handler属性 handler属性的值就是自定义的继承了ExceptionHandler类的子类的全名 假如该属性没有定义Struts会采用自己的缺省值当然其他的属性也很重要但如果想覆盖缺省的异常处理的话handler无疑是最重要的属性
最后必须指出的一点是你可以有不同的异常处理类来处理不同的异常在上面的例子中CustomizedExceptionHandler用来处理任何javalangException的子类 其实你也可以定义多个异常处理类每一个专门处理不同的异常树下面的XML片断解释了如何配置以实现这一点
在这里一旦有异常抛出struts framework将试图在配置文件中找到ExceptionHandler如果没有找到那么struts将沿着该异常的父类链一层层往上找直到发现匹配的为止因此我们可以定义一个层次型的异常处理关系结构在配置文件中已经体现了这一点