zoukankan      html  css  js  c++  java
  • Spring 梳理 -异常处理

    1. Spring 提供了多种方式将异常转换为相应
      1. Spring框架提供的通用异常,将异常转换为HTTP状态码
        1. Spring默认会将自身抛出的异常自动映射到合适的状态码,如下是一些示例:

          举个例子,当后端抛出如下异常(TypeMismatchException异常,往方法传参时,类型不匹配):

          org.springframework.beans.TypeMismatchException: Failed to convert value of type 'java.lang.String' to required type 'long'; nested exception is java.lang.NumberFormatException: For input string: "2l"
              at org.springframework.beans.TypeConverterSupport.doConvert(TypeConverterSupport.java:77)
              at org.springframework.beans.TypeConverterSupport.convertIfNecessary(TypeConverterSupport.java:47)
              at org.springframework.validation.DataBinder.convertIfNecessary(DataBinder.java:603)
          ...

          前台返回400状态码:

      2. 在异常上可以添加@ResponseStatus注解,从而将普通异常转换为HTTP状态码
        1. 除了以上异常,对于其它异常以及我们业务自己抛出的异常,如果没有明确绑定Http状态码,响应默认都会带有500状态码
        2. 当然,除了这些默认机制,我们也可以将自定义异常绑定特点的Http状态码,通过@ResponseStatus注解可实现,如下示例:

           定义一个异常,通过@ResponseStatus注解绑定400状态码:

          @ResponseStatus(value = HttpStatus.NOT_FOUND)
          public class MyException extends RuntimeException
          {
          
          }

          然后再controller抛出自定义异常throw new MyException();

          访问controller,发现响应确实返回了400状态码。

      3. 在方法上添加@ExceptionHandler注解,使得控制器方法具备处理异常的能力
        1. 控制器内部异常,在控制器内部处理
        2. 我们在controller下添加了一个MyException异常的处理方法,直接返回到body。适用于控制器内部,抛出“MyException.class”的方法。如果控制内部抛出的有其他类型的异常,如OtherException,再在控制器内部添加一个“@ExceptionHandler(OtherException.class)”即可

              @ExceptionHandler(MyException.class)
              @ResponseBody
              public String handleException(){
                  return "handle by ExceptionHandler.";
              }

          打开浏览器,观察结果:

      4. 控制器通知(@ControllerAdvice)
        1. 用户添加异常处理全局机制,避免在每个控制内内部定义独立的异常控制流程
        2. @ControllerAdvice最实用定义场景是将所有@ExceptionHandler方法收集到一个类中,这样所有控制器的异常可以在一个进行一致的处理
        3. 异常处理方法只能处理同一个controller中抛出的异常,然而一个系统,肯定不止一个controller,总不可能在每个controller中都添加重复性的异常处理方法吧~~

          那么对于多个controller,如何处理异常呢?使用@ControllerAdvice注解即可。

        4. 有一个点注意下,就是spring 扫描配置的时候,要包括该bean,参考配置如下,可参考:
          1. spring-mvc.xml:
            
                <context:component-scan base-package="com.cetiti.epdc.dss" >
                    <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>  
                    <context:include-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice"/> 
                </context:component-scan> 
            
            spring.xml
            
                <context:component-scan base-package="com.cetiti.epdc.dss">
                    <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" />
                    <context:exclude-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice" />
                </context:component-scan>
            
            另外,在上面的示例中,范围更小的异常,优先级更大,所以会调用handleNumberFormatException方法。
        5. 带有@ControllerAdvice注解的类,可以收到系统中所有Controller抛出的异常,如下示例:

          复制代码
          @ControllerAdvice
          public class DSSExceptionHandler extends BaseController
          {
          
              /**
               * 处理controller抛出的异常
               *
               * @return
               */
              @ExceptionHandler(Exception.class)
              @ResponseBody
              public String handleException(HttpServletRequest request, Exception e)
              {
                  logger.error("Request FAILD, URL = {} ", request.getRequestURI());
                  logger.error(e.toString(), e);
                  return gson.toJson(BaseController.FAILD);
              }
          
              /**
               * 处理controller抛出的异常
               *
               * @return
               */
              @ExceptionHandler(NumberFormatException.class)
              @ResponseBody
              public String handleNumberFormatException(HttpServletRequest request, NumberFormatException e)
              {
                  logger.error("Request FAILD, URL = {} ", request.getRequestURI());
                  logger.error(e.toString(), e);
                  return gson.toJson(BaseController.FAILD);
              }
          
          }
           
    2. 下面是几个ExceptionHandler注解的使用例子:

      @Controller
      public class ExceptionHandlingController {
      
        // @RequestHandler methods
        ...
        
        // 以下是异常处理方法
        
        // 将DataIntegrityViolationException转化为Http Status Code为409的响应
        @ResponseStatus(value=HttpStatus.CONFLICT, reason="Data integrity violation")  // 409
        @ExceptionHandler(DataIntegrityViolationException.class)
        public void conflict() {
          // Nothing to do
        }
        
        // 针对SQLException和DataAccessException返回视图databaseError
        @ExceptionHandler({SQLException.class,DataAccessException.class})
        public String databaseError() {
          // Nothing to do.  Returns the logical view name of an error page, passed to
          // the view-resolver(s) in usual way.
          // Note that the exception is _not_ available to this view (it is not added to
          // the model) but see "Extending ExceptionHandlerExceptionResolver" below.
          return "databaseError";
        }
      
        // 创建ModleAndView,将异常和请求的信息放入到Model中,指定视图名字,并返回该ModleAndView
        @ExceptionHandler(Exception.class)
        public ModelAndView handleError(HttpServletRequest req, Exception exception) {
          logger.error("Request: " + req.getRequestURL() + " raised " + exception);
      
          ModelAndView mav = new ModelAndView();
          mav.addObject("exception", exception);
          mav.addObject("url", req.getRequestURL());
          mav.setViewName("error");
          return mav;
        }
      }
    3. 参考 https://www.cnblogs.com/junzi2099/p/7840294.html
    4. 参考 https://www.cnblogs.com/chenpi/p/6117090.html
  • 相关阅读:
    Python(21):numpy数组模块
    ASP.NET(99):ASP.NET 内容管理系统CMS
    Python(20):Python常用模块sys、random、math
    Python(19):Python标准库: 日期、时间和日历模块
    Python(18):Python模块基础
    微信官方文档
    Python(17):Python面向对象高级
    Python(16):Python面向对象进阶
    Python(15):Python面向对象基础
    Python(14):python异常处理
  • 原文地址:https://www.cnblogs.com/jiangtao1218/p/9824651.html
Copyright © 2011-2022 走看看