spring mvc 异常统一处理方式

springMVC提供的异常处理主要有两种方式,一种是直接实现自己的HandlerExceptionResolver,另一种是使用注解的方式实现一个专门用于处理异常的Controller——ExceptionHandler。

1、实现自己的HandlerExceptionResolver,HandlerExceptionResolver是一个接 口,springMVC本身已经对其有了一个自身的实现——DefaultExceptionResolver,该解析器只是对其中的一些比较典型的异常 进行了拦截处理。

  1. import javax.servlet.http.HttpServletRequest;
  2. import javax.servlet.http.HttpServletResponse;
  3. import org.springframework.web.servlet.HandlerExceptionResolver;
  4. import org.springframework.web.servlet.ModelAndView;
  5. public class ExceptionHandler implements HandlerExceptionResolver {
  6. @Override
  7. public ModelAndView resolveException(HttpServletRequest request,
  8. HttpServletResponse response, Object handler, Exception ex) {
  9. // TODO Auto-generated method stub
  10. return new ModelAndView("exception");
  11. }
  12. }

上述的resolveException的第4个参数表示对哪种类型的异常进行处理,如果想同时对多种异常进行处理,可以把它换成一个异常数组。

定义了这样一个异常处理器之后就要在applicationContext中定义这样一个bean对象,如:

  1. <bean id="exceptionResolver" class="com.tiantian.xxx.web.handler.ExceptionHandler"/>

2、使用@ExceptionHandler进行处理获取【下载地址】

使用@ExceptionHandler进行处理有一个不好的地方是进行异常处理的方法必须与出错的方法在同一个Controller里面

如:

  1. import org.springframework.stereotype.Controller;
  2. import org.springframework.web.bind.annotation.ExceptionHandler;
  3. import org.springframework.web.bind.annotation.RequestMapping;
  4. import com.tiantian.blog.web.servlet.MyException;
  5. @Controller
  6. public class GlobalController {
  7. /**
  8. * 用于处理异常的
  9. * @return
  10. */
  11. @ExceptionHandler({MyException.class})
  12. public String exception(MyException e) {
  13. System.out.println(e.getMessage());
  14. e.printStackTrace();
  15. return "exception";
  16. }
  17. @RequestMapping("test")
  18. public void test() {
  19. throw new MyException("出错了!");
  20. }
  21. }

这里在页面上访问test方法的时候就会报错,而拥有该test方法的Controller又拥有一个处理该异常的方法,这个时候处理异常的方法就会被调用

当发生异常的时候,上述两种方式都使用了的时候,第一种方式会将第二种方式覆盖

最近使用spring mvc开发一个web系统,发现在controller里发生未捕获异常时不出日志。

分析DispatcherServlet,初始化handlerExceptionResolvers

  1. /**
  2. * Initialize the strategy objects that this servlet uses.
  3. * <p>May be overridden in subclasses in order to initialize
  4. * further strategy objects.
  5. */
  6. protected void initStrategies(ApplicationContext context) {
  7. initMultipartResolver(context);
  8. initLocaleResolver(context);
  9. initThemeResolver(context);
  10. initHandlerMappings(context);
  11. initHandlerAdapters(context);
  12. // 初始化异常处理支持器
  13. initHandlerExceptionResolvers(context);
  14. initRequestToViewNameTranslator(context);
  15. initViewResolvers(context);
  16. }
  17. // 进入初始化处理方法,具体内容就不贴了,主要是先到上下文中搜寻我们自己定义的ExceptionResolvers,如果没有自定义的resolvers,从默认配置中读取。
  18. private void initHandlerExceptionResolvers(ApplicationContext context)
  19. // 从默认策略中取得默认配置,从DispatcherServlet.properties文 件中取得相关的配置策略,但是在spring2.5的mvc jar包中properties文件中没有 HandlerExceptionResolver的默认配置,返回一个EmptyList给handlerExceptionResolvers
  20. protected List getDefaultStrategies(ApplicationContext context, Class strategyInterface)

