我最近在Spring 4 / Hibernate Web应用程序中实现了Spring Security,以处理登录/退出和不同的用户角色。
经过大量阅读后,它现在看起来工作得很好,但是我注意到由于错误的Spring Security配置引发的异常没有使用我的自定义处理程序正常处理,但显示为丑陋的Tomcat错误页面(显示HTTP状态500) - 需要UserDetailsService,然后是stacktrace)。
解决特定错误并不困难(在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;
}
}
但是,未完成配置的安全性抛出的异常可能不会被此机制捕获,因为在调用任何控制器方法之前,Spring Security会截获登录POST请求。我想在自定义错误页面上以优雅的方式显示所有异常,也就是在Controller到位之前抛出的异常。
我找不到很多相关信息,Spring手册(http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#mvc-exceptionhandlers)中描述的所有错误处理技术似乎都使用了Controller建议。
是否有通过通用方式处理所有异常的便捷方法?并使我的Controller建议类处理多余的异常?
答案 0 :(得分:8)
正如您所注意到的那样,@ExceptionHandler
对于抛出外部(在堆中的位置比)Spring MVC的异常不起作用。
您可以通过在web.xml中指定错误页面来捕获未在其他地方捕获的所有异常:
<error-page>
<exception-type>java.lang.Throwable</exception-type>
<location>/500</location>
</error-page>
您将此500页设为普通页面,通常在Spring MVC中:
@RequestMapping(value="/500")
public @ResponseBody String handleException(HttpServletRequest req) {
// this will get the exception thrown/caught
Throwable exception = (Throwable)req.getAttribute("javax.servlet.error.exception");
// customize the response as you want
return "Internal server error.";
}
答案 1 :(得分:3)
如果你使用的是Spring Boot,你可以创建一个自定义的ErrorController,你手边有一个名为BasicErrorController的默认值。