我最近在我的 Spring 4 / Hibernate Web 应用程序中实现了 Spring Security 来处理登录/注销和不同的用户角色。
经过大量阅读后,它现在看起来工作得很好,但我注意到由于错误的 Spring Security 配置而引发的异常没有使用我的自定义处理程序正常处理,而是显示为丑陋的 Tomcat 错误页面(显示 HTTP Status 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 引发的异常,因为在调用任何控制器方法之前,Spring Security 会拦截登录 POST 请求。我想在自定义错误页面上以优雅的方式显示所有异常,以及在控制器到位之前抛出的异常。
我找不到太多相关信息,Spring 手册中描述的所有错误处理技术(http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#mvc-exceptionhandlers http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#mvc-exceptionhandlers)似乎使用控制器建议。
是否有一种方便的方法以通用方式处理所有异常?并使我的控制器建议类处理异常变得多余?