• Spring复习——day16_SpringMVC_异常处理器


    目录

     

    11、异常处理器

    11.1、异常处理器简单入门

    11.1.1、基于配置的异常处理

    11.1.2、基于注解的异常处理

    11.2、异常处理器的使用

    11.2.1、创建异常处理器类

    11.2.2、让程序抛出异常

    11.2.3、运行程序,测试

    11.3、项目异常处理方案

    11.3.1、异常分类

    11.3.2、异常解决方案

    11.3.3、异常解决方案的具体实现

    11.3.4、小结:


    11、异常处理器

    11.1、异常处理器简单入门

    11.1.1、基于配置的异常处理

    SpringMVC提供了一个处理器控制器方法执行过程中所出现的异常的接口:HandlerExceptionResolver

    HandlerExceptionResolver接口的实现类有:DefaultHandlerExceptionResolver和SimpleMappingExceptionResolver

    SpringMVC提供了自定义的异常处理器SimpleMappingExceptionResolver,使用方式:

    1. <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
    2. <property name="exceptionMappings">
    3. <props>
    4. <prop key="java.lang.ArithmeticException">errorprop>
    5. props>
    6. property>
    7. <property name="exceptionAttribute" value="ex">property>
    8. bean>

    11.1.2、基于注解的异常处理

    1. //@ControllerAdvice将当前类标识为异常处理的组件
    2. @ControllerAdvice
    3. public class ExceptionController {
    4. //@ExceptionHandler用于设置所标识方法处理的异常
    5. @ExceptionHandler(ArithmeticException.class)
    6. //ex表示当前请求处理中出现的异常对象
    7. public String handleArithmeticException(Exception ex, Model model){
    8. model.addAttribute("ex", ex);
    9. return "error";
    10. }
    11. }

    11.2、异常处理器的使用

    11.2.1、创建异常处理器类

    1. //@RestControllerAdvice用于标识当前类为REST风格对应的异常处理器
    2. @RestControllerAdvice
    3. public class ProjectExceptionAdvice {
    4. //除了自定义的异常处理器,保留对Exception类型的异常处理,用于处理非预期的异常
    5. @ExceptionHandler(Exception.class)
    6. public void doException(Exception ex){
    7. System.out.println("嘿嘿,异常你哪里跑!")
    8. }
    9. }

     确保SpringMvcConfig能够扫描到异常处理器类

    11.2.2、让程序抛出异常

    1. @GetMapping("/{id}")
    2. public Result getById(@PathVariable Integer id) {
    3. //出现数学异常
    4. int i = 1/0;
    5. Book book = bookService.getById(id);
    6. Integer code = book != null ? Code.GET_OK : Code.GET_ERR;
    7. String msg = book != null ? "" : "数据查询失败,请重试!";
    8. return new Result(code,book,msg);
    9. }

    11.2.3、运行程序,测试

    修改异常处理器类返回结果给前端

    1. //@RestControllerAdvice用于标识当前类为REST风格对应的异常处理器
    2. @RestControllerAdvice
    3. public class ProjectExceptionAdvice {
    4. //除了自定义的异常处理器,保留对Exception类型的异常处理,用于处理非预期的异常
    5. @ExceptionHandler(Exception.class)
    6. public Result doException(Exception ex){
    7. System.out.println("嘿嘿,异常你哪里跑!")
    8. return new Result(666,null,"嘿嘿,异常你哪里跑!");
    9. }
    10. }

    使用Postman测试:

     至此,就算后台执行的过程中抛出异常,最终也能按照我们和前端约定好的格式返回给前端。

    知识点1:@RestControllerAdvice

    名称:@RestControllerAdvice

    类型:类注解

    位置:Rest风格开发的控制器增强类定义上方

    作用:为Rest风格开发的控制器类做曾强

    说明:此注解自带@ResponseBody注解、@ControllerAdvice@Component注解,具备对应的功能

    知识点2:@ExceptionHandler

    名称:@ExeptionHandler

    类型:方法注解

    位置:专用于异常处理的控制器方法上方

    作用:设置指定异常的处理方案,功能等同于控制器方法,出现异常后终止原始控制器执行,并转入当前方法执行

    说明:此类方法可以根据处理的异常不同,制作多个方法分别处理对应的异常

    11.3、项目异常处理方案

    11.3.1、异常分类

    1、业务异常(BusinessException):

    1.1、规范的用户行为产生的异常、

    用户在页面输入内容的时候为按照指定的格式进行数据的填写(数字写为字符串)

    1.2、不规范的用户行为操作产生的异常

    用户故意传递错误的数据

    2、系统异常(SystemException)

    项目运行过程中可预计但无法避免的异常(数据库或服务器宕机)

    3、其他异常(Exception)

    编程人员未预计到的异常(用到的文件不存在)

    将异常分类后,针对不同类型的异常,要提供具体的解决方案

    11.3.2、异常解决方案

    1、业务异常(BusinessException)

    发送对应的消息传递给用户,提醒规范操作,常见的就是提示用户名已存在或者密码格式不正确

    2、系统异常(SystemException)

    步骤1:发送固定的消息传递给用户,安抚用户(系统繁忙,请稍后再试;系统正在维护升级,请稍后再试;系统出现问题,请联系系统管理员等)

    步骤2:发送特定消息给运维成员,提醒维护(可以发送短信、邮箱或者是公司内部通信软件)

    步骤3:记录日志(发消息和记录日志对用户来说是不可见的,属于后台程序)

    3、其他异常(Exception)

    步骤1:发送固定的消息给用户,安抚用户

    步骤2:发送特定的消息给编程人员,提醒维护(纳入预期范围内,一般是程序员没有考虑全,比如未做非空校验等)

    步骤3:记录日志:

    11.3.3、异常解决方案的具体实现

    思路:

    1、先通过自定义异常,完成BusinessException和SystemException的定义

    2、将其他异常包装成自定义异常类型

    3、在异常处理器类中对不同的异常进行处理

    步骤1:自定义异常处理器

    1. //自定义异常处理器,用于封装异常信息,对异常进行分类
    2. public class SystemException extends RuntimeException{
    3. private Integer code;
    4. public Integer getCode() {
    5. return code;
    6. }
    7. public void setCode(Integer code) {
    8. this.code = code;
    9. }
    10. public SystemException(Integer code, String message) {
    11. super(message);
    12. this.code = code;
    13. }
    14. public SystemException(Integer code, String message, Throwable cause) {
    15. super(message, cause);
    16. this.code = code;
    17. }
    18. }
    19. //自定义异常处理器,用于封装异常信息,对异常进行分类
    20. public class BusinessException extends RuntimeException{
    21. private Integer code;
    22. public Integer getCode() {
    23. return code;
    24. }
    25. public void setCode(Integer code) {
    26. this.code = code;
    27. }
    28. public BusinessException(Integer code, String message) {
    29. super(message);
    30. this.code = code;
    31. }
    32. public BusinessException(Integer code, String message, Throwable cause) {
    33. super(message, cause);
    34. this.code = code;
    35. }
    36. }

    说明:

    让自定义异常类继承RuntimeException的好处是,后期在抛出这两个异常的时候,就不用在try...catch...或throws了

    自定义异常类中添加code属性的原因是为了更好的区分异常时来自哪个业务的

    步骤2:将其他异常包成自定义异常

    具体的包装方式有:

    方式一:try{}catch(){}在catch中重新定义throw我们的自定义异常即可

    方式二:直接throw自定义异常即可

    1. public Book getById(Integer id) {
    2. //模拟业务异常,包装成自定义异常
    3. if(id == 1){
    4. throw new BusinessException(Code.BUSINESS_ERR,"请不要使用你的技术挑战我的耐性!");
    5. }
    6. //模拟系统异常,将可能出现的异常进行包装,转换成自定义异常
    7. try{
    8. int i = 1/0;
    9. }catch (Exception e){
    10. throw new SystemException(Code.SYSTEM_TIMEOUT_ERR,"服务器访问超时,请重试!",e);
    11. }
    12. return bookDao.getById(id);
    13. }

    上面为了使code更专业,我们在Code类中在新增需要的属性

    1. //状态码
    2. public class Code {
    3. public static final Integer SAVE_OK = 20011;
    4. public static final Integer DELETE_OK = 20021;
    5. public static final Integer UPDATE_OK = 20031;
    6. public static final Integer GET_OK = 20041;
    7. public static final Integer SAVE_ERR = 20010;
    8. public static final Integer DELETE_ERR = 20020;
    9. public static final Integer UPDATE_ERR = 20030;
    10. public static final Integer GET_ERR = 20040;
    11. public static final Integer SYSTEM_ERR = 50001;
    12. public static final Integer SYSTEM_TIMEOUT_ERR = 50002;
    13. public static final Integer SYSTEM_UNKNOW_ERR = 59999;
    14. public static final Integer BUSINESS_ERR = 60002;
    15. }

     步骤3:处理器中处理自定义异常

    1. //@RestControllerAdvice用于标识当前类为REST风格对应的异常处理器
    2. @RestControllerAdvice
    3. public class ProjectExceptionAdvice {
    4. //@ExceptionHandler用于设置当前处理器类对应的异常类型
    5. @ExceptionHandler(SystemException.class)
    6. public Result doSystemException(SystemException ex){
    7. //记录日志
    8. //发送消息给运维
    9. //发送邮件给开发人员,ex对象发送给开发人员
    10. return new Result(ex.getCode(),null,ex.getMessage());
    11. }
    12. @ExceptionHandler(BusinessException.class)
    13. public Result doBusinessException(BusinessException ex){
    14. return new Result(ex.getCode(),null,ex.getMessage());
    15. }
    16. //除了自定义的异常处理器,保留对Exception类型的异常处理,用于处理非预期的异常
    17. @ExceptionHandler(Exception.class)
    18. public Result doOtherException(Exception ex){
    19. //记录日志
    20. //发送消息给运维
    21. //发送邮件给开发人员,ex对象发送给开发人员
    22. return new Result(Code.SYSTEM_UNKNOW_ERR,null,"系统繁忙,请稍后再试!");
    23. }
    24. }

     步骤4:测试

    如果传入的参数为1,会报BusinessException

    如果传入其他参数,会报SystemException

     

     对于异常我们就已经处理完成了,不管后台哪一层抛出异常,都会以我们与前端约定好的方式进行返回,前端只需要把信息获取到,根据返回的正确与否来展示不同的内容即可。

    11.3.4、小结:

    以后项目中的异常处理方式为:

     

  • 相关阅读:
    【Ubuntu搭建MQTT Broker及面板+发布消息、订阅主题】
    安安静静地一天!
    Xmake v2.7.3 发布,包组件和 C++ 模块增量构建支持
    用Java实现贪吃蛇小游戏
    解释Java中的反射API
    C Primer Plus(6) 中文版 第14章 结构和其他数据形式 14.5 嵌套结构
    IIR滤波器的设计与实现(内含设计IIR滤波器的高效方法)
    UI自动化测试单例实现报错:AttributeError: ‘NoneType‘ object has no attribute ‘get_driver‘
    selenium 自动化测试
    windows系统下如何删除带有两点的文件夹
  • 原文地址:https://blog.csdn.net/qq_46061535/article/details/127604593