Welcome 微信登录

首页 / 操作系统 / Linux / SpringMVC错误页面配置

当前SpringMVC非常流行,在大多数情况,我们都需要自定义一些错误页面(例如:401, 402, 403, 500…),以便更友好的提示。对于spring mvc,这些当然是支持自定义的,spring是怎么做的? 还是去看看spring的源码吧:

原理

DispatcherServlet

众所周知,springmvc的入口是DispatcherServlet, 在DispatcherServlet的源码中,不知你是否注意到了以下方法:protected ModelAndView processHandlerException(HttpServletRequest request, HttpServletResponse response,Object handler, Exception ex) throws Exception {// Check registered HandlerExceptionResolvers...ModelAndView exMv = null;for (HandlerExceptionResolver handlerExceptionResolver : this.handlerExceptionResolvers) {exMv = handlerExceptionResolver.resolveException(request, response, handler, ex);if (exMv != null) {break;}}if (exMv != null) {if (exMv.isEmpty()) {request.setAttribute(EXCEPTION_ATTRIBUTE, ex);return null;}// We might still need view name translation for a plain error model...if (!exMv.hasView()) {exMv.setViewName(getDefaultViewName(request));}if (logger.isDebugEnabled()) {logger.debug("Handler execution resulted in exception - forwarding to resolved error view: " + exMv, ex);}WebUtils.exposeErrorRequestAttributes(request, ex, getServletName());return exMv;}throw ex;}这个方法就是springmvc对于异常的处理,其调用了HandlerExceptionResolver的resolveException方法。HandlerExceptionResolver有众多实现类,其中,重点看看
SimpleMappingExceptionResolver(我们就是要通过它来配置自定义错误页面)。

SimpleMappingExceptionResolver

public class SimpleMappingExceptionResolver extends AbstractHandlerExceptionResolver {...private Properties exceptionMappings;private Class<?>[] excludedExceptions;private Map<String, Integer> statusCodes = new HashMap<String, Integer>();...public void setExceptionMappings(Properties mappings) {this.exceptionMappings = mappings;}public void setStatusCodes(Properties statusCodes) {for (Enumeration<?> enumeration = statusCodes.propertyNames(); enumeration.hasMoreElements();) {String viewName = (String) enumeration.nextElement();Integer statusCode = new Integer(statusCodes.getProperty(viewName));this.statusCodes.put(viewName, statusCode);}}}@Overrideprotected ModelAndView doResolveException(HttpServletRequest request, HttpServletResponse response,Object handler, Exception ex) {// Expose ModelAndView for chosen error view.String viewName = determineViewName(ex, request);if (viewName != null) {// Apply HTTP status code for error views, if specified.// Only apply it if we"re processing a top-level request.Integer statusCode = determineStatusCode(request, viewName);if (statusCode != null) {applyStatusCodeIfPossible(request, response, statusCode);}return getModelAndView(viewName, ex, request);}else {return null;}}protected String determineViewName(Exception ex, HttpServletRequest request) {String viewName = null;if (this.excludedExceptions != null) {for (Class<?> excludedEx : this.excludedExceptions) {if (excludedEx.equals(ex.getClass())) {return null;}}}// Check for specific exception mappings.if (this.exceptionMappings != null) {viewName = findMatchingViewName(this.exceptionMappings, ex);}// Return default error view else, if defined.if (viewName == null && this.defaultErrorView != null) {if (logger.isDebugEnabled()) {logger.debug("Resolving to default view "" + this.defaultErrorView + "" for exception of type [" +ex.getClass().getName() + "]");}viewName = this.defaultErrorView;}return viewName;}protected String findMatchingViewName(Properties exceptionMappings, Exception ex) {String viewName = null;String dominantMapping = null;int deepest = Integer.MAX_VALUE;for (Enumeration<?> names = exceptionMappings.propertyNames(); names.hasMoreElements();) {String exceptionMapping = (String) names.nextElement();int depth = getDepth(exceptionMapping, ex);if (depth >= 0 && (depth < deepest || (depth == deepest &&dominantMapping != null && exceptionMapping.length() > dominantMapping.length()))) {deepest = depth;dominantMapping = exceptionMapping;viewName = exceptionMappings.getProperty(exceptionMapping);}}if (viewName != null && logger.isDebugEnabled()) {logger.debug("Resolving to view "" + viewName + "" for exception of type [" + ex.getClass().getName() +"], based on exception mapping [" + dominantMapping + "]");}return viewName;}protected Integer determineStatusCode(HttpServletRequest request, String viewName) {if (this.statusCodes.containsKey(viewName)) {return this.statusCodes.get(viewName);}return this.defaultStatusCode;}由此可见:SimpleMappingExceptionResolver通过 exceptionMappings和statusCodes来确立Exception、http状态码以及view之间的映射关系。明白这个就很简单了,我们可以通过设置exceptionMappings、statusCodes的值来实现我们自定义的映射关系。

实战

页面准备

  1. 我们在WEB-INF/views/commons/error(目录自己定)新建我们自定义的错误页面,404.html, 500.html等等。
  2. SimpleMappingExceptionResolver只实现映射关系,我们还需要通过配置web.xml来实现。<error-page><error-code>404</error-code><location>/error/404.html</location></error-page><error-page><error-code>500</error-code><location>/error/500.html</location></error-page>  
  3. 在spring-mvc配置文件中将404.html、500.html等设置为资源文件,避免被springmvc再次拦截。<mvc:resources mapping="/error/**" location="/WEB-INF/views/commons/error/" />
  4. 配置SimpleMappingExceptionResolver。<bean class="org.springframework.web.servlet.handler. SimpleMappingExceptionResolver"><property name="exceptionMappings"><map><entry key="ResourceNotFoundException" value="common/error/resourceNotFoundError" /><entry key=".DataAccessException" value="common/error/dataAccessError" /></map></property><property name="statusCodes"><map><entry key="common/error/resourceNotFoundError" value="404" /><entry key="common/error/dataAccessError" value="500" /></map></property></bean>
到此,就实现我们需要的配置了。SpringMVC+MyBatis集成配置  http://www.linuxidc.com/Linux/2016-09/135212.htmSpringMVC总结篇  http://www.linuxidc.com/Linux/2016-06/132659.htmSpring+SpringMVC企业快速开发架构搭建  http://www.linuxidc.com/Linux/2015-09/122942.htmSpringMVC的乱码处理  http://www.linuxidc.com/Linux/2015-07/120542.htmSpring MVC+Spring3+Hibernate4开发环境搭建 http://www.linuxidc.com/Linux/2013-07/87119.htmSpring MVC整合Freemarker基于注解方式 http://www.linuxidc.com/Linux/2013-02/79660.htm基于注解的Spring MVC简单介绍 http://www.linuxidc.com/Linux/2012-02/54896.htmSpringMVC详细示例实战教程 http://www.linuxidc.com/Linux/2015-06/118461.htmSpring MVC 框架搭建及详解 http://www.linuxidc.com/Linux/2012-01/52740.htmSpringMVC 异常处理  http://www.linuxidc.com/Linux/2015-06/119049.htmSpringMVC框架入门配置 IDEA下搭建Maven项目 http://www.linuxidc.com/Linux/2016-09/134918.htm本文永久更新链接地址:http://www.linuxidc.com/Linux/2016-12/138097.htm