【发布时间】:2023-03-21 20:35:01
【问题描述】:
我最近在我的 Spring 4 / Hibernate Web 应用程序中实现了 Spring Security 来处理登录/注销和不同的用户角色。
经过大量阅读,它现在似乎工作得很好,但我注意到由于错误的 Spring Security 配置引发的异常没有使用我的自定义处理程序优雅地处理,而是显示为丑陋的 Tomcat 错误页面(显示 HTTP 状态 500 - 需要 UserDetailsService 后跟堆栈跟踪)。
解决特定错误并不困难(在 RememberMe 配置中添加 userDetailsService(userDetailsService))但事实仍然是抛出的一些异常没有由 如下所示的 ControllerAdvice 处理 MaxUploadSizeExceededException 和所有其他运行时异常:
@ControllerAdvice
public class ExceptionHandlingControllerAdvice {
public static final String DEFAULT_ERROR_VIEW = "genericerror";
@ExceptionHandler(value = MaxUploadSizeExceededException.class)
public View maxUploadSizeExceededExceptionHandler(
HttpServletRequest req) throws IOException {
String redirectUrl = req.getRequestURL().toString();
RedirectView rv = new RedirectView(redirectUrl);
FlashMap outputFlashMap = RequestContextUtils.getOutputFlashMap(req);
if (outputFlashMap != null) {
outputFlashMap.put(KeyConstants.FLASH_ERROR_KEY, "Bestand is te groot");
}
return rv;
}
@ExceptionHandler(value = RuntimeException.class)
public View defaultErrorHandler(HttpServletRequest req, Exception e) {
RedirectView rv = new RedirectView("/error", true); //context relative
StackTraceElement[] steArray = e.getStackTrace();
StringBuilder stackTrace = new StringBuilder();
for (StackTraceElement element: steArray) {
stackTrace.append(element.toString() + "\n");
}
FlashMap outputFlashMap = RequestContextUtils.getOutputFlashMap(req);
if (outputFlashMap != null) {
outputFlashMap.put("url", req.getRequestURL());
outputFlashMap.put("excClassName", e.getClass().getName());
outputFlashMap.put("excMessage", e.getMessage());
outputFlashMap.put("excStacktrace", stackTrace.toString());
}
e.printStackTrace();
return rv;
}
}
但是配置不完整的Security抛出的异常很可能没有被这个机制捕获,因为登录POST请求在调用任何控制器方法之前就被Spring Security拦截了。我想在自定义错误页面上以优雅的方式显示所有异常,以及在控制器到位之前抛出的异常。
我找不到太多相关信息,Spring 手册 (http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#mvc-exceptionhandlers) 中描述的所有错误处理技术似乎都使用了控制器建议。
有没有一种方便的方法来以通用方式处理所有异常?并让我的 Controller 建议类处理异常变得多余?
【问题讨论】:
-
为什么不能简单地将@ExceptionHandler(value = RuntimeException.class) 改为@ExceptionHandler(value = Exception.class)。这样你应该能够处理所有的异常。
-
不,这并不能解决问题。问题不在于异常类过于具体,而是在调用 Controller 方法和 ControllerAdvice 发挥作用之前抛出异常。
-
好的,明白了,你可能会像使用 servlet 异常处理程序那样低级。
标签: spring-mvc spring-security error-handling