Java代码  

  1. 分析DispatcherServlet,分发处理请求
  1. // 从dispatch方法中看到,系统对请求进行具体的逻辑处理部分被catch住了一次exception,然后会使用servlet持有的ExceptionResolver进行处理
  2. protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
  3. HttpServletRequest processedRequest = request;
  4. HandlerExecutionChain mappedHandler = null;
  5. int interceptorIndex = -1;
  6. // Expose current LocaleResolver and request as LocaleContext.
  7. LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();
  8. LocaleContextHolder.setLocaleContext(buildLocaleContext(request), this.threadContextInheritable);
  9. // Expose current RequestAttributes to current thread.
  10. RequestAttributes previousRequestAttributes = RequestContextHolder.getRequestAttributes();
  11. ServletRequestAttributes requestAttributes = new ServletRequestAttributes(request);
  12. RequestContextHolder.setRequestAttributes(requestAttributes, this.threadContextInheritable);
  13. if (logger.isTraceEnabled()) {
  14. logger.trace("Bound request context to thread: " + request);
  15. }
  16. try {
  17. ModelAndView mv = null;
  18. boolean errorView = false;
  19. try {
  20. processedRequest = checkMultipart(request);
  21. // Determine handler for the current request.
  22. mappedHandler = getHandler(processedRequest, false);
  23. if (mappedHandler == null || mappedHandler.getHandler() == null) {
  24. noHandlerFound(processedRequest, response);
  25. return;
  26. }
  27. // Apply preHandle methods of registered interceptors.
  28. HandlerInterceptor[] interceptors = mappedHandler.getInterceptors();
  29. if (interceptors != null) {
  30. for (int i = 0; i < interceptors.length; i++) {
  31. HandlerInterceptor interceptor = interceptors[i];
  32. if (!interceptor.preHandle(processedRequest, response, mappedHandler.getHandler())) {
  33. triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null);
  34. return;
  35. }
  36. interceptorIndex = i;
  37. }
  38. }
  39. // Actually invoke the handler.
  40. HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
  41. mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
  42. // Do we need view name translation?
  43. if (mv != null && !mv.hasView()) {
  44. mv.setViewName(getDefaultViewName(request));
  45. }
  46. // Apply postHandle methods of registered interceptors.
  47. if (interceptors != null) {
  48. for (int i = interceptors.length - 1; i >= 0; i--) {
  49. HandlerInterceptor interceptor = interceptors[i];
  50. interceptor.postHandle(processedRequest, response, mappedHandler.getHandler(), mv);
  51. }
  52. }
  53. }
  54. catch (ModelAndViewDefiningException ex) {
  55. logger.debug("ModelAndViewDefiningException encountered", ex);
  56. mv = ex.getModelAndView();
  57. }
  58. // 这里catch住controller抛出的异常,使用持有的ExceptionResolver处理,当没有配置自己的处理器时,程序会将异常继续往上抛出,最终交给我们的容器处理
  59. catch (Exception ex) {
  60. Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
  61. mv = processHandlerException(processedRequest, response, handler, ex);
  62. errorView = (mv != null);
  63. }
  64. // Did the handler return a view to render?
  65. if (mv != null && !mv.wasCleared()) {
  66. render(mv, processedRequest, response);
  67. if (errorView) {
  68. WebUtils.clearErrorRequestAttributes(request);
  69. }
  70. }
  71. else {
  72. if (logger.isDebugEnabled()) {
  73. logger.debug("Null ModelAndView returned to DispatcherServlet with name ‘" +
  74. getServletName() + "‘: assuming HandlerAdapter completed request handling");
  75. }
  76. }
  77. // Trigger after-completion for successful outcome.
  78. triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null);
  79. }
  80. // 当没有配置ExceptionResolver时,异常将到达这里,最终抛出
  81. catch (Exception ex) {
  82. // Trigger after-completion for thrown exception.
  83. triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, ex);
  84. throw ex;
  85. }
  86. catch (Error err) {
  87. ServletException ex = new NestedServletException("Handler processing failed", err);
  88. // Trigger after-completion for thrown exception.
  89. triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, ex);
  90. throw ex;
  91. }
  92. finally {
  93. // Clean up any resources used by a multipart request.
  94. if (processedRequest != request) {
  95. cleanupMultipart(processedRequest);
  96. }
  97. // Reset thread-bound context.
  98. RequestContextHolder.setRequestAttributes(previousRequestAttributes, this.threadContextInheritable);
  99. LocaleContextHolder.setLocaleContext(previousLocaleContext, this.threadContextInheritable);
  100. // Clear request attributes.
  101. requestAttributes.requestCompleted();
  102. if (logger.isTraceEnabled()) {
  103. logger.trace("Cleared thread-bound request context: " + request);
  104. }
  105. }
  106. }

spring mvc异常设置,

  1. 此段代码ZZ from http://tdcq.iteye.com/blog/890957
  2. <!-- 全局异常配置 start -->
  3. <bean id="exceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
  4. <property name="exceptionMappings">
  5. <props>
  6. <prop key="java.lang.Exception">errors/error</prop>
  7. <prop key="java.lang.Throwable">errors/err</prop>
  8. </props>
  9. </property>
  10. <property name="statusCodes">
  11. <props>
  12. <prop key="errors/error">500</prop>
  13. <prop key="errors/404">404</prop>
  14. </props>
  15. </property>
  16. <!-- 设置日志输出级别,不定义则默认不输出警告等错误日志信息 -->
  17. <property name="warnLogCategory" value="WARN"></property>
  18. <!-- 默认错误页面,当找不到上面mappings中指定的异常对应视图时,使用本默认配置 -->
  19. <property name="defaultErrorView" value="errors/error"></property>
  20. <!-- 默认HTTP状态码 -->
  21. <property name="defaultStatusCode" value="500"></property>
  22. </bean>
  23. <!-- 全局异常配置 end -->

