Heim  >  Artikel  >  Java  >  Zusammenfassung der Ausnahmebehandlung in Java EE-Projekten (ein Artikel, den man unbedingt lesen muss)

Zusammenfassung der Ausnahmebehandlung in Java EE-Projekten (ein Artikel, den man unbedingt lesen muss)

高洛峰
高洛峰Original
2017-01-17 11:17:201488Durchsuche

Warum sollten wir über Ausnahmebehandlung in J2EE-Projekten sprechen? Viele Java-Anfänger möchten vielleicht sagen: „Ist die Ausnahmebehandlung nicht einfach versuchen ... fangen ... endlich? Jeder weiß das!“. Das dachte der Autor, als ich Java zum ersten Mal lernte. Wie definiere ich die entsprechende Ausnahmeklasse in einem mehrschichtigen J2ee-Projekt? Wie gehe ich mit Ausnahmen auf jeder Ebene im Projekt um? Wann wird eine Ausnahme ausgelöst? Wann werden Ausnahmen protokolliert? Wie sollen Ausnahmen erfasst werden? Wann müssen Sie eine aktivierte Ausnahme in eine nicht aktivierte Ausnahme umwandeln und wann müssen Sie eine nicht aktivierte Ausnahme in eine aktivierte Ausnahme umwandeln? Sollten Ausnahmen auf der Front-End-Seite angezeigt werden? Wie entwerfe ich ein Ausnahme-Framework? In diesem Artikel werden diese Probleme erörtert.

1. JAVA-Ausnahmebehandlung

In prozeduralen Programmiersprachen können wir durch die Rückgabe eines Werts feststellen, ob eine Methode normal ausgeführt wird. Wenn beispielsweise in einem in der Sprache C geschriebenen Programm die Methode korrekt ausgeführt wird, wird 1 zurückgegeben. Wenn ein Fehler auftritt, wird 0 zurückgegeben. Wenn in Anwendungen, die in VB oder Delphi entwickelt wurden, ein Fehler auftritt, wird dem Benutzer ein Meldungsfeld angezeigt.

Wir können die Fehlerdetails nicht über den Rückgabewert der Methode abrufen. Da die Methoden möglicherweise von verschiedenen Programmierern geschrieben wurden, sind die zurückgegebenen Ergebnisse und Fehlermeldungen nicht konsistent, wenn derselbe Fehlertyp in verschiedenen Methoden auftritt.

Daher übernimmt die Java-Sprache einen einheitlichen Ausnahmebehandlungsmechanismus.

Was ist eine Ausnahme? Fehler, die zur Laufzeit auftreten und abgefangen und behandelt werden können.

In der Java-Sprache ist Exception die übergeordnete Klasse aller Ausnahmen. Jede Ausnahme erweitert die Exception-Klasse. Eine Ausnahme entspricht einem Fehlertyp. Wenn Sie einen neuen Fehlertyp definieren möchten, erweitern Sie eine neue Exception-Unterklasse. Der Vorteil der Verwendung von Ausnahmen besteht darin, dass Sie den Speicherort des Quellcodes, der den Programmfehler verursacht hat, genau lokalisieren und detaillierte Fehlerinformationen erhalten können.

Die Java-Ausnahmebehandlung wird durch fünf Schlüsselwörter implementiert: Try, Catch, Throw, Throws, schließlich. Die spezifische Ausnahmebehandlungsstruktur wird durch den Block try….catch….finally implementiert. Der Try-Block speichert Java-Anweisungen, die Ausnahmen verursachen können, und Catch wird zum Erfassen und Behandeln von Ausnahmen verwendet. Der Final-Block wird verwendet, um nicht freigegebene Ressourcen im Programm zu löschen. Unabhängig davon, wie der Code im Try-Block zurückkehrt, wird der Final-Block immer ausgeführt.

Ein typischer Ausnahmebehandlungscode

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;
}


Sie können die Vorteile des Ausnahmebehandlungsmechanismus von Java sehen:

Einheitliche Klassifizierung von Fehlern, erreicht durch Erweiterung der Exception-Klasse oder ihrer Unterklassen. Dadurch wird die Möglichkeit vermieden, dass derselbe Fehler bei unterschiedlichen Methoden unterschiedliche Fehlermeldungen haben kann. Wenn in verschiedenen Methoden derselbe Fehler auftritt, lösen Sie einfach dasselbe Ausnahmeobjekt aus.

