`

基于JBoss Seam拦截器的异常消息提示体系设计(一)

阅读更多
每个技术体系框架都有自己的消息(message)机制,Struts2框架下有ActionError、ActionMessage、FieldError这三种消息方式,JSF框架也提供了消息API—FacesMessage,这些消息处理结合页面消息标签,将程序产生的错误、人为的消息显示在页面上,给用户非常友好的提示。但是在使用这些消息API的时候,我感觉这些提供的功能还是比较原始,达不到我想要的程度。比如,在Struts2中我如果想将错误消息通过弹出框弹出,我发现是一种非常难以实现的工作。在不使用AJAX的时候,本页提示更是想都不敢想,还要防止出错后的重复提交问题。采用基于事件的JSF框架,本页消息提示容易实现多了,通过<h:outputText>标签输出类似于<script>alert(‘程序出错啦’)</script>来达到弹出提示的功能,但是这种实现方式如此简陋。在OECP项目中,客户端采用的是基于JSF的架构,怎样来提供统一的、漂亮的消息提示呢?同时怎样将捕获到的所有异常来封装成消息来显示到客户端呢?现在我就来简单的介绍一下OECP项目中对异常消息提示体系的设计思路。
       JSF作为一个标准大力推广,然而SUN却没有提供一个非常强大的实现,SUN的实现太简陋了,网上笔诛讨伐甚多。开发JSF应用,我们依然要采用其他第三方的实现,现在存在比较成熟的第三方实现主要有Apache的MyFaces,JBoss的Richfaces,ICEFaces,甚至把Seam也加上。Seam作为JBoss大力发展的大一统的Web集成框架,已经在各方面展示强劲的能力。OECP客户端也是基于JBoss Seam框架体系的,引入JBoss Seam后,在拦截器、UI展现等方面都对JSF起到一个非常好的补充。
为什么要引入JBoss Seam的拦截器,主要是因为虽然JSF的监听器机制虽然已经比较强大了,但是却存在一个缺陷(也许是自己才疏学浅没有研究深入)。JSF提供的 PhaseListener接口提供了两个方法beforePhase和afterPhase让我们在事件执行前后做一些处理,但是我却得不到当前执行的类、方法,我无法获得这些方法操作的控制权,最简单的异常捕获封装消息的操作都不知道怎么实现,这让我很怀念Struts2的拦截器功能。幸亏JBoss Seam想到了这些问题,JBoss Seam为自己的组件提供了强大的拦截器实现,通过JBoss Seam的拦截器我们不就可以将所有的操作给拦住,然后做加工处理了吗?那就看看JBoss Seam是怎么做的吧。
      首先要为你的应用添加JBoss Seam,这个我就不多说了,google一下吧。OECP项目开始就使用JBoss Seam构建,所以那就赶紧添加拦截器吧。在使用EJB的情况下,JBoss Seam推荐使用会话Bean作为Seam的action,使用EJB标准的拦截器和Seam本身的拦截器都可以很好工作。但是在OECP项目中,我们为了保证业务组件的纯洁性(按标准实现,无框架污染),我们放弃了JBoss Seam的方式而采用了JavaEE标准的分层架构,那么客户端的Action就是简单的Manage Bean。

1、将这个Manage Bean变成Seam的组件。将action类加入Seam提供的@Name注解,这个普通的manage bean就成了Seam组件。

Java代码

   1. @Name("resourceRegisterAction") 
   2. @Scope(ScopeType.PAGE) 
   3. public class ResourceRegisterAction 

2、构建拦截器

Seam构建拦截器的方式是采用的标准的JavaEE体系。如下面代码所示,构造一个拦截机要有一个带有InvocationContext参数的方法,返回值使用Object。需要注意的是,一定要加上@AroundInvoke这个注解,否则框架不将它作为拦截方法。然后在 ic.proceed()前后就可以加入你要处理的操作了。建议继承seam提供的AbstractInterceptor,seam会在效率上进行相应的优化。isInterceptorEnabled是该拦截器的开关,如果返回false,该拦截器将不可用。该方法在容器一启动就加载执行,不要想着在里面处理一些动态的信息。
Java代码

   1. public class DefaultActionInterceptor extends AbstractInterceptor { 
   2.     private Object rv = null; 
   3. @AroundInvoke 
   4. public Object aroundInvoke(InvocationContext ic) throws Exception { 
   5.                     try { 
   6.                         rv = ic.proceed(); 
   7.                     } catch (Exception e) { 
   8.                         dealException(ic, e); 
   9.                     } 
  10. return rv;           
  11. } 
  12.                  
  13.                 @Override 
  14.                 public boolean isInterceptorEnabled() { 
  15.                     return true; 
  16.                 } 
  17.                  
  18. } 



3、封装异常消息

在OECP中,我们把异常粗略的分为业务异常和系统异常。对于这两种异常我们将区分对待。业务异常是EJB业务组件抛出的业务执行过程中出现的异常,而系统异常通常是客户端的程序书写存在问题而出现的异常。我们把异常信息包装后,通过OecpUtil.setPopMsg(msg)将异常信息放到 request上下文中,并在页面上显示出来。
Java代码

   1. private void dealException(InvocationContext ic, Exception e) 
   2.                 throws NamingException { 
   3.                 if (e instanceof BusinessEJBException) { 
   4.                     OecpUtil.setPopMsg(new Message("出错提示", e.getMessage())); 
   5.                     BusinessEJBException be = (BusinessEJBException) e; 
   6.                     if (!be.isLogged()) {// 如果该异常没有被记录,则调用日志记录组件记录 
   7.                         log(ic, be); 
   8.                 } 
   9.             } else { 
  10.                 OecpUtil.setPopMsg(new Message("出错提示", 
  11.                     "程序出现错误,您可以拨打以下电话告知处理。1364642****")); 
  12.                 log(ic, e); 
  13.             } 
  14. } 
  15.  
  16. OecpUtil.java 
  17. public static void setPopMsg(Message message) { 
  18. FacesUtil.getExternalContext().getRequestMap().put("_pop", message); 
  19.     } 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics