ControllerAdvice 有条件地处理异常
Posted
技术标签:
【中文标题】ControllerAdvice 有条件地处理异常【英文标题】:ControllerAdvice conditionally handle exception 【发布时间】:2020-12-02 05:46:56 【问题描述】:我有一个控制器建议来处理我的 REST 控制器中的异常行为,我遇到了一种情况,我必须有条件地处理具有特定消息(重复键的消息)的 SQLIntegrityConstraintViolationException
,返回 409
,让其他的由默认处理程序处理(返回500
错误代码)。
我正在考虑两种可能的方法来实现这一目标:
-
根据我的情况在 else 分支上抛出一个新的裸机
Exception
,因此处理由 Spring 完成。
显式调用通用异常处理程序(例如从我的 else 分支内部调用 return handleGeneralException(exception)
)。
我有一种“正确”的方式可以将我的ControllerAdvice
中的一小部分异常传递给另一个处理程序,而不是“原始”处理程序?
编辑 1: 我想在我的 ControllerAdvice 中做这样的事情:
if (exception.getMessage.contains("something"))
// handle exception
else
// pass to other handler
【问题讨论】:
【参考方案1】:有一个自定义异常类,然后当您抛出 SQLIntegrityConstraintViolationException
时,将其包装在您的自定义异常类中,其中包含您希望在控制器建议中访问的任何附加字段。处理控制器建议类中的自定义异常。
@ControllerAdvice
public class CustomExceptionHandler
@ExceptionHandler(YourCustomException.class)
public final ResponseEntity<ExceptionResponse> handleNotFoundException(YourCustomExceptionex,
WebRequest request)
ExceptionResponse exceptionResponse = new ExceptionResponse(new Date(), ex.getMessage(),
request.getDescription(false), HttpStatus.NOT_ACCEPTABLE.getReasonPhrase());
return new ResponseEntity<>(exceptionResponse, HttpStatus.CONFLICT);
虽然在代码中使用 try catch 块来处理此异常,但如果您使用 Spring Data JPA,请确保处理 DataIntegrityViolationException
而不是 SQLIntegrityConstraintViolationException
。因此,如果您使用的是 Spring Data Jpa,那么:
try
anyRepository.save(new YourModel(..));
catch (DataIntegrityViolationException e)
System.out.println("history already exist");in res
throw New YourCustomException("additional msg if you need it ", e);
【讨论】:
问题是这是一个运行时异常——我可以在哪里处理和包装它?有在控制器的建议?我的意思是,我从来没有在我的代码中处理它 为您的代码创建一个 try catch 块,并在 catch 块句柄SQLIntegrityConstraintViolationException
中重新抛出它作为您的自定义异常类。
我的问题是我应该在哪里有那个 try-catch 块。请看我的编辑
@AvramPop 尝试捕获将在运行时抛出此异常的代码块。【参考方案2】:
以下代码将在ControllerAdbvice中捕获异常SQLIntegrityConstraintViolationException的错误信息,无需在代码中处理
@ControllerAdvice
public class CustomGlobalExceptionHandler extends ResponseEntityExceptionHandler
@ExceptionHandler(value = DataIntegrityViolationException.class)
public ResponseEntity<ExceptionResponse> dataIntegrityViolationExceptionHandler(Exception ex)
ExceptionResponse response = new ExceptionResponse();
Throwable throwable = ex.getCause();
while (throwable != null)
if (throwable instanceof SQLIntegrityConstraintViolationException)
String errorMessage = throwable.getMessage();
response.setErrors(new ArrayList<>(Arrays.asList(errorMessage)));
throwable = throwable.getCause();
return new ResponseEntity<Object>(response, HttpStatus.CONFLICT);
【讨论】:
你可能没有理解这个问题...我想做一些类似 if(throwable.getCause().equals("somecause")) return new ResponseEntity; else (见我的编辑)以上是关于ControllerAdvice 有条件地处理异常的主要内容,如果未能解决你的问题,请参考以下文章
Spring Boot @ControllerAdvice 异常处理程序未触发
如何让一个由 ControllerAdvice 注释的类来处理不同类型的异常?