Erhalten Sie detailliertere Fehlerinformationen. Durch Ausnahmeklassen können Ausnahmen detailliertere Fehlerinformationen bereitgestellt werden, die für Benutzer nützlicher sind. Um Benutzern das Verfolgen und Debuggen von Programmen zu erleichtern.

Trennen Sie das korrekte Rückgabeergebnis von der Fehlermeldung. Reduziert die Programmkomplexität. Der Anrufer muss nicht mehr über die zurückgegebenen Ergebnisse wissen.

Zwingen Sie den Aufrufer, Ausnahmen zu behandeln, um die Qualität des Programms zu verbessern. Wenn eine Methodendeklaration eine Ausnahme auslösen muss, muss der Aufrufer einen try...catch-Block verwenden, um die Ausnahme zu behandeln. Natürlich kann der Aufrufer die Ausnahme auch weiterhin auf die obere Ebene werfen lassen.

2. Geprüfte Ausnahme oder ungeprüfte Ausnahme?

Java-Ausnahmen sind in zwei Kategorien unterteilt: geprüfte Ausnahmen und nicht geprüfte Ausnahmen. Alle Ausnahmen, die java.lang.Exception erben, sind geprüfte Ausnahmen. Alle Ausnahmen, die java.lang.RuntimeException erben, sind ungeprüfte Ausnahmen.

Wenn eine Methode eine Methode aufruft, die möglicherweise eine geprüfte Ausnahme auslöst, muss die Ausnahme abgefangen und verarbeitet oder über einen try...catch-Block erneut ausgelöst werden.
Sehen wir uns die Deklaration der Methode createStatement() der Connection-Schnittstelle an.

public Statement createStatement() throws SQLException;
SQLException是checked异常。当调用createStatement方法时,java强制调用者必须对SQLException进行捕获处理。
public String getPassword(String userId){
try{
……
Statement s = con.createStatement();
……
Catch(SQLException sqlEx){
……
}
……
}

oder

public String getPassword(String userId)throws SQLException{
Statement s = con.createStatement();
}

(Natürlich müssen Ressourcen wie Connection und Satement rechtzeitig geschlossen werden. Dies dient nur zur Veranschaulichung, dass überprüfte Ausnahmen den Aufrufer dazu zwingen müssen, oder abzufangen continue to throw (Out)

unChecked-Ausnahme wird auch als Laufzeitausnahme bezeichnet. Normalerweise weist RuntimeException auf eine Ausnahme hin, die der Benutzer nicht beheben kann, z. B. weil er keine Datenbankverbindung herstellen oder eine Datenbank nicht öffnen kann Datei usw. Allerdings können Benutzer genauso wie geprüfte Ausnahmen auch ungeprüfte Ausnahmen abfangen. Wenn der Aufrufer die unChecked-Ausnahme jedoch nicht abfängt, werden Sie vom Compiler nicht dazu gezwungen.

Ein Code, der Zeichen in Ganzzahlwerte umwandelt, lautet beispielsweise wie folgt:

String str = “123”;
int value = Integer.parseInt(str);

Die Methodensignatur von parseInt lautet:

public staticint parseInt(String s)throws NumberFormatException

Wenn der Parameter übergeben wird und nicht in die entsprechende Ganzzahl konvertiert werden kann, wird eine NumberFormatException ausgelöst. Da NumberFormatException von RuntimeException ausgeht, handelt es sich um eine ungeprüfte Ausnahme. Es besteht also keine Notwendigkeit, beim Aufruf der parseInt-Methode…catch

zu versuchen

因为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异常的详细讨论可以参考

《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异常。并详细描述可能会抛出的异常,以让调用者决定是否进行处理。

3. 设计一个新的异常类

在设计一个新的异常类时,首先看看是否真正的需要这个异常类。一般情况下尽量不要去设计新的异常类,而是尽量使用java中已经存在的异常类。

IllegalArgumentException, UnsupportedOperationException


不管是新的异常是chekced异常还是unChecked异常。我们都必须考虑异常的嵌套问题。

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

方法methodA声明会抛出ExceptionA.

public void methodB()throws ExceptionB

methodB声明会抛出ExceptionB,当在methodB方法中调用methodA时,ExceptionA是无法处理的,所以ExceptionA应该继续往上抛出。一个办法是把methodB声明会抛出ExceptionA.但这样已经改变了MethodB的方法签名。一旦改变,则所有调用methodB的方法都要进行改变。

另一个办法是把ExceptionA封装成ExceptionB,然后再抛出。如果我们不把ExceptionA封装在ExceptionB中,就丢失了根异常信息,使得无法跟踪异常的原始出处。

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


如上面的代码中,ExceptionB嵌套一个ExceptionA.我们暂且把ExceptionA称为“起因异常”,因为ExceptionA导致了ExceptionB的产生。这样才不使异常信息丢失。

所以我们在定义一个新的异常类时,必须提供这样一个可以包含嵌套异常的构造函数。并有一个私有成员来保存这个“起因异常”。

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方法来显示全部的异常栈跟踪。包括嵌套异常的栈跟踪。

public void printStackTrace(PrintStrean ps){
if(cause == null){
super.printStackTrace(ps);
}else{
ps.println(this);
cause.printStackTrace(ps);
}
}

 一个完整的支持嵌套的checked异常类源码如下。我们在这里暂且把它叫做NestedException

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. 如何记录异常

作为一个大型的应用系统都需要用日志文件来记录系统的运行,以便于跟踪和记录系统的运行情况。系统发生的异常理所当然的需要记录在日志系统中。

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方法中,我们还把整个异常信息都记录了。

笔者曾看到很多项目是这样记录异常的,不管三七二一,只有遇到异常就把整个异常全部记录下。如果一个异常被不断的封装抛出多次,那么就被记录了多次。那么异常倒底该在什么地方被记录?

异常应该在最初产生的位置记录!

如果必须捕获一个无法正确处理的异常,仅仅是把它封装成另外一种异常往上抛出。不必再次把已经被记录过的异常再次记录。

如果捕获到一个异常,但是这个异常是可以处理的。则无需要记录异常

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;
}


捕获到一个未记录过的异常或外部系统异常时,应该记录异常的详细信息

try{
……
String sql=”select * from userinfo”;
Statement s = con.createStatement();
……
Catch(SQLException sqlEx){
Logger.error(“sql执行错误”+sql+sqlEx);
}


究竟在哪里记录异常信息,及怎么记录异常信息,可能是见仁见智的问题了。甚至有些系统让异常类一记录异常。当产生一个新异常对象时,异常信息就被自动记录。

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);
race();
}

 