Java代码  

  1. 用spring mvc做了个项目,但是出现异常的情况下居然没有日志输出,然后各种尝试。。。正如上面介绍的:设置日志输出级别,不定义则默认不输出警告等错误日志信息!!【当然,try catch的异常没问题】
  2. 敬请留意。

时间: 2024-10-10 02:44:00

spring mvc 异常统一处理方式的相关文章

Spring MVC异常统一处理(异常信息的国际化,日志记录)

JAVA EE项目中,不管是对底层的数据操作,还是业务层的处理过程,还是控制层的处理,都不可避免的会遇到各种可预知的(业务异常主动抛出).不可预知的异常需要处理.一般dao层.service层的异常都会直接抛出,最后由controller统一进行处理,每个过程都单独处理异常,且要考虑到异常信息和前端的反馈,代码的耦合度高,不统一,后期维护的工作也多. 同时还必须考虑异常模块和日志模块.国际化的支持. 因此需要一种异常处理机制将异常处理解耦出来,这样保证相关处理过程的功能单一,和系统其它模块解耦,

spring mvc 异常统一处理 【转】

SpringMVC 提供的异常处理主要有两种方式,一种是直接实现自己的HandlerExceptionResolver,另一种是使用注解的方式实现一个专门用于处理异 常的Controller——ExceptionHandler.前者当发生异常时,页面会跳到指定的错误页面,后者同样,只是后者会在每个 controller中都需要加入重复的代码.如何进行简单地统一配置异常,使得发生普通错误指定到固定的页面,ajax发生错直接通过js获取,展现给 用户,变得非常重要.下面先介绍下2种异常处理方式,同时

Spring MVC异常统一处理(包括普通请求异常以及ajax请求异常)

通常SpringMVC对异常的配置都是返回某个jsp视图给用户,但是通过ajax方式发起请求,即使发生异常,前台也无法获得任何异常提示信息.因此需要对异常进行统一的处理,对于普通请求以及ajax请求的异常都有效. 1.Spring MVC的异常处理机制 Spring MVC 通过HandlerExceptionResolver处理程序的异常,包括处理器映射,数据绑定以及处理器执行时发生的异常.HandlerExceptionResolver仅有一个接口方法: ModelAndView resol

spring mvc异常统一处理(ControllerAdvice注解)

@ControllerAdvice,是spring3.2提供的新注解,从名字上可以看出大体意思是控制器增强.让我们先看看@ControllerAdvice的实现: Java代码   @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Component public @interface ControllerAdvice { } 没什么特别之处,该注解使用@Component注解,这样的话当我们使用

Spring MVC 中采用注解方式 Action中跳转到另一个Action的写法

Spring MVC 中采用注解方式 Action中跳转到另一个Action的写法 在Action中方法的返回值都是字符串行,一般情况是返回某个JSP,如: return "xx":意思是返回到某个JSP页面上 如果想在此Action中跳转到另一个Action中怎样做呢? return "redirect://.do?" 例如: @RequestMapping(params = "action=delete") public String del

Spring MVC自定义统一异常处理类,并且在控制台中输出错误日志

在使用SimpleMappingExceptionResolver实现统一异常处理后(参考Spring MVC的异常统一处理方法), 发现出现异常时,log4j无法在控制台输出错误日志.因此需要自定义一个继承至SimpleMappingExceptionResolver的 RrtongMappingExceptionResolver类,在RrtongMappingExceptionResolver中通过 log.error(ex.getMessage())的方式输出日志到控制台上.以下是具体的配

Spring MVC 的 XML 配置方式

索引: 开源Spring解决方案--lm.solution 参看代码 GitHub: solution/pom.xml solution/webapi/pom.xml solution/mapper/pom.xml web.xml spring-mvc.xml spring-context.xml dbconfig.properties log4j.properties RESTfulController.java 一.要点讲解 1.引入构建 spring .spring mvc 的框架类库 s

Spring MVC拦截器+注解方式实现防止表单重复提交

原理:在新建页面中Session保存token随机码,当保存时验证,通过后删除,当再次点击保存时由于服务器端的Session中已经不存在了,所有无法验证通过. 注,如果是集群的方式,则需要将token放入到缓存中即可. 注解Token代码:java源码  Java代码 复制代码 收藏代码 1[email protected](ElementType.METHOD) 2[email protected] (RetentionPolicy.RUNTIME) 3.public @interface T

Spring中的统一异常处理方式

源自:https://segmentfault.com/a/1190000016236188 在具体的SSM项目开发中,由于Controller层为处于请求处理的最顶层,再往上就是框架代码的. 因此,肯定需要在Controller捕获所有异常,并且做适当处理,返回给前端一个友好的错误码. 不过,Controller一多,我们发现每个Controller里都有大量重复的.冗余的异常处理代码,很是啰嗦.能否将这些重复的部分抽取出来,这样保证Controller层更专注于业务逻辑的处理,同时能够使得异