`
sunxboy
  • 浏览: 2880084 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

J2EE项目异常处理 上(转)

阅读更多

【IT168 专稿】为什么要在J2EE项目中谈异常处理呢?可能许多Java初学者都想说:“异常处理不就是try….catch…finally吗?这谁都会啊!”。笔者在初学Java时也是这样认为的。如何在一个多层的J2EE项目中定义相应的异常类?在项目中的每一层如何进行异常处理?异常何时被抛出?异常何时被记录?异常该怎么记录?何时需要把checked Exception转化成unchecked Exception ,何时需要把unChecked Exception转化成checked Exception?异常是否应该呈现到前端页面?如何设计一个异常框架?本文将就这些问题进行探讨。

    1. JAVA异常处理
    在面向过程式的编程语言中,我们可以通过返回值来确定方法是否正常执行。比如在一个C语言编写的程序中,如果方法正确的执行则返回1.错误则返回0。在VB或Delphi开发的应用程序中,出现错误时,我们就弹出一个消息框给用户。
通过方法的返回值我们并不能获得错误的详细信息。可能因为方法由不同的程序员编写,当同一类错误在不同的方法出现时,返回的结果和错误信息并不一致。
    所以Java语言采取了一个统一的异常处理机制。
    什么是异常?运行时发生的可被捕获和处理的错误。
    在Java语言中,Exception是所有异常的父类。任何异常都扩展于Exception类。Exception就相当于一个错误类型。如果要定义一个新的错误类型就扩展一个新的Exception子类。采用异常的好处还在于可以精确的定位到导致程序出错的源代码位置,并获得详细的错误信息。

    Java异常处理通过五个关键字来实现,try,catch,throw ,throws, finally。具体的异常处理结构由try….catch….finally块来实现。try块存放可能出现异常的Java语句,catch用来捕获发生的异常,并对异常进行处理。Finally块用来清除程序中未释放的资源。不管理try块的代码如何返回,finally块都总是被执行。
  
    一个典型的异常处理代码

public String getPassword(String userId)throws DataAccessException...{
String sql = “select password from userinfo where userid=’”+userId +”’”;
String password = null;
Connection con = null;
Statement s = null;
ResultSet rs = null;
try...{
con = getConnection();//获得数据连接
s = con.createStatement();
rs = s.executeQuery(sql);
while(rs.next())...{
password = rs.getString(1);
}
rs.close();
s.close();

}
Catch(SqlException ex)...{
throw new DataAccessException(ex);
}
finally...{
try...{
if(con != null)...{
con.close();
}
}
Catch(SQLException sqlEx)...{
throw new DataAccessException(“关闭连接失败!”,sqlEx);
}
}
return password;
}
    可以看出Java的异常处理机制具有的优势:
    给错误进行了统一的分类,通过扩展Exception类或其子类来实现。从而避免了相同的错误可能在不同的方法中具有不同的错误信息。在不同的方法中出现相同的错误时,只需要throw 相同的异常对象即可。
    获得更为详细的错误信息。通过异常类,可以给异常更为详细,对用户更为有用的错误信息。以便于用户进行跟踪和调试程序。
    把正确的返回结果与错误信息分离。降低了程序的复杂度。调用者无需要对返回结果进行更多的了解。
强制调用者进行异常处理,提高程序的质量。当一个方法声明需要抛出一个异常时,那么调用者必须使用try….catch块对异常进行处理。当然调用者也可以让异常继续往上一层抛出。

 

2. Checked 异常 还是 unChecked 异常?
    Java异常分为两大类:checked 异常和unChecked 异常。所有继承Java.lang.Exception 的异常都属于checked异常。所有继承Java.lang.RuntimeException的异常都属于unChecked异常。
    当一个方法去调用一个可能抛出checked异常的方法,必须通过try…catch块对异常进行捕获进行处理或者重新抛出。
    我们看看Connection接口的createStatement()方法的声明。
     public Statement createStatement() throws SQLException;

     SQLException是checked异常。当调用createStatement方法时,Java强制调用者必须对SQLException进行捕获处理。

public String getPassword(String userId)...{
try...{
……
Statement s = con.createStatement();
……
Catch(SQLException sqlEx)...{
……
}
……
}
    或者

public String getPassword(String userId)throws SQLException...{
Statement s = con.createStatement();
}
    (当然,像Connection,Satement这些资源是需要及时关闭的,这里仅是为了说明checked 异常必须强制调用者进行捕获或继续抛出)

    unChecked异常也称为运行时异常,通常RuntimeException都表示用户无法恢复的异常,如无法获得数据库连接,不能打开文件等。虽然用户也可以像处理checked异常一样捕获unChecked异常。但是如果调用者并没有去捕获unChecked异常时,编译器并不会强制你那么做。

    比如一个把字符转换为整型数值的代码如下:


String str = “123”;
int value = Integer.parseInt(str);
    parseInt的方法签名为:
    public static int parseInt(String s) throws NumberFormatException

    当传入的参数不能转换成相应的整数时,将会抛出NumberFormatException。因为NumberFormatException扩展于 RuntimeException,是unChecked异常。所以调用parseInt方法时无需要try…catch

    因为Java不强制调用者对unChecked异常进行捕获或往上抛出。所以程序员总是喜欢抛出unChecked异常。或者当需要一个新的异常类时,总是习惯的从RuntimeException扩展。当你去调用它些方法时,如果没有相应的catch块,编译器也总是让你通过,同时你也根本无需要去了解这个方法倒底会抛出什么异常。看起来这似乎倒是一个很好的办法,但是这样做却是远离了Java异常处理的真实意图。并且对调用你这个类的程序员带来误导,因为调用者根本不知道需要在什么情况下处理异常。而checked异常可以明确的告诉调用者,调用这个类需要处理什么异常。如果调用者不去处理,编译器都会提示并且是无法编译通过的。当然怎么处理是由调用者自己去决定的。

所以Java推荐人们在应用代码中应该使用checked异常。就像我们在上节提到运用异常的好外在于可以强制调用者必须对将会产生的异常进行处理。包括在《Java Tutorial》等Java官方文档中都把checked异常作为标准用法。

 

使用checked异常,应意味着有许多的try…catch在你的代码中。当在编写和处理越来越多的try…catch块之后,许多人终于开始怀疑checked异常倒底是否应该作为标准用法了。

    甚至连大名鼎鼎的《thinking in Java》的作者Bruce Eckel也改变了他曾经的想法。Bruce Eckel甚至主张把unChecked异常作为标准用法。并发表文章,以试验checked异常是否应该从Java中去掉。Bruce Eckel语:“当少量代码时,checked异常无疑是十分优雅的构思,并有助于避免了许多潜在的错误。但是经验表明,对大量代码来说结果正好相反”
关于checked异常和unChecked异常的详细讨论可以参考
    Alan Griffiths http://www.octopull.demon.co.uk/Java/ExceptionalJava.html
    Bruce Eckel http://www.mindView.net/Etc/Disscussions/CheckedExceptions
   《Java Tutorial》 http://Java.sun.com/docs/books/tutorial/essential/exceptions/runtime.html

    使用checked异常会带来许多的问题。
    checked异常导致了太多的try…catch 代码
    可能有很多checked异常对开发人员来说是无法合理地进行处理的,比如SQLException。而开发人员却不得不去进行try…catch。当开发人员对一个checked异常无法正确的处理时,通常是简单的把异常打印出来或者是干脆什么也不干。特别是对于新手来说,过多的checked异常让他感到无所适从。

try...{
……
Statement s = con.createStatement();
……
Catch(SQLException sqlEx)...{
sqlEx.PrintStackTrace();
}
或者
try...{
……
Statement s = con.createStatement();
……
Catch(SQLException sqlEx)...{
//什么也不干
}

    checked异常导致了许多难以理解的代码产生
    当开发人员必须去捕获一个自己无法正确处理的checked异常,通常的是重新封装成一个新的异常后再抛出。这样做并没有为程序带来任何好处。反而使代码晚难以理解。
就像我们使用JDBC代码那样,需要处理非常多的try…catch.,真正有用的代码被包含在try…catch之内。使得理解这个方法变理困难起来
    checked异常导致异常被不断的封装成另一个类异常后再抛出

public void methodA()throws ExceptionA...{
…..
throw new ExceptionA();
}

public void methodB()throws ExceptionB...{
try...{
methodA();
……
}catch(ExceptionA ex)...{
throw new ExceptionB(ex);
}
}

Public void methodC()throws ExceptinC...{
try...{
methodB();

}
catch(ExceptionB ex)...{
throw new ExceptionC(ex);
}
}     我们看到异常就这样一层层无休止的被封装和重新抛出。

    checked异常导致破坏接口方法
    一个接口上的一个方法已被多个类使用,当为这个方法额外添加一个checked异常时,那么所有调用此方法的代码都需要修改。

    可见上面这些问题都是因为调用者无法正确的处理checked异常时而被迫去捕获和处理,被迫封装后再重新抛出。这样十分不方便,并不能带来任何好处。在这种情况下通常使用unChecked异常。

chekced异常并不是无一是处,checked异常比传统编程的错误返回值要好用得多。通过编译器来确保正确的处理异常比通过返回值判断要好得多。
    如果一个异常是致命的,不可恢复的。或者调用者去捕获它没有任何益处,使用unChecked异常。
    如果一个异常是可以恢复的,可以被调用者正确处理的,使用checked异常。
    在使用unChecked异常时,必须在在方法声明中详细的说明该方法可能会抛出的unChekced异常。由调用者自己去决定是否捕获unChecked异常

倒底什么时候使用checked异常,什么时候使用unChecked异常?并没有一个绝对的标准。但是笔者可以给出一些建议
当所有调用者必须处理这个异常,可以让调用者进行重试操作;或者该异常相当于该方法的第二个返回值。使用checked异常。
这个异常仅是少数比较高级的调用者才能处理,一般的调用者不能正确的处理。使用unchecked异常。有能力处理的调用者可以进行高级处理,一般调用者干脆就不处理。
    这个异常是一个非常严重的错误,如数据库连接错误,文件无法打开等。或者这些异常是与外部环境相关的。不是重试可以解决的。使用unchecked异常。因为这种异常一旦出现,调用者根本无法处理。
    如果不能确定时,使用unchecked异常。并详细描述可能会抛出的异常,以让调用者决定是否进行处理。

 

 

分享到:
评论

相关推荐

    J2EE项目异常处理的几种方案

    ### J2EE项目异常处理的几种方案:深入探讨与实践 在J2EE项目中,异常处理是一项至关重要的任务,它直接关系到系统的稳定性和用户体验。本文将详细解析几种常用的异常处理方案,尤其是针对Struts2框架下的异常管理...

    J2EE项目中统一异常处理源码

    综上所述,"J2EE项目中统一异常处理源码"通过自定义异常分析和统一处理策略,实现了对14类异常的精细化管理,提升了项目的健壮性和用户体验。`ExceptionHandler.java`作为核心处理类,包含了捕获、分析和响应异常的...

    简单的j2ee项目

    1. **Java基础知识**:首先,理解J2EE项目需要扎实的Java语言基础,包括面向对象编程、异常处理、集合框架等。 2. **Servlet**:Servlet是Java中用于处理HTTP请求的核心组件,它们在服务器端运行,接收并响应来自...

    J2EE项目源码(企业内部源码)

    《J2EE项目源码(企业内部源码)》提供了深入了解J2EE应用程序开发的宝贵机会,特别是对于那些想要深入研究Spring、Struts、Hibernate和JSP等核心技术的开发者而言。这个源码集合是一个实际项目的代码实现,可以作为...

    J2EE项目开发Excel导出

    - 异常处理:确保代码包含适当的错误处理,以应对数据问题或文件操作失败。 - 版本兼容性:确保使用的Apache POI版本与目标Excel文件格式兼容。 综上所述,J2EE项目开发中的Excel导出涉及到Java编程、Apache POI...

    J2EE项目实训——Struts框架技术.rar

    7. **异常处理**:Struts框架提供了全局的异常处理机制,可以定义一个或多个错误页面,用于捕获并处理应用程序中抛出的异常。 8. **拦截器(Interceptor)**:拦截器是Struts2引入的重要特性,它们是实现了特定接口...

    J2EE专业项目实例开发(2)

    本书是学习J2EE编程的优秀参考书,主要包括以下内容:第一部分概述了有关J2EE编程的重要概念,如applet的创建、布局管理器和事件处理、异常处理和线程、存储数据和创建网络应用程序、RMI和CORBA;第二部分介绍J2EE的...

    软件测试技术在J2EE项目中的应用

    在J2EE项目中,可以使用JUnit进行Java类的单元测试,它提供了断言、测试套件和异常处理等功能,便于开发者编写和运行测试用例。 2. **集成测试**:当单个组件通过单元测试后,需要验证它们之间的交互。JUnit和...

    《J2EE图书馆项目实例开发》源代码

    8. **异常处理**:良好的异常处理机制是任何项目的关键,本项目可能使用try-catch-finally结构和自定义异常来捕获和处理可能出现的问题。 9. **国际化与本地化**:大型项目通常需要支持多种语言,因此项目可能包含...

    J2EE项目开发的平台、环境搭建、集成及工程的建立

    ### J2EE项目开发平台与环境搭建详解 #### 一、引言 J2EE(Java 2 Platform, Enterprise Edition)是Sun Microsystems公司提出的一种基于Java的大型企业级应用程序开发框架,它支持多层分布式应用,能够处理大量...

    J2EE项目代码编写规范.zip

    5. **异常处理**:在J2EE项目中,异常处理是关键部分。应定义统一的异常类,用于封装业务异常,并在可能抛出异常的地方进行捕获和处理,防止程序中断。 6. **事务管理**:在JPA或Hibernate等持久层框架中,事务管理...

    J2EE项目开发Excel导入导出操作组件源代码

    - **异常处理**:处理可能出现的文件读写异常,确保程序的健壮性。 - **配置和接口**:提供配置参数,如文件路径、列映射等,并定义对外的接口,使得其他模块可以方便地调用导入导出功能。 5. **说明文档**: ...

    J2EE项目代码编写规范

    《J2EE项目代码编写规范详解》 代码编写规范是软件开发中不可或缺的一部分,它旨在提升代码质量,增强代码可读性,降低维护成本,并帮助开发者形成良好的编程习惯。对于J2EE项目而言,规范化的代码编写尤为重要,...

    J2EE项目案例源代码(强力推荐:运行稳定)

    这通常涉及到良好的异常处理、资源管理以及负载均衡策略。通过分析这些源代码,我们可以学习如何在实际开发中实现这些目标。 界面的精美则体现了用户体验设计的重要性。在J2EE项目中,通常结合HTML、CSS和...

    两个J2EE项目示例

    它们不仅展示了J2EE应用的基本架构,还可能涵盖了各种API的使用、异常处理、日志记录等方面,对于提升初学者的实战能力非常有帮助。在深入学习的过程中,不断实践和调试,将有助于初学者逐步成长为熟练的J2EE开发者...

    j2ee经典项目各技术经典处理

    这包括面向对象编程概念,如封装、继承和多态,以及异常处理、集合框架(如List、Set、Map)和IO流等核心内容。 2. **Servlet与JSP**:Servlet是J2EE服务器端编程的基础,用于接收和响应HTTP请求。JSP则是用于创建...

    为J2EE定制一个用来处理错误的异常处理框架

    回顾一下上一个J2EE工程,是否遇到过类似错误没有记 入日志或者被多次记录的情况?是否只是因为在某处代码吃 掉了异常导致你花费无数次时间...这篇文章为你提供了在J2EE项目中通过使用错误处理框架使用一些策略的基础。

    J2EE网上购物系统

    1. **Struts2**:Struts2是一个强大的MVC框架,通过拦截器机制处理HTTP请求,提供了一系列的拦截器来实现如认证、授权、异常处理等功能。它的Action类负责接收并处理请求,然后返回结果到视图。Struts2还支持多种...

    J2EE项目-在线求助系统

    此外,项目可能还涉及权限管理、异常处理、国际化、缓存等高级特性。通过这个项目,开发者可以掌握如何在实际环境中运用J2EE技术栈,为后续的企业级项目开发打下坚实基础。对于初学者来说,这是一个很好的实践平台,...

    J2EE项目开发Excel导入导出操作组件源代码(附带说明文档).rar

    这需要处理单元格类型转换、数据验证和异常处理。 4. **导出功能**: - 导出功能可能涉及从数据库获取数据并构造Excel文件。组件可能提供方法,根据指定的查询条件、数据格式和样式生成Excel文件,供用户下载。 5...

Global site tag (gtag.js) - Google Analytics