这似乎看起来是十分美妙的,其实必然导致了异常被重复记录。同时违反了“类的职责分配原则”,是一种不好的设计。记录异常不属于异常类的行为,记录异常应该由专门的日志系统去做。并且异常的记录信息是不断变化的。我们在记录异常同应该给更丰富些的信息。以利于我们能够根据异常信息找到问题的根源,以解决问题。

虽然我们对记录异常讨论了很多,过多的强调这些反而使开发人员更为疑惑,一种好的方式是为系统提供一个异常处理框架。由框架来决定是否记录异常和怎么记录异常。而不是由普通程序员去决定。但是了解些还是有益的。

5. J2EE项目中的异常处理

目前,J2ee项目一般都会从逻辑上分为多层。比较经典的分为三层:表示层,业务层,集成层(包括数据库访问和外部系统的访问)。

J2ee项目有着其复杂性,J2ee项目的异常处理需要特别注意几个问题。

在分布式应用时,我们会遇到许多checked异常。所有RMI调用(包括EJB远程接口调用)都会抛出java.rmi.RemoteException;同时RemoteException是checked异常,当我们在业务系统中进行远程调用时,我们都需要编写大量的代码来处理这些checked异常。而一旦发生RemoteException这些checked异常对系统是非常严重的,几乎没有任何进行重试的可能。也就是说,当出现RemoteException这些可怕的checked异常,我们没有任何重试的必要性,却必须要编写大量的try…catch代码去处理它。一般我们都是在最底层进行RMI调用,只要有一个RMI调用,所有上层的接口都会要求抛出RemoteException异常。因为我们处理RemoteException的方式就是把它继续往上抛。这样一来就破坏了我们业务接口。RemoteException这些J2EE系统级的异常严重的影响了我们的业务接口。我们对系统进行分层的目的就是减少系统之间的依赖,每一层的技术改变不至于影响到其它层。

//
public class UserSoaImplimplements UserSoa{
public UserInfo getUserInfo(String userId)throws RemoteException{
//……
远程方法调用.
//……
}
}
public interface UserManager{
public UserInfo getUserInfo(Stirng userId)throws RemoteException;
}


同样JDBC访问都会抛出SQLException的checked异常。

