分享
 
 
 

J2EE中的异常管理及错误跟踪框架二(图)

王朝java/jsp·作者佚名  2008-05-31
窄屏简体版  字體: |||超大  

许多人认为SUN应该在每应用的基础上给J2EE框架内置插入所有容器的钩子。这样就答应自定义错误处理方案、安全及更多可安装的功能,而不需要依靠特定厂商的方案和框架。不幸地是,SUN并没有在EJB规范中提供这样的机制。既然如此,我们只有拿出AOP这个强有力的工具来增加异常处理。我们选择的aspectWerkz框架,可以如下使用方面:

public class EJBExceptionHandler implements AroundAdvice {PRivate ExceptionHandler handler;

public EJBExceptionHandler() {handler = ConfigHelper.getEJBExceptionHandler();

} public Object invoke(JoinPoint joinPoint) throws Throwable {Log log = LogFactory.getLog(joinPoint.getEnclosingStaticJoinPoint().getClass().getName());

log.debug("EJB Exception Handler bean context aspect!!");

try { return joinPoint.proceed();

} catch (RuntimeException e) { handler.handle(Thread.currentThread(), e);

} catch (Error e) { handler.handle(Thread.currentThread(), e);

}return null;

}}

实际的处理器是通过ConfigHelper类来配置和获取的。假如RuntimeException 或者Error在业务逻辑处理过程被抛出时,处理器就会被请求处理了。

DefaultEJBExceptionHandler序列化任何并非来自SUN核心包异常的堆栈信息到专门的SerializableException中,这从好的方面来看,可以将在远程客户端不存在的类的异常的堆栈以任意方式传播,另一方面,这会丢失原始的异常。

假如客户端是远程的,EJB容器忠实地捕捉RuntimeException或Error并将他包在java.rmi.RemoteException中,否则使用javax.ejb.EJBException。为了在最低程度保持来源的精确性及堆栈信息,框架在BusinessDelegates剥离传送异常并重新抛出原始异常。

Rampart框架的BusinessDelegate类提供一个EJB无关的接口给客户端,而在内部包含本地或远程的EJB接口。BusinessDelegate类从EJB实现类中用XDoclet生成的,他遵循图4中UML图结构:

BusinessDelegate提供所有来自源EJB实现类的业务方法并代理给相应的LocalProxy或RemoteProxy类。在内部两个代理类处理EJB相关的异常,从而隐藏了BusinessDelegate的实现细节。下面的代码是来自某个LocalProxy类的方法:

