- 浏览: 373304 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
y806839048:
启动activemq我试了,也不行
ActiveMQ5.0实战三:使用Spring发送,消费topic和queue消息 -
y806839048:
是不是要另外启动activemq
ActiveMQ5.0实战三:使用Spring发送,消费topic和queue消息 -
y806839048:
为什么我的两个应用中,不能实现通信
ActiveMQ5.0实战三:使用Spring发送,消费topic和queue消息 -
fengfujie:
[flash=200,200][/flash][tr][th] ...
JMS消息类型模型 -
fengfujie:
...
JMS消息类型模型
作者:Jean-Pierre Norguet,JavaWorld.com,11/15/07
在一个面向对象的项目中,设计异常处理的最好途径从来也没有如我们期待的那样清晰。在旧的大的系统中,异常的发生有激增的趋势,最终达到几百行 的代码。对于一些常见的编程场景,异常检查是必须的,但是也会带来可观的处理开销。虽然安静的异常捕获可以找到问题的源头,但是避免不了它的一些缺点(虽 然这些缺点不是致命的);比如你必须熟悉这些代码。
序
本文将介绍如何通过有限的异常集合来满足一个错误处理的需求。在建立起一个好的错误处理系统框架之后,将会指出异常处理设计中常见的错误,这些错误将会逐 渐损害应用程序的性能;然后将会给出一个异常集合的例子,这个例子支持本文讨论的异常处理设计的基本功能:异常系统应该被设计成能够帮助外部系统(用户) 处理未知情况(在运行时发生),而不是设计成能够帮助编程人员处理已知情况;还会介绍本文给出例子中的各个类的含义以及如何在一个特定的Java企业应用 程序体系中使用它们;最后给出这个例子的Java实现。
错误处理需求
什么是一个好的错误处理系统?抛开审美角度的考虑,一个好的错误处理系统通常要符合下面的条件:
1、任何异常都不会导致应用系统的崩溃。
2、在发生异常时,允许应用程序进行相应的处理。
3、显示给用户的错误信息要清晰的描述发生了什么错误以及应该采取什么样的处理。
4、如果需要辅助信息,错误信息还要帮助用户与帮助部门交互,为帮助部门团队提供必要的信息,
使他们能够快速的容易的重现错误。
5、日志信息能为开发团队人员在识别错误、在应用程序代码中定位错误产生的位置以及修正错误提供必要的信息。
6、错误处理代码不会降低应用程序代码的可读性。必要的时候,错误处理仅仅是一个安全网,它对应用程序的核心功能具
有较低的访问权限。
一个错误处理系统的设计符合这些条件才能被认为是完整的。对于大多数Java开发人员来说接下来的问题就是:如何灵活的使用异常类来设计一个错误处理系统,而不是通过简单的重载它们来实现。
应该避免的常见用法
可以通过一个有限的异常类集合来满足上面提到的需求。当设计这样的一个异常类集合时,你应该避免一些常见的用法,例如:
1、对每个问题都定义的异常类,这样会导致系统中异常类的激增。
2、对每个包定义一个异常类集合,这没什么用处而且也会导致系统中异常类的激增。
3、对每个异常都提供checked和non-checked两个版本,引入了检测异常开销。异常语义的后续副本也会混淆异常处理的设计。
4、最后,抛出和捕获通用异常在很多方面也是错误倾向。
本文下面提到的异常类集合按照错误处理语义分类,避免了异常处理相关的常见问题。尤其是在应用程序的规模和复杂程度增长是,这种方式更值得推荐。
异常处理设计
图1展示了异常类集合的设计,这个设计避免了异常类激增、检测异常开销和异常的安静捕获。
图1.一个异常类集合的例子
在这个图中你会发现有些异常是checked,而有些是runtime。为了避免异常抛出声明的开销,checked异常基于下面两个目的被保留下来:
- 告诉调用方法,在这个处理过程中发生了一个可预见的意外情况。在这种情况下,问题的语义已经被处理方法定义了,直接捕获会更好。
- 告诉外部系统发生了一个未解决的问题,需要根据异常语义来处理这个问题。
理解异常语义
在这里阐明本文对异常语义的定义。在作者看来,设计对象的类需要根据它们在现实世界中的等价物。一个水果或者一个人很容易设计成一个Java对象类。但是 异常设计却不同:因为一个水果或者一个人在现实世界中非常直观,异常却不同。实际上,上面的两类异常中,只有第一类在现实世界中存在;而第二类异常模拟了 系统执行过程中会发生什么错误,因此在系统之外就不存在了。直接捕获因此也只对第一类异常适合。
作者的设计建议就是异常应该根据它们的目的来设计。系统内部的、自我调整的异常就意味着是帮助系统来处理不可预见的情况。这些异常的目的也就不是模拟系统中的问题,而是给一个系统需要采取什么措施的指示。
一个异常类集合的例子
在图1中你可以看到四类异常对应四类处理,如下:
- BusinessException:一种异常情况发生。这种情况是可预见的,也可以被调用方法检测到并立即采取措施。
- ParameterException:输入的数据对处理过程不合法。用户被要求重新输入有效数据或者修改处理过程的条件。
- TechnicalException:技术问题,如无效的SQL语句。这种情况下,请求操作未完成。用户需要和帮助部门联系,调查问题的原因;或者尝试其它的服务。对使用系统的其它用户没有影响。
- CriticalTechnicalException:技术问题,如数据库崩溃。用户被建议稍后重试。在问题修复前,所有的用户都不能使用系统。
这个异常类集合只是一个例子;很多异常类集合都可以参照它来定义。例如,TechnicalException和 CriticalTechnicalException可以被设计成一个类,这个类声明一个severity布尔属性。重要的是关注采取什么处理措施而不 是什么问题引起异常。
异常日志记录
虽然异常语义关注采取的措施,但是出现的问题也很重要。例如,开发团队人员可以使用这些信息调试代码。在异常处理设计中,导致异常的信息能够在以用程序的 错误日志中发现。在适当的位置使用一个好的日志记录框架,这个框架能够有效的从异常信息和堆栈跟踪中记录问题信息。
剩下的唯一问题就是怎么样设计异常类使之能够方便的返回信息。一个解决方案就是为异常类声明一个id属性来代表遇到的问题的种类。另外,问题自身 可带有通用异常,也就是把通用异常内嵌到应用程序异常中。在捕获的时候,原始的信息和堆栈跟踪信息能够通过内嵌的异常得到。id属性和内嵌异常是包装问题 的两种途径。
异常处理流程的设计
一旦你已经设计好异常类本身了,下一步需要思考的就是它在应用程序中的处理流程。一个标准的JEE应用程序体系通常包括四个部分:展现、业务、集成、持 久。异常经常在集成和持久部分被抛出。在业务部分,里层的捕获checked异常,而外层捕获runtime异常并根据它们的类型来采取相应的处理措施。 也可以在业务部分抛出一些checked异常并且捕获它们。在这种模式下,集成和持久部分,包括业务部分的里层都将runtime异常转化成具体的处理措 施。图2展示的就是一个典型的JEE应用程序异常处理流程。
图2.标准JEE包体系中异常的处理流程
异常抛出路径是指从持久部分(假设)发生问题到问题被解决所经历的流程。如果持久层的调用方法能够解决这个问题,那么这个异常就直接被捕获并采 取相应的处理措施,业务流程一切照常;如果问题不能被解决,异常将内嵌到一个runtime异常中经过业务部分的中间层传递到应用程序的上层中,在这里, 典型的处理方法就是使用一些应用程序控制器来捕获这些runtime异常并采取相应的处理措施,展现层显示相应的错误信息给用户。直接捕获checked 异常和推迟捕获runtime异常是异常处理设计中的两种主要方案,如图3所示。
图3.直接捕获checked异常和推迟捕获runtime异常
扩展java.lang.Exception
文中提到的异常处理设计方案在任何的面向对象语言中都可以很容易的实现,包括Java。一个相似的异常类树已经在标准Java库中提供了。在这个库中异常 被设计为java.lang.Throwable,ckeched异常被设计为java.lang.Exception,runtime异常被设计为 java.lang.RuntimeException。
在java.lang.Exception下,有大量泛语义的业务异常。运行时应用程序异常,如ParamterException、 TechnicalException、CriticalTechnicalException(见图1)各自都设计成相应的概要异常,如 IllegalArgumentException、MissingResourceException、IllegalStateException。
在应用程序中,重用Java标准异常是一个不错的主意,但是由Java标准类抛出的异常也会导致一些混乱。你可以通过扩展 java.lang.Exception自定义异常类树来避免这样的混乱。通过自定义的异常类树,你还可以实现内嵌异常和问题ID。列表1给出了文中例子 的Java代码实现。注意,它包括内嵌异常和问题ID。
列表1.通过Java代码实现内嵌异常和问题ID
- public class NestedException extends RuntimeException {
- protected Exception nestedException;
- protected int issueId;
- public NestedException(String msg, Exception e, int id) {
- super(msg);
- this.nestedException = e;
- this.issueId = id;
- }
- public Exception getNestedException() {
- return this.nestedException;
- }
- public int getIssue() {
- return this.issueId;
- }
- }
- public interface Issue {
- public final static int UNDEFINED = 0;
- public final static int EXTERNAL_SERVICE_1_DOWN = 1;
- public final static int EXTERNAL_SERVICE_2_DOWN = 2;
- public final static int SQL_STATEMENT_ERROR = 3;
- // ...
- }
总结
设计一个满足好的错误处理系统需求的异常类树非常简单。简单的秘诀就是将设计的主要精力集中在系统应该采取什么样的处理措施,而不是关注会出现的什么样的 问题。在本文的设计当中,问题的信息封装在异常类里面。通过在处理措施和问题之间分配异常语义,让你将异常类树限制在一个有限的异常类集合中(可能就六七 个左右)。这种设计不仅限制了异常类激增,保证代码的可读性,使你在以后的开发中以最佳的清晰度来关注应用程序的业务逻辑的编码。
作者简介
Jean-Pierre Norguet拥有布鲁塞尔大学的计算机科学和网络工程博士学位。在IBM经过了三年全职的电子商务应用程序关键任务的Java开发后,作为团队领导者和 教练,他擅长的技术领域包括了整个应用程序开发周期。目前专注于Java技术、实体集成和迷你Web应用的研究。除了一些在线Java文章外, Norguet博士还与Prentice、IBM出版社一起出版了有关JEE的著作,同时还在ACM、IEEE和Springer-Verlag的国际研 讨会发表了一些文章。他的业务兴趣还包括艺术绘画、兼职法语教师和临时健康顾问。
发表评论
-
Spring Milestone Maven Repository地址
2009-05-11 10:52 7868使用maven又想试用spring 3.0 m3的朋友可以用s ... -
HiddenHttpMethodFilter:自动转换Http Method
2009-03-29 11:21 5494REST的核心之一就是提供统一接口,也就是说对所有的资源(UR ... -
ActiveMQ5.0实战三:使用Spring发送,消费topic和queue消息
2008-08-28 18:21 33120ActiveMQ5.0实战一: 安装配 ... -
The smallwig theory of optimization
2008-04-17 09:49 1379There are three kinds of optimi ... -
ElementType.LOCAL_VARIABLE目前基本没用
2008-04-07 18:30 3904jdk5.0引入Annotation语法,@Target中的E ... -
Memcached java client 2.01发布
2008-04-05 21:39 2381com.danga.MemCached 发布2.0.1包括许多 ... -
Struts2中使用Stream Result Type
2008-04-05 18:25 18105Stream result type是Struts2中比较有用 ... -
NotSerializableException: EnhancerByCGLIB
2008-04-03 12:23 4292使用Ibatis时,为了获得更好的性能,我们一般都会将enha ... -
Pointcut命名有可能导致错误
2008-02-28 19:16 4315使用Spring @AspectJ方式的AOP,代码@Aspe ... -
异常通知:面向方面的模型
2008-02-28 15:16 2174原文:http://dev2dev.bea.com ... -
Sping容器加载xsd文件时的问题
2008-01-31 17:56 6372今天遇到一个非常奇怪的spring容器问题,先看日志]-303 ... -
关于memcached client的选择
2008-01-10 15:29 13542Memcached(http://www.danga.com/ ... -
Java确实不适合于作为主要编程教学语言
2008-01-10 12:12 1648最近米国那边又在讨论这个话题, 孟岩也发了一篇帖子http:/ ... -
Spring 2.5Annotation使用基本类型和${}
2008-01-08 19:08 2746最近使用了Spring2.5 annotation风格的DI, ... -
ActiveMQ5.0实战二: 基本配置
2008-01-08 17:33 12453/** *作者:andyao,email:andyaoy@gm ... -
JMS消息类型模型
2008-01-04 18:12 9544/**作者:andyao,email:andyaoy@gmai ... -
ActiveMQ5.0实战一: 安装配置ActiveMQ5.0
2008-01-05 18:03 10093/** *作者:andyao,email:andyaoy@gm ... -
Spring Annotation和XML风格的声明式事务
2008-01-04 14:02 5604/***作者:andyao,email:andyaoy@gma ... -
国际化异常消息
2007-12-21 14:26 3864/**作者:andyao,email:andyaoy@gmai ... -
有效的Java异常
2007-12-17 15:51 1531原文出处:http://dev2dev.b ...
相关推荐
### Struts2框架中“No result defined for action and result input”错误解析及解决方法 #### 错误概述 在Struts2框架中开发Web应用程序时,可能会遇到一个名为“No result defined for action and result input...
Exception handling and transaction management with Mule Chapter 10. Securing Mule Chapter 11. Tuning Mule Part 3: Traveling further with Mule Chapter 12. Developing with Mule Chapter 13. Writing ...
// getter and setter for uploadFile } ``` 接下来,我们讨论下载部分。在Struts2中,我们可以创建一个Action方法返回一个`InputStream`,Struts2会自动将其包装成HTTP响应,并设置合适的Content-Type和Content-...
public String execute() throws Exception { Map, Object> map = new HashMap(); map.put("key", "value"); map.put("number", 123); // ... 添加其他数据 return Action.SUCCESS; } @Result(name = ...
Kagi Chart Type (Enterprise Edition only) - Kagi charts display a series of connecting vertical lines where the thickness and direction of the lines are dependent on the price action. These charts ...
#### 一、异常 javax.servlet.jsp.JspException: Cannot retrieve mapping for action /Login **异常描述**: 该异常通常出现在尝试访问一个未在`struts-config.xml`文件中正确配置的Action时。具体表现为无法获取...
The exception that is thrown when an action that requires ownership is attempted by a principal that is not an owner of the object for which ownership is required.
EXCEPTION WHEN OTHERS THEN -- 处理未捕获的异常 DBMS_OUTPUT.PUT_LINE('An error occurred: ' || SQLERRM); END; ``` ### 函数与过程 - **函数**:返回一个值的子程序。 - **过程**:不返回值但可以执行一...
6)....Fixed: Exception filters ignore settings for restart/terminate EurekaLog 7.3 Hotfix 2 (7.3.2.0), 20-October-2015 1)....Fixed: Added workaround for codegen bug in Delphi 7 (possibly - other), ...
getter and setter for 'author' public String execute() throws Exception { return "done"; } public String login() throws Exception { ServletActionContext.getRequest().setAttribute("author", ...
for (int i = 0; i ; i++) { s1 = str[0]; } if (" ".equals(s1) || null == s1) { depart.setRoute("暂无路线"); } else { depart.setRoute(s1); } epVO.setDepart(depart); // dept对象 Dept dept = ...
### SSH批量处理Action层知识点详解 #### 一、概述 SSH框架是指Spring、Struts2与Hibernate三个开源框架的组合,常被用于Java Web应用程序的开发。本篇将重点介绍如何利用SSH框架实现批量处理的功能,特别是批量...
1. 异常 javax.servlet.jsp.JspException: Cannot retrieve mapping for action /Login 这个错误表明在struts-config.xml中没有为/L Login定义Action Mapping。确保在配置文件中正确地声明了Action,如: ```xml ...
3. **自定义拦截器处理异常(Custom Interceptor for Exception Handling)** Struts2的拦截器机制允许开发者创建自定义拦截器来处理异常。拦截器可以捕获并处理Action执行过程中的异常,或者记录日志,甚至将用户...
Praise for the Third Edition of Spring in Action Preface Acknowledgments About this Book 1. Core Spring Chapter 1. Springing into action 1.1. Simplifying Java development 1.1.1. Unleashing the power ...
### 使用 Easy Struts for Eclipse 开发 Struts #### 一、Easy Struts 插件简介与安装配置 **Easy Struts** 是一个针对 Eclipse 的插件,它极大地简化了使用 **Struts** 框架进行 Web 开发的过程。通过 Easy ...
In try block we write those code which can throw exception while code execution and when the exception is thrown it is caught inside the catch block. Multiple try catch We can have more than one try/...
for (Locale temp : ls) { System.out.println(temp.getDisplayCountry() + "\t" + temp.getCountry() + "\t" + temp.getDisplayName()); } ``` #### 六、数据校验与类型转换 - **数据校验**:Struts2提供了...
#### 一、`Servlet.service() for servlet jsp threw exception` 在Struts框架的开发过程中,我们经常会遇到一些常见的异常情况,这些异常不仅会打断我们的工作流程,还会影响到应用程序的正常运行。本文将针对`...
for (ParcelUuid parcelUuid : uuids) { if (parcelUuid.equals(MY_UUID_IN_HEX)) { // 使用预定义的服务UUID Method createRfcommSocket = device.getClass().getMethod("createRfcommSocketToServiceRecord", ...