本文介紹了如何在默認異常處理建議已由其他建議處理時將其忽略的處理方法,對大家解決問題具有一定的參考價值,需要的朋友們下面隨著小編來一起學習吧!
問題描述
我目前有一個ExceptionAdvice類,它處理所有基本的(400、405、404和其他)異常。例如,我有一個默認建議,它處理所有的MethodArgumentNotValidExceptions并返回400個錯誤請求錯誤。例如
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(MethodArgumentNotValidException.class)
public Error handleBadRequestException(Exception exception) {
return buildError(extractTriggerElement(exception), exception);
}
我還有一個不同的切入點建議,目標是處理方法ArgumentNotValidException的一個控制器方法,因為我需要為這種情況創建自定義錯誤消息。大概是這樣的
@AfterThrowing(pointcut = "execution(*
package.controller.MyController*.updateSomething(*))", throwing = "ex")
private Error handleCustomError(MethodArgumentNotValidException ex) {
return buildCustomError(ex);
}
問題是,控制器建議首先被調用,但隨后它被默認的建議覆蓋,因此我得到了默認的錯誤消息。
有沒有辦法在其他建議已經處理過的情況下忽略來自默認建議的@ExceptionHandler
,這樣我就可以拿回CustomError消息?
推薦答案
您誤會了@AfterThrowing
:
您只能使用這種建議,以便在方法因異常退出之后、拋出它之前以及可能由另一段代碼處理之前執行某些操作。您無法更改應用程序流,例如,捕獲異常或操作方法結果。
此外,由于我剛才解釋的原因,@AfterThrowing
建議必須返回void
。您的建議甚至不應該編譯,但是編譯器應該會產生錯誤";。這個建議必須返回void";。至少這是我的AspectJ編譯器所做的(我使用的是完整的AspectJ,而不是稱為Spring AOP的精簡版,但結果應該是相同的。)
有關@AfterThrowing
的詳細信息,請參閱Spring AOP manual。
解釋完這一點后,您能做什么?我將在一個純Java+AspectJ示例中向您展示,以便將Spring從等式中去掉。您可以自己輕松地將知識傳授給Spring AOP和Spring MVC錯誤處理程序:
更改應用程序流所需的是@Around
建議。如果您發出這種通知,捕獲特殊方法中的錯誤并返回錯誤對象,則默認的Spring異常處理程序甚至不會看到存在異常,因為它已經被方面捕獲。即,默認處理程序將僅處理方面未處理的所有其他錯誤。
以下是一些完全自洽且可編譯的示例代碼:
響應類:
我們在示例應用程序中使用它們,以便像在Spring中一樣模擬正常和錯誤響應。
package de.scrum_master.app;
public interface Response {
String getMessage();
}
package de.scrum_master.app;
public class NormalResponse implements Response {
private String message = "OK";
@Override
public String getMessage() {
return message;
}
@Override
public String toString() {
return "NormalResponse [message=" + message + "]";
}
}
package de.scrum_master.app;
public class ErrorResponse implements Response {
private String message;
private Exception exeception;
public ErrorResponse(String message, Exception exeception) {
this.message = message;
this.exeception = exeception;
}
@Override
public String getMessage() {
return message;
}
public Exception getExeception() {
return exeception;
}
@Override
public String toString() {
return "ErrorResponse [message=" + message + ", exeception=" + exeception + "]";
}
}
驅動程序應用程序:
該應用程序有兩種方法,這兩種方法都會隨機生成正常或錯誤響應。方法produceSpecialException()
是我們希望由方面稍后處理的方法。
我們通過try-Catch塊模擬默認處理程序,然后調用幫助器方法defaultHandler(Exception e)
。
package de.scrum_master.app;
import java.util.Random;
public class Application {
private final static Random RANDOM = new Random();
public Response produceException() throws Exception {
if (RANDOM.nextBoolean())
throw new Exception("normal error");
return new NormalResponse();
}
public Response produceSpecialException() throws Exception {
if (RANDOM.nextBoolean())
throw new Exception("special error");
return new NormalResponse();
}
public static ErrorResponse defaultHandler(Exception e) {
return new ErrorResponse("default handler", e);
}
public static void main(String[] args) {
Application application = new Application();
for (int i = 0; i < 5; i++) {
try {
System.out.println(application.produceException());
} catch (Exception e) {
System.out.println(defaultHandler(e));
}
try {
System.out.println(application.produceSpecialException());
} catch (Exception e) {
System.out.println(defaultHandler(e));
}
}
}
}
無方面控制臺日志:
ErrorResponse [message=default handler, exeception=java.lang.Exception: normal error]
NormalResponse [message=OK]
ErrorResponse [message=default handler, exeception=java.lang.Exception: normal error]
ErrorResponse [message=default handler, exeception=java.lang.Exception: special error]
NormalResponse [message=OK]
NormalResponse [message=OK]
ErrorResponse [message=default handler, exeception=java.lang.Exception: normal error]
ErrorResponse [message=default handler, exeception=java.lang.Exception: special error]
NormalResponse [message=OK]
NormalResponse [message=OK]
正如您在上面看到的,所有錯誤都由默認處理程序處理。這并不令人驚訝。
方面:
該方面僅處理";特殊";錯誤,忽略其他錯誤。
package de.scrum_master.aspect;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import de.scrum_master.app.ErrorResponse;
import de.scrum_master.app.Response;
@Aspect
public class ErrorHandler {
@Around("execution(de.scrum_master.app.Response produceSpecialException(..))")
public Response handleError(ProceedingJoinPoint thisJoinPoint) throws Throwable {
try {
return (Response) thisJoinPoint.proceed();
}
catch (Exception e) {
return new ErrorResponse("aspect handler", e);
}
}
}
帶有方面的控制臺日志:
ErrorResponse [message=default handler, exeception=java.lang.Exception: normal error]
ErrorResponse [message=aspect handler, exeception=java.lang.Exception: special error]
NormalResponse [message=OK]
ErrorResponse [message=aspect handler, exeception=java.lang.Exception: special error]
ErrorResponse [message=default handler, exeception=java.lang.Exception: normal error]
NormalResponse [message=OK]
ErrorResponse [message=default handler, exeception=java.lang.Exception: normal error]
ErrorResponse [message=aspect handler, exeception=java.lang.Exception: special error]
NormalResponse [message=OK]
NormalResponse [message=OK]
如上所述,現在某些錯誤由aspect handler
(";特殊錯誤&)處理,而所有其他錯誤仍由default handler
(";正常錯誤&q;)處理。
這篇關于如何在默認異常處理建議已由其他建議處理時將其忽略的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,