public java.lang.String someOtherMethod(){ try {return serviceInterface.someOtherMethod();

} catch (EJBException e) {BusinessDelegateUtil.throwActualException(e);

} return null;

// Statement is never reached}

serviceInterface变量代表EJB本地接口。任何被容器抛出的EJBException实例意味着一个未知错误被BusinessDelegateUtil类捕捉和处理,如下面发生的操作:

public static void throwActualException(EJBException e) { doThrowActualException(e);

}private static void doThrowActualException(Throwable actual) { boolean done = false;

while(!done) {if(actual instanceof RemoteException) { actual = ((RemoteException)actual).detail;

} else if (actual instanceof EJBException) { actual = ((EJBException)actual).getCausedByException();

} else { done = true;

} } if(actual instanceof RuntimeException) {throw (RuntimeException)actual;

} else if (actual instanceof Error) {throw (Error)actual;

}}

actual异常被摘出并重新被抛出给顶层的客户端异常处理器。当异常到达处理器时,堆栈信息会是来自服务端且包含实际错误的原始异常。没有多余的客户端信息被附加。

Swing异常处理器

JVM为每一个控制线程提供了缺省的顶层异常处理器。在异常发生时,处理器输出Error或RuntimeException的堆栈信息到System.err并且结束线程。这种处理行为与用户的要求相差很远而且从调试的观点来看也不是很优雅。我们需要一种机制在保存堆栈信息和为以后调试预备的唯一请求ID的同时答应通知用户。“创建基于J2EE的应用范围用户会话”描述了如何在所有层都可以形成这样的请求ID。

J2SE1.4以前的版本,在Thread实例中未捕捉的异常将导致其所在的ThreadGroup的uncaughtException()方法被执行。在应用中控制异常处理的简单方法是继续ThreadGroup类,重写uncaughtException()方法,并且确认所有Thread在自定义的ThreadGroup类的实例中启动。

J2SE5提供了一种更方便的机制答应在Thread类的实例中安装UncaughtExceptionHandler实现。处理器在未捕捉的异常到达Thread实例的运行方法中通过回调机制起作用。我们的框架基于J2SE1.3+,因而使用基于继续ThreadGroup的方法:

private static class SwingThreadGroup extends ThreadGroup { private ExceptionHandler handler; public SwingThreadGroup(ExceptionHandler handler) {super("Swing ThreadGroup");this.handler = handler; } public void uncaughtException(Thread t, Throwable e) {handler.handle(t, e); }}

在上面的代码断中SwingThreadGroup类重写了uncaughtException()方法并传递Thread实例及抛出Throwable给配置的异常处理器。

在我们在客户端层控制所有未处理的异常之前还需要做些技巧性的工作。为了使用这个方案有效,所有线程必须与我们的SwingThreadGroup实例关联。这可以通过生成一个主Thread实例并且通过Runnable实现传递SwingThreadGroup实例,这样就可以执行整个程序了。所有来自这个新的主Thread实例的Thread实例自动加入SwingThreadGroup实例,因此当非强制异常被抛出时会触发新的异常处理器。

点击查看大图

如图5中框架在SwingExceptionHandlerController类中实现这个逻辑。应用提供SwingMain接口的实现和异常处理器给控制器。然后控制器必须启动,同时旧的主线程可以加入新线程中并等待结束。下面的代码显示演示应用如何完成这种任务。createAndShowGUI()方法构成实际的应用内容用来初始化Swing组件及传送控制给用户。

public DemoApp() { SwingExceptionHandlerController.setHandler(new DefaultSwingExceptionHandler());

SwingExceptionHandlerController.setMain(new SwingMain() {public Component getParentComponent() { return frame;

}public void run() { createAndShowGUI();

} });

SwingExceptionHandlerController.start();

SwingExceptionHandlerController.join();

}

防卫的底线现在在Swing层了,但我们依然需要提供有意义的信息给用户。演示应用提供了一种更基本的实现,可以简单地显示国际化信息的对话框和唯一的用来给支持人员的请求ID。一个更复杂的错误处理器可以发送email、SNMP信息或者包含请求ID的技术支持。要害的是客户端及服务端日志可以用请求ID来过滤从而使基于每个请求的定位更精确。

图6显示合并的Swing客户端及J2EE服务端日志为请求ID为1cffeb4:feb53del38:-7ff6提供精确的定位。注重堆栈信息仅包含来自服务端的信息,而异常就是来自那儿。

虽然为独立的J2SE应用增加异常处理的底层框架是基础的,但当我们移植到基于网页客户端时还是需要作些改变。

WAR异常处理器

网页应用在J2EE开发中是比较幸运的,拥有自己安装异常处理的能力。通过web.xml配置描述文档,异常和HTTP错误可以在servlets或jsp中映射到错误页面。看一下下面的来自web.xml文档中的示例片断:

<servlet

<servlet-nameErrorHandlerServlet</servlet-name

<servlet-classdk.rhos.fw.rampart.util.errorhandling.ErrorHandlerServlet</servlet-class</servlet<servlet-mapping <servlet-nameErrorHandlerServlet</servlet-name

<url-pattern/errorhandler</url-pattern</servlet-mapping<error-page

<exception-typejava.lang.Throwable</exception-type

<location/errorhandler</location</error-page

这些标记指示所有未处理的异常会转到/errorhandler这个URL去,在这里就是映射到ErrorHandlerServlet类。这是一个专门的servlet用来作为网页组件与异常处理框架之间的桥梁。当来自网页应用的未处理异常到达servlet容器中,一组包含异常信息的参数会被增加到HttpServletRequest实例并且传递给ErrorHandlerServlet类的service方法。下面的片断例示了service方法:

...private static final String CONST_EXCEPTION = "javax.servlet.error.exception";

...protected void service(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse)

throws ServletException, IOException {

Throwable exception = (Throwable)httpServletRequest.getAttribute(CONST_EXCEPTION);

ExceptionHandler handler = ConfigHelper.getWARExceptionHandler();

handler.handle(Thread.

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有