为了避免系统级的checked异常对业务系统的深度侵入,我们可以为业务方法定义一个业务系统自己的异常。针对像SQLException,RemoteException这些非常严重的异常,我们可以新定义一个unChecked的异常,然后把SQLException,RemoteException封装成unChecked异常后抛出。

如果这个系统级的异常是要交由上一级调用者处理的,可以新定义一个checked的业务异常,然后把系统级的异常封存装成业务级的异常后再抛出。

一般地,我们需要定义一个unChecked异常,让集成层接口的所有方法都声明抛出这unChecked异常。

public DataAccessExceptionextends RuntimeException{
……
}
public interface UserDao{
public String getPassword(String userId)throws DataAccessException;
}
public class UserDaoImplimplements UserDAO{
public String getPassword(String userId)throws DataAccessException{
String sql = “select password from userInfo where userId= ‘”+userId+”'”;
try{
…
//JDBC调用
s.executeQuery(sql);
…
}catch(SQLException ex){
throw new DataAccessException(“数据库查询失败”+sql,ex);
}
}
}


定义一个checked的业务异常,让业务层的接口的所有方法都声明抛出Checked异常.

public class BusinessExceptionextends Exception{
…..
}
public interface UserManager{
public Userinfo copyUserInfo(Userinfo user)throws BusinessException{
Userinfo newUser = null;
try{
newUser = (Userinfo)user.clone();
}catch(CloneNotSupportedException ex){
throw new BusinessException(“不支持clone方法:”+Userinfo.class.getName(),ex);
}
}
}


J2ee表示层应该是一个很薄的层,主要的功能为:获得页面请求,把页面的参数组装成POJO对象,调用相应的业务方法,然后进行页面转发,把相应的业务数据呈现给页面。表示层需要注意一个问题,表示层需要对数据的合法性进行校验,比如某些录入域不能为空,字符长度校验等。

J2ee从页面所有传给后台的参数都是字符型的,如果要求输入数值或日期类型的参数时,必须把字符值转换为相应的数值或日期值。

如果表示层代码校验参数不合法时,应该返回到原始页面,让用户重新录入数据,并提示相关的错误信息。
通常把一个从页面传来的参数转换为数值,我们可以看到这样的代码

ModeAndView handleRequest(HttpServletRequest request,HttpServletResponse response)throws Exception{
String ageStr = request.getParameter(“age”);
int age = Integer.parse(ageStr);
…………
String birthDayStr = request.getParameter(“birthDay”);
SimpleDateFormat format = new SimpleDateFormat(“MM/dd/yyyy”);
Date birthDay = format.parse(birthDayStr);
}

   


上面的代码应该经常见到,但是当用户从页面录入一个不能转换为整型的字符或一个错误的日期值。

Integer.parse()方法被抛出一个NumberFormatException的unChecked异常。但是这个异常绝对不是一个致命的异常,一般当用户在页面的录入域录入的值不合法时,我们应该提示用户进行重新录入。但是一旦抛出unchecked异常,就没有重试的机会了。像这样的代码造成大量的异常信息显示到页面。使我们的系统看起来非常的脆弱。

同样,SimpleDateFormat.parse()方法也会抛出ParseException的unChecked异常。

这种情况我们都应该捕获这些unChecked异常,并给提示用户重新录入。

ModeAndView handleRequest(HttpServletRequest request,HttpServletResponse response)throws Exception{
String ageStr = request.getParameter(“age”);
String birthDayStr = request.getParameter(“birthDay”);
int age = 0;
Date birthDay = null;
try{
age=Integer.parse(ageStr);
}catch(NumberFormatException ex){
error.reject(“age”,”不是合法的整数值”);
}
…………
try{
SimpleDateFormat format = new SimpleDateFormat(“MM/dd/yyyy”);
birthDay = format.parse(birthDayStr);
}catch(ParseException ex){
error.reject(“birthDay”,”不是合法的日期,请录入'MM/dd/yyy'格式的日期”);
}
}

在表示层一定要弄清楚调用方法的是否会抛出unChecked异常,什么情况下会抛出这些异常,并作出正确的处理。

在表示层调用系统的业务方法,一般情况下是无需要捕获异常的。如果调用的业务方法抛出的异常相当于第二个返回值时,在这种情况下是需要捕获。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持PHP中文网。

更多Java EE项目中的异常处理总结(一篇不得不看的文章)相关文章请关注PHP中文网!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn