kay*_*ahr 27 java spring freemarker spring-mvc
我有一个Spring MVC应用程序,它使用FreeMarker作为View技术(但也许视图技术对我的问题并不重要).我需要拦截在请求期间可能抛出的所有异常.
我已经实现了HandlerExceptionResolver,但只有在控制器中发生异常时才会执行此解析程序.但是当控制器返回ModelAndView并且在渲染视图时发生异常(因为找不到变量或类似的东西),则不会调用异常解析器,而是在浏览器窗口中获得堆栈跟踪.
我还尝试在控制器中使用异常处理程序方法,该方法返回视图并使用@ExceptionHandler对其进行注释,但这也不起作用(很可能是因为异常不会在控制器中抛出但在视图中).
那么是否有一些Spring机制可以注册一个捕获视图错误的异常处理程序?
oxc*_*oxc 21
提前说一句:如果你只需要一个没有太多逻辑和模型准备的"静态"错误页面,那么<error-page>在你的文章中添加一个-Tag 就足够了web.xml(见下面的例子).
否则,可能有更好的方法来做到这一点,但这对我们有用:
我们使用servlet <filter>中web.xml,捕捉所有的异常,并调用我们自定义的ErrorHandler,我们春节HandlerExceptionResolver内使用相同的.
<filter>
<filter-name>errorHandlerFilter</filter-name>
<filter-class>org.example.filter.ErrorHandlerFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>errorHandlerFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Run Code Online (Sandbox Code Playgroud)
实现看起来基本上是这样的:
public class ErrorHandlerFilter implements Filter {
ErrorHandler errorHandler;
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
try {
filterChain.doFilter(request, response);
} catch (Exception ex) {
// call ErrorHandler and dispatch to error jsp
String errorMessage = errorHandler.handle(request, response, ex);
request.setAttribute("errorMessage", errorMessage);
request.getRequestDispatcher("/WEB-INF/jsp/error/dispatch-error.jsp").forward(request, response);
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
errorHandler = (ErrorHandler) WebApplicationContextUtils
.getRequiredWebApplicationContext(filterConfig.getServletContext())
.getBean("defaultErrorHandler");
}
// ...
}
Run Code Online (Sandbox Code Playgroud)
我相信这应该对FreeMarker模板几乎一样.当然,如果您的错误视图引发错误,那么您或多或少会有选项.
为了捕获404之类的错误并为其准备模型,我们使用映射到ERROR调度程序的过滤器:
<filter>
<filter-name>errorDispatcherFilter</filter-name>
<filter-class>org.example.filter.ErrorDispatcherFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>errorDispatcherFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>ERROR</dispatcher>
</filter-mapping>
<error-page>
<error-code>404</error-code>
<location>/WEB-INF/jsp/error/dispatch-error.jsp</location>
</error-page>
<error-page>
<exception-type>java.lang.Exception</exception-type>
<location>/WEB-INF/jsp/error/dispatch-error.jsp</location>
</error-page>
Run Code Online (Sandbox Code Playgroud)
doFilter-Implementation看起来像这样:
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
final HttpServletRequest request = (HttpServletRequest) servletRequest;
// handle code(s)
final int code = (Integer) request.getAttribute("javax.servlet.error.status_code");
if (code == 404) {
final String uri = (String) request.getAttribute("javax.servlet.error.request_uri");
request.setAttribute("errorMessage", "The requested page '" + uri + "' could not be found.");
}
// notify chain
filterChain.doFilter(servletRequest, servletResponse);
}
Run Code Online (Sandbox Code Playgroud)
您可以扩展DispatcherServlet.
在您的web.xml中,替换您自己的类的通用DispatcherServlet.
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>com.controller.generic.DispatcherServletHandler</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
Run Code Online (Sandbox Code Playgroud)
稍后创建自己的类DispatcherServletHandler并从DispatcherServlet扩展:
public class DispatcherServletHandler extends DispatcherServlet {
private static final String ERROR = "error";
private static final String VIEW_ERROR_PAGE = "/WEB-INF/views/error/view-error.jsp";
@Override
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
try{
super.doService(request, response);
} catch(Exception ex) {
request.setAttribute(ERROR, ex);
request.getRequestDispatcher(VIEW_ERROR_PAGE).forward(request, response);
}
}
}
Run Code Online (Sandbox Code Playgroud)
在该页面中,我们只需向用户显示一条消息.