7、SpringBoot统一异常处理-01

01、分析

  • 统一跳转:/error 这是一种全局的机制
  • 配置类:补充状态进行跳转 – 局部的机制
  • 自定义页面的方式,方便我们可以把error.html随心所欲的进行存放

问题:

  • 其实给开发增大的工作量,
  • 不明确具体异常信息,如果要追求细粒度的控制。
  • 内部定义的状态 HttpStatus.状态枚举,是一个大方向的错误指定
    • 比如:INTERNAL_SERVER_ERROR 它是服务器只要任何方法执行报任何异常Exception 都会是500。这就会给开发者带来困扰,给用户一个错误就够了。对开发者来说就不够细粒度,因为未来程序的开发大部分是一种前后端分离的开发方式,如果不给接口调用者,具体的错误信息提示的话,可能会造成很多的沟通成本,开发的时间成本。
    • 在开发中越具体的错误捕获对于开发者来说排除错误是非常有利的。

举例:

比如开发用户注册的接口:

比如:用户名不为空,密码格式不对

  • 不友好的统一返回:{status:500,msg:"未知错误”}
  • 友好的统一返回:{status:501,msg:"用户名不为空"} {status:502,msg:"密码格式不对"}

02、异常规则

  • 具体异常优先级要高于大异常。

  • 在try/catch的具体异常一定写在大异常上面

     try {
                Connection con = null;
                PreparedStatement preparedStatement = con.prepareStatement("");
            }catch (SQLException sqlex){
                sqlex.printStackTrace();
            } catch(Exception exx){
    
            }
    

03、springboot如何做到细粒度自定异常返回呢?

01、用@ControllerAdvice

package com.kuangstudy.web.error.config2;

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;

import javax.servlet.http.HttpServletRequest;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

/**
 * Description:
 * Author: yandi Administrator
 * Version: 1.0
 * Create Date Time: 2021/12/15 22:37.
 * Update Date Time:
 *
 * @see
 */
@ControllerAdvice
public class GlobalExceptionControllerHandler {

    /**
     * 拦截所有程序异常
     * @param request
     * @param ex
     * @return
     */
    @ExceptionHandler(value=Exception.class)
    public String errorHandler(HttpServletRequest request,Exception ex){
        return "err2/noError";
    }

    /**
     * SQLException异常
     * @param request
     * @param ex
     * @return
     */
    @ExceptionHandler(value=SQLException.class)
    public String errorHandlerSQL(HttpServletRequest request,Exception ex){
        return "err2/sqlError";
    }

    /**
     * MyException异常
     * @param request
     * @param ex
     * @return
     */
    @ExceptionHandler(value=MyException.class)
    public String errorHandlerMy(HttpServletRequest request,Exception ex){
        return "err2/myError";
    }

}

@ControllerAdvice 和 @RestControllerAdvice底层原理是:AOP 主要用于开启全局异常处理一种机制,对后面的统一返回,统一异常处理,统一参数注入都会用这个@ControllerAdvice。

02、@RestControllerAdvice

有了@ControllerAdvice 为什么还出现@RestControllerAdvice,其实和@Controller和@RestController一个道理。因为在程序开发中,不仅仅只有页面返回处理。如果单体项目,有freemarker 和 thymeleaf的话其实使用@ControllerAdvice做统一异常处理能够满足错误处理机制。

如果在有freemarker 和 thymeleaf的使用@RestControllerAdvice 会怎么样呢?

package com.kuangstudy.web.error.config2;

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.servlet.http.HttpServletRequest;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

/**
 * Description:
 * Author: yykk Administrator
 * Version: 1.0
 * Create Date Time: 2021/12/15 22:37.
 * Update Date Time:
 *
 * @see
 */
//@ControllerAdvice
@RestControllerAdvice
public class GlobalExceptionControllerHandler {

    /**
     * 拦截所有程序异常
     * @param request
     * @param ex
     * @return
     */
    @ExceptionHandler(value=Exception.class)
    @ResponseBody
    public String errorHandler(HttpServletRequest request,Exception ex){
        return "err2/noError";
    }

    /**
     * SQLException异常
     * @param request
     * @param ex
     * @return
     */
    @ExceptionHandler(value=SQLException.class)
    @ResponseBody
    public String errorHandlerSQL(HttpServletRequest request,Exception ex){
        return "err2/sqlError";
    }

    /**
     * MyException异常
     * @param request
     * @param ex
     * @return
     */
    @ExceptionHandler(value=MyException.class)
    @ResponseBody
    public String errorHandlerMy(HttpServletRequest request,Exception ex){
        return "err2/myError";
    }

}

@ControllerAdvice 和 @RestControllerAdvice的区别:

  • 通过上面的分析,得出结论@ControllerAdvice根据你的返回值找页面。@RestControllerAdvice直接把方法的内容输出
  • 其实和@Controller和@RestController是一个含义。所以我们把统一异常处理的类GlobalExceptionControllerHandler当做Controller去对待就对了。它只不过是一个特殊的Controller 就出现异常以后就交给这个特殊GlobalExceptionControllerHandler来处理。

04、开发中我到底使用那种会更好呢?

  • 如果是前后端分离的方式,只能使用@RestControllerAdvice。为什么:因为前后端分离压根就没有freemarker或者 thymeleaf,也就说没有页面,也没有静态资源。
  • 如果是单体项目存在freemarker或者 thymeleaf,你想跳页面给用户呈现你就使用:@ControllerAdvice 如果你想返回状态和具体信息:你就使用@RestControllerAdvice

01、@ControllerAdvice + 页面跳转方式呈现具体细粒度错误信息在页面

package com.kuangstudy.web.error.config2;

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

/**
 * Description:
 * Author: yykk Administrator
 * Version: 1.0
 * Create Date Time: 2021/12/15 22:37.
 * Update Date Time:
 *
 * @see
 */
@ControllerAdvice
//@RestControllerAdvice
public class GlobalExceptionControllerHandler {

    /**
     * 拦截所有程序异常
     * @param request
     * @param ex
     * @return
     */
    @ExceptionHandler(value=Exception.class)
    public ModelAndView errorHandler(HttpServletRequest request, Exception ex ){
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("err2/noError");
        modelAndView.addObject("status", HttpStatus.INTERNAL_SERVER_ERROR);
        modelAndView.addObject("msg",ex.getMessage());
        modelAndView.addObject("url",request.getRequestURL().toString());
        return modelAndView;
    }

    /**
     * SQLException异常
     * @param request
     * @param ex
     * @return
     */
    @ExceptionHandler(value=SQLException.class)
    public String errorHandlerSQL(HttpServletRequest request,Exception ex){
        return "err2/sqlError";
    }

    /**
     * MyException异常
     * @param request
     * @param ex
     * @return
     */
    @ExceptionHandler(value=MyException.class)
    @ResponseBody
    public String errorHandlerMy(HttpServletRequest request,Exception ex){
        return "err2/myError";
    }

}

02、@RestControllerAdvice 返回json错误信息给用户和开发者

package com.kuangstudy.web.error.config2;

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

/**
 * Description:
 * Author: yandi Administrator
 * Version: 1.0
 * Create Date Time: 2021/12/15 22:37.
 * Update Date Time:
 *
 * @see
 */
@RestControllerAdvice
public class GlobalExceptionControllerHandler {

    /**
     * 拦截所有程序异常
     * @param request
     * @param ex
     * @return
     */
    @ExceptionHandler(value=Exception.class)
    public Map<String,Object> errorHandler(HttpServletRequest request, Exception ex ){
        Map<String,Object> map = new HashMap<>();
        map.put("status",HttpStatus.INTERNAL_SERVER_ERROR);
        map.put("msg",ex.getMessage());
        map.put("url",request.getRequestURL().toString());
        return map;
    }

    /**
     * SQLException异常
     * @param request
     * @param ex
     * @return
     */
    @ExceptionHandler(value=SQLException.class)
    public Map<String,Object> errorHandlerSQL(HttpServletRequest request,Exception ex){
        Map<String,Object> map = new HashMap<>();
        map.put("status",601);
        map.put("msg",ex.getMessage());
        map.put("url",request.getRequestURL().toString());
        return map;
    }

    /**
     * MyException异常
     * @param request
     * @param ex
     * @return
     */
    @ExceptionHandler(value=MyException.class)
    @ResponseBody
    public Map<String,Object> errorHandlerMy(HttpServletRequest request,Exception ex){
        Map<String,Object> map = new HashMap<>();
        map.put("status",602);
        map.put("msg",ex.getMessage());
        map.put("url",request.getRequestURL().toString());
        return map;
    }

}

  • 使用@RestControllerAdvice,它的返回值建议在是String和ModelAndView ,如果你返回ModelAndView就会指定setViewName页面的源码通过fm和th渲染以后返回。如果String直接返回字符串,对于用户和开发者来说,没有意义。特别用户者看不懂,对开发者信息不方便解析。

05、统一返回为什么是R类,而不是Map或者Object

原因如:

  • Map不具备面向对象的特征
  • Object 不明确类型。
  • 建议自己去定义一个统一返回来处理统一异常。

命名方式:

  • R
  • ResponseResult
  • ApiResponse
  • Result

无论用那种,都是一种面向封装的思想。

06、总结

理解:全局异常处理就很像另外一个controller,由异常去触发

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
项目详细功能参考项目演示内容即可项目优势:1、项目从零开始到完结 附带视频,源码以及相关辅助资料,适合学习使用,项目也可拿来即用。2、几乎全手写代码,功能流程详细 跟着可以独立完成,附带详细代码相关常见bug 和 调试解决方案,让大家学会跟踪快速解决问题。3、系统后端使用LayUI技术,对页面不精通的小伙伴也可以快速完成精美页面的设计及应用,支持统一后台管理,也可拿来做其他项目通用后台4、针对layui 相关技术点薄弱的学员提供相关技术点学习,让快速上手完成项目研发5、选材来自生活,项目真实感强,可用学习使用和就业面试使用,适合作为面试中提高实际项目经验...6、该项目前后端分离,满足前沿技术点..项目技术栈:- 数据库:MySQL8.0- 后端技术:SpringBoot,MyBatisPlus,JWT 等- 日志技术:Log4j- 数据库连接池:druid- 前端技术:LayUI, axios,Echarts,Ztree 等- Web容器:Apache Tomcat 9- 项目管理工具:Maven3.6- 思维导图设计工具:XMIND 8- 开发工具: IDEA2020, WebStorm2020- 数据库设计软件:Power Designer16.5特别提示:1、涉及相关技术点学习,更多侧重大学生或无项目经验以及项目经验较少的学员入门到项目完结项目实战2、项目中功能处理大多提供多种解决方式,如跨域访问,更多让大家了解解决方式的同时学会技术点应用3、加入bug的调试以及代码跟踪处理,更好的让学员更多学会如何解决问题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值