3.设计一个新的异常类
在设计一个新的异常类时,首先看看是否真正的需要这个异常类。一般情况下尽量不要去设计新的异常类,而是尽量使用java中已经存在的异常类。
如java 代码IllegalArgumentException, UnsupportedOperationException
不管是新的异常是chekced异常还是unChecked异常。我们都必须考虑异常的嵌套问题。
java 代码
public void methodA()throws ExceptionA{
…..
throw new ExceptionA();
}
方法methodA声明会抛出ExceptionA.
public void methodB() throws ExceptionB
methodB声明会抛出ExceptionB,当在methodB方法中调用methodA时,如何将ExceptionA继续往上抛出。
一个办法是把methodB声明会抛出ExceptionA, 但这样已经改变了MethodB的方法签名。一旦改变,则所有调用methodB的方法都要进行改变。
另一个办法是把ExceptionA封装成ExceptionB,然后再抛出。如果我们不把ExceptionA封装在ExceptionB中,就丢失了根异常信息,使得无法跟踪异常的原始出处。
java 代码
public void methodB()throws ExceptionB{
try{
methodA();
……
}catch(ExceptionA ex){
throw new ExceptionB(ex);
}
}
如上面的代码中,ExceptionB嵌套一个ExceptionA.我们暂且把ExceptionA称为“起因异常”,因为ExceptionA导致了ExceptionB的产生。这样才不使异常信息丢失。
所以我们在定义一个新的异常类时,必须提供这样一个可以包含嵌套异常的构造函数。并有一个私有成员来保存这个“起因异常”。
java 代码
public Class ExceptionB extends Exception{
private Throwable cause;
public ExceptionB(String msg, Throwable ex){
super(msg);
this.cause = ex;
}
public ExceptionB(String msg){
super(msg);
}
public ExceptionB(Throwable ex){
this.cause = ex;
}
}
当然,我们在调用printStackTrace方法时,需要把所有的“起因异常”的信息也同时打印出来。所以我们需要覆写printStackTrace方法来显示全部的异常栈跟踪。包括嵌套异常的栈跟踪。
java 代码
public void printStackTrace(PrintStrean ps){
if(cause == null){
super.printStackTrace(ps);
}else{
ps.println(this);
cause.printStackTrace(ps);
}
}
一个完整的支持嵌套的checked异常类源码如下。我们在这里暂且把它叫做NestedException
java 代码
public NestedException extends Exception{
private Throwable cause;
public NestedException (String msg){
super(msg);
}
public NestedException(String msg, Throwable ex){
super(msg);
This.cause = ex;
}
public Throwable getCause(){
return (this.cause == null ? this :this.cause);
}
public getMessage(){
String message = super.getMessage();
Throwable cause = getCause();
if(cause != null){
message = message + “;nested Exception is ” + cause;
}
return message;
}
public void printStackTrace(PrintStream ps){
if(getCause == null){
super.printStackTrace(ps);
}else{
ps.println(this);
getCause().printStackTrace(ps);
}
}
public void printStackTrace(PrintWrite pw){
if(getCause() == null){
super.printStackTrace(pw);
}
else{
pw.println(this);
getCause().printStackTrace(pw);
}
}
public void printStackTrace(){
printStackTrace(System.error);
}
}
同样要设计一个unChecked异常类也与上面一样。只是需要继承RuntimeException。
4. 如何记录异常
作为一个大型的应用系统都需要用日志文件来记录系统的运行,以便于跟踪和记录系统的运行情况。系统发生的异常理所当然的需要记录在日志系统中。
java 代码
public String getPassword(String userId)throws NoSuchUserException{
UserInfo user = userDao.queryUserById(userId);
If(user == null){
Logger.info(“找不到该用户信息,userId=”+userId);
throw new NoSuchUserException(“找不到该用户信息,userId=”+userId);
}
else{
return user.getPassword();
}
}
public void sendUserPassword(String userId) throws Exception {
UserInfo user = null;
try{
user = getPassword(userId);
//……..
sendMail();
//
}catch(NoSuchUserException ex)(
logger.error(“找不到该用户信息:”+userId+ex);
throw new Exception(ex);
}
我们注意到,一个错误被记录了两次.在错误的起源位置我们仅是以info级别进行记录。而在sendUserPassword方法中,我们还把整个异常信息都记录了。
笔者曾看到很多项目是这样记录异常的,不管三七二一,只有遇到异常就把整个异常全部记录下。如果一个异常被不断的封装抛出多次,那么就被记录了多次。那么异常倒底该在什么地方被记录?
异常应该在最初产生的位置记录!
如果必须捕获一个无法正确处理的异常,仅仅是把它封装成另外一种异常往上抛出。不必再次把已经被记录过的异常再次记录。
如果捕获到一个异常,但是这个异常是可以处理的。则无需要记录异常
java 代码
public Date getDate(String str){
Date applyDate = null;
SimpleDateFormat format = new SimpleDateFormat(“MM/dd/yyyy”);
try{
applyDate = format.parse(applyDateStr);
}
catch(ParseException ex){
//乎略,当格式错误时,返回null
}
return applyDate;
}
捕获到一个未记录过的异常或外部系统异常时,应该记录异常的详细信息
java 代码
try{
……
String sql=”select * from userinfo”;
Statement s = con.createStatement();
……
Catch(SQLException sqlEx){
Logger.error(“sql执行错误”+sql+sqlEx);
}
究竟在哪里记录异常信息,及怎么记录异常信息,可能是见仁见智的问题了。甚至有些系统让异常类一记录异常。当产生一个新异常对象时,异常信息就被自动记录。
java 代码
public class BusinessException extends Exception {
private void logTrace() {
StringBuffer buffer=new StringBuffer();
buffer.append("Business Error in Class: ");
buffer.append(getClassName());
buffer.append(",method: ");
buffer.append(getMethodName());
buffer.append(",messsage: ");
buffer.append(this.getMessage());
logger.error(buffer.toString());
}
public BusinessException(String s) {
super(s);
Trace();
}
这似乎看起来是十分美妙的,其实必然导致了异常被重复记录。同时违反了“类的职责分配原则”,是一种不好的设计。记录异常不属于异常类的行为,记录异常应该由专门的日志系统去做。并且异常的记录信息是不断变化的。我们在记录异常时应该给出更丰富些的信息。以利于我们能够根据异常信息找到问题的根源,以解决问题。
虽然我们对记录异常讨论了很多,过多的强调这些反而使开发人员更为疑惑,一种好的方式是为系统提供一个异常处理框架。由框架来决定是否记录异常和怎么记录异常。而不是由普通程序员去决定。但是了解些还是有益的。
分享到:
相关推荐
在J2EE项目开发中,异常处理是一项至关重要的任务,它确保了系统的稳定性和用户体验。一个良好的异常处理机制能够提供详细的错误信息,帮助开发者快速定位问题,并且可以在生产环境中优雅地处理异常,防止用户看到...
J2EE 体系结构图或三层结构图 J2EE 体系结构图是 Java 企业版(Java Enterprise Edition)的架构设计图,它描述了 J2EE 应用程序的逻辑结构和物理结构。J2EE 体系结构图可以分为三层结构图,即Presentation Layer、...
综上所述,J2EE项目中的异常处理策略应包括多层面的设计与实施,从代码层面的异常捕获,到框架层面的拦截器和全局异常配置,再到异常层次结构的构建以及日志记录与监控的完善,每一步都是提升系统稳定性与可维护性的...
N层架构中最常见的层次包括表示层、业务逻辑层、数据访问层等,但具体层次的数量和命名可以根据项目需求进行调整。 ### 二、J2EE N层架构详解 #### 1. 表示层(Presentation Layer) 表示层是用户与系统的接口,...
典型的J2EE三层结构,分为表现层、中间层(业务逻辑层)和数据服务层。三层体系将业务规则、数据访问及合法性校验等工作放在中间层处理。客户端不直接与数据库交互,而是通过组件与中间层建立连接,再由中间层与...
### J2EE 三层结构详解 #### 一、引言 在现代软件开发领域,Java 2 Platform, Enterprise Edition(J2EE)以其强大的企业级应用支持能力而闻名。本书旨在帮助读者深入理解J2EE的三层架构模型,并通过具体的案例来...
在本项目中,你可能会看到这些层次的实现,例如使用Servlet和JSP进行表现层开发,EJB(Enterprise JavaBeans)处理业务逻辑,以及JDBC(Java Database Connectivity)进行数据访问。 2. **Servlet与JSP**:Servlet...
在J2EE项目中,Servlet常用于接收客户端请求,处理业务逻辑,并将结果返回给用户。 2. **JSP(JavaServer Pages)**:JSP是一种动态网页技术,允许开发者在HTML页面中嵌入Java代码。它简化了视图层的开发,使页面...
经典J2EE项目案例 从给定的文件信息中,我们可以提取出以下知识点: 1. 项目开发环境和工具 * 项目开发环境:Tomcat6.0、IE10、Firefox8.0、JDK1.7、Windows 7 * 项目开发工具:MyEclipse9.0、Mysql、JUnit 2. ...
1. **Java基础知识**:首先,理解J2EE项目需要扎实的Java语言基础,包括面向对象编程、异常处理、集合框架等。 2. **Servlet**:Servlet是Java中用于处理HTTP请求的核心组件,它们在服务器端运行,接收并响应来自...
在J2EE项目开发中,理解并掌握J2EE架构及其相关技术是非常关键的。J2EE应用程序通常由四层结构组成,分别是客户层、应用层、表示逻辑层和企业信息系统层。客户层主要负责与用户的交互,应用层处理业务逻辑,表示逻辑...
总的来说,"J2EE项目实例源码"提供了一个实践性的学习案例,涵盖了J2EE应用开发中的数据库设计、连接、业务逻辑处理以及视图展现等多个关键环节。通过研究这个项目,开发者可以深化对J2EE平台的理解,提升实际项目...
总的来说,这个压缩包提供了J2EE开发所需的基础设施,涵盖了持久层、业务逻辑层和表示层的解决方案,对于快速启动J2EE项目非常有帮助。通过合理使用这些框架,开发者可以更专注于业务逻辑的实现,而无需过多关注底层...
EJB分为三种类型:Session Beans(会话Bean)处理客户端交互,Entity Beans(实体Bean)管理持久性数据,Message-Driven Beans(消息驱动Bean)用于监听和处理消息队列中的消息。 3. **JNDI(Java Naming and ...
这份文档可能包含了模板的具体结构、使用方法、优势以及实际项目中的应用示例,对于深入理解和应用J2EE项目开发模板非常有帮助。 总的来说,J2EE项目开发模板是企业级Java开发的基石,它规范了开发流程,提升了开发...
在J2EE开发中,MVC(Model-View-Controller)三层架构是一种广泛采用的设计模式,它有助于分离业务逻辑、用户界面和数据访问,从而提高代码的可维护性和可扩展性。本文主要针对初学者,讲解了如何在J2EE环境中实现...
通过深入研究提供的J2EE项目案例源代码,初学者不仅可以学习到如何在实际项目中应用这些技术,还能了解如何组织代码结构,遵循设计模式,以及如何有效地利用J2EE提供的服务。这将有助于他们快速提升在企业级Java开发...
在J2EE应用程序中,异常处理是一个至关重要的方面,它涉及到代码的可读性、可维护性和业务逻辑的正常执行。异常处理框架的目标是简化这一过程,让开发人员能够更专注于核心业务逻辑,而非繁琐的异常处理代码。本文将...
### 浅析J2EE的三层结构优点 #### 一、引言 随着信息技术的不断发展,企业级应用程序的需求日益增长,而Java Enterprise Edition (J2EE)作为一种成熟的企业级开发平台,凭借其强大的功能和灵活性,在众多开发框架...