Springboot拦截器及统一异常处理

文章目录

  • 一、Java中异常相关概念
    • 1、异常类
    • 2、异常处理方法
    • 3、注意事项
    • 4、自定义异常
  • 二、配置全局异常处理
    • 1、统一返回体定义
    • 2、定义异常处理实现类
    • 3、全局异常处理类
  • 三、Springboot拦截器
    • 1、定义拦截器
    • 2、注册拦截器
  • 四、验证效果


一、Java中异常相关概念

1、异常类

  • Throwable类:Java中所有异常类的父类,它包含了最终要的两个类Exception和Error。
  • Error类:属于程序无法处理的错误,是JVM需要承担的,无法通过try-catch进行捕捉,例如系统崩溃、内存不足、堆栈溢出,编译器不会对这类异常进行检查,一旦发生就容易导致程序运行终止,仅靠程序本身无法恢复。
  • Exception:程序本身可以处理的异常,可以通过catch进行捕捉,也是我们需要处理的,以保证程序能够正常运行。

Exception又分为运行时异常(RunTimeException,又叫非受检查异常unchecked
Exception)和非运行时异常(又叫受检查异常checked Exception)。

运行时异常我们可处理可不处理,一般由程序逻辑错误引起,我们应该在编码时尽量避免这种错误,比如:NullPointException

非运行时异常时Exception中除RunTimeException以外的异常,比如:IOException、SQLException等以及我们自定义的Exception异常,这种异常,Java编译器会强制要求我们处理

@SneakyThrows注解:作用在方法上,加上以后可以对非运行时异常不进行处理

2、异常处理方法

  • try-catch:try中放可能发生异常的代码,如果发生异常,后面的代码不会再执行,直接进入catch,在catch中拿到异常对象,我们进行处理;
  • try-catch-finally:finally是无论异常是否发生都会执行的,通常用来释放资源;
  • try-finally:相当于没有捕捉异常;
  • throws:在方法名后面进行抛出,表明该方法对此异常不进行处理,由调用者进行处理,谁用谁处理,调用者也可继续向上抛出;
  • throw:在方法内进行抛出,我们手动抛出一个异常对象。

3、注意事项

  • 对于非运行时异常,程序必须进行处理,用try-catch或throws都可以,在写代码时idea会提示;
  • 对运行时异常,程序中没有处理,默认处理方法时throws;
  • 子类重写父类的方法时,对抛出异常的规定:子类重写的方法,所抛出的异常类型不能大 于父类异常的类型,可以是一样的类型或者是父类异常的子类。

4、自定义异常

自定义异常类继承Exception或RunTimeException,继承Exception属于非运行时异常,继承RunTimeException属于运行时异常。

二、配置全局异常处理

  在项目中我们通常会写很多接口,各种各样的异常出现会让我们的返回结果很受影响,因为我们的接口都会写通用的返回格式,但是异常出现时返回的错误就和我们的返回格式产生分歧,所以为了保证这种情况不出现,我们就需要配置全局异常处理,在异常发生时也按照我们想要的返回格式。

核心:@RestControllerAdvice+@ExceptionHandler

1、统一返回体定义

@Data
@NoArgsConstructor
public class R<T> implements Serializable {
    private static final long serialVersionUID = 1L;
    /**
     * 成功
     */
    public static final int SUCCESS = Constants.SUCCESS;
    /**
     * 失败
     */
    public static final int FAIL = Constants.FAIL;
    /**
     * 消息状态码
     */
    private int code;
    /**
     * 消息内容
     */
    private String msg;
    /**
     * 数据对象
     */
    private T data;

    public static <T> R<T> ok() {
        return restResult(null, SUCCESS, "操作成功");
    }

    public static <T> R<T> ok(T data) {
        return restResult(data, SUCCESS, "操作成功");
    }

    public static <T> R<T> ok(String msg) {
        return restResult(null, SUCCESS, msg);
    }

    public static <T> R<T> ok(String msg, T data) {
        return restResult(data, SUCCESS, msg);
    }

    public static <T> R<T> fail() {
        return restResult(null, FAIL, "操作失败");
    }

    public static <T> R<T> fail(String msg) {
        return restResult(null, FAIL, msg);
    }

    public static <T> R<T> fail(T data) {
        return restResult(data, FAIL, "操作失败");
    }

    public static <T> R<T> fail(String msg, T data) {
        return restResult(data, FAIL, msg);
    }

    public static <T> R<T> fail(int code, String msg) {
        return restResult(null, code, msg);
    }

    /**
     * 返回警告消息
     *
     * @param msg 返回内容
     * @return 警告消息
     */
    public static <T> R<T> warn(String msg) {
        return restResult(null, HttpStatus.WARN, msg);
    }

    /**
     * 返回警告消息
     *
     * @param msg 返回内容
     * @param data 数据对象
     * @return 警告消息
     */
    public static <T> R<T> warn(String msg, T data) {
        return restResult(data, HttpStatus.WARN, msg);
    }

    private static <T> R<T> restResult(T data, int code, String msg) {
        R<T> r = new R<>();
        r.setCode(code);
        r.setData(data);
        r.setMsg(msg);
        return r;
    }

    public static <T> Boolean isError(R<T> ret) {
        return !isSuccess(ret);
    }

    public static <T> Boolean isSuccess(R<T> ret) {
        return R.SUCCESS == ret.getCode();
    }
}

2、定义异常处理实现类

继承自RuntimeException类,只传进来一个状态码,如果想传更多的参数,就自己加上,代码中有示例。

@Data
public class MessageException extends RuntimeException{

    private int code;
    //private String desc;

    public MessageException(String message,int code/**,String desc*/) {
        super(message);
        this.code = code;
        //this.desc = desc;
    }
}

3、全局异常处理类

这里可以使用@RestControllerAdvice+@ExceptionHandler或者@ControllerAdvice+@ExceptionHandler+@ResponseBody,都是可以的,@RestControllerAdvice=@ControllerAdvice+@ResponseBody。

@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {

    @ExceptionHandler(MessageException.class)
    public R businessExceptionHandler(MessageException e){
        //log.error("MessageException "+e.getMessage(),e);
        return R.fail(e.getCode(),e.getMessage());
    }
}

三、Springboot拦截器

拦截器可以根据 URL 对请求进行拦截,主要应用于登陆校验、权限验证、乱码解决、性能监控和异常处理等功能。

1、定义拦截器

在 Spring Boot中定义拦截器十分的简单,只需要创建一个拦截器类,并实现 HandlerInterceptor 接口,重写以下三个方法。直接上代码。

public class MessageAccessInterceptor implements HandlerInterceptor {

    /**
     * 目标方法执行前 (Controller方法调用之前)
     * 该方法在控制器处理请求方法前执行,其返回值表示是否中断后续操作
     * 返回 true 表示继续向下执行,返回 false 表示中断后续操作
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
    	//注意这个businessKey,后面验证的时候要使用
        String businessKey = request.getHeader("businessKey");
        if (ObjectUtil.isEmpty(businessKey)) {
        	//直接使用上文中定义的异常处理方法
            throw new MessageException("业务签名未找到!", HttpStatus.FORBIDDEN);
        } 
        return true;
    }

    /**
     * 目标方法执行后
     * 该方法在控制器处理请求方法调用之后、解析视图之前执行
     * 可以通过此方法对请求域中的模型和视图做进一步修改
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView
        modelAndView) {
        //System.out.println("postHandle: " + request.getRequestURI());
    }

    /**
     * 页面渲染后
     * 该方法在视图渲染结束后执行
     * 可以通过此方法实现资源清理、记录日志信息等工作
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception
        ex) {
        //System.out.println("afterCompletion: " + request.getRequestURI());
    }

2、注册拦截器

创建一个实现了 WebMvcConfigurer 接口的配置类(使用了 @Configuration 注解的类),重写 addInterceptors() 方法,并在该方法中调用 registry.addInterceptor() 方法将自定义的拦截器注册到容器中。

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //addPathPatterns为拦截此请求路径的请求
        //excludePathPatterns为不拦截此路径的请求
        registry.addInterceptor(new MessageAccessInterceptor())
   			//可以设置多个路径拦截
           .addPathPatterns("/push/sms");
           //.excludePathPatterns();
    }
}

四、验证效果

如果header参数不传businessKey参数,提示信息正如咱上文中配置的那样。
在这里插入图片描述
如果header传输了businessKey参数,则会顺利通过拦截器。
成功的验证了本文的所有功能。如需源码,请评论区留下邮箱地址。
完毕!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/275585.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C语言—每日选择题—Day64

前言 两天没更新了&#xff0c;作者在复习期末考试&#xff0c;更新一波&#xff0c;祝大家都能顺利通过期末考试&#xff01;&#xff01;&#xff01; 指针相关博客 打响指针的第一枪&#xff1a;指针家族-CSDN博客 深入理解&#xff1a;指针变量的解引用 与 加法运算-CSDN博…

javaWebssh民宿管理系统myeclipse开发mysql数据库MVC模式java编程计算机网页设计

一、源码特点 java ssh民宿管理系统是一套完善的web设计系统&#xff08;系统采用ssh框架进行设计开发&#xff09;&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模 式开发。开发环境为TOMCAT7.0,My…

【高可用】使用Keepalived实现SFTP服务的高可用

使用Keepalived实现SFTP服务的高可用 背景 这个事情的背景是生产环境的数据采集流程时不时会出问题&#xff08;这个也是不可避免的&#xff09;&#xff0c;目前的处理手段是&#xff1a;所有的数据接口服务器&#xff08;也就是存放原始数据等待采集的服务器&#xff09;都…

完全背包问题,原理剖析,公式推导,OJ详解

文章目录 前言一、完全背包的状态设计1、状态设计2、状态转移方程3、对比0/1背包问题4、时间复杂度分析 二、完全背包问题的优化1、时间复杂度优化2、空间复杂度优化 三、OJ练习裸题完全背包离散化最小值 前言 完全背包问题&#xff0c;相比0/1背包问题&#xff0c;实就每个物品…

git unable to create temporary file: No space left on device(git报错)

1.问题 1.1 vscode中npm run serve跑项目的时候&#xff0c;进度达到95%的时候一直卡着无进度&#xff1b; 1.2 git命令提交代码报错&#xff1b; 2.具体解决 这个错误通常表示你的磁盘空间已经满了&#xff0c;导致 Git 无法在临时目录中创建文件。2.1 清理磁盘空间&#xf…

浅谈IDC数据中心机房低压配电系统的组成与设计

随着我国移动互联网技术的不断发展&#xff0c;海量的数据资源日益庞大&#xff0c;IDC数据中心存储着这些大量的数据信息&#xff0c;其蕴含着巨大的研究和商业价值&#xff0c;因此数据中心IT设备的运行应具有较高的可靠性和稳定性。数据中心供配电系统是为机房内所有需要动力…

身份自动化工作流,帮助您快速提高工作效率

从工业革命初期&#xff0c;自动化流水线生产以机械设备取代人力的方式&#xff0c;成功地使工人解脱了繁重的体力工作&#xff0c;极大地减少了因人为差错而引发的问题。然而&#xff0c;在现代企业管理中&#xff0c;许多管理人员仍处在繁琐的手动维护大量身份信息的机械操作…

Python 爬取 哔站视频弹幕 并实现词云图可视化

嗨喽&#xff0c;大家好呀~这里是爱看美女的茜茜呐 环境介绍: python 3.8 解释器 pycharm 编辑器 第三方模块: requests >>> pip install requests protobuf >>> pip install protobuf 如何安装python第三方模块: win R 输入 cmd 点击确定, 输入安装命…

软件测试面试(面试前一定要做的准备)

目录 一、问题预测 1. 让简单介绍下自己&#xff08;每次面试开场&#xff09; 2. 让说下自己会的内容 3. 看了哪些书籍&#xff08;有问到&#xff09; 4. 了解过哪些技术博客/论坛&#xff08;有问到&#xff09; 5. 是否了解软件测试需要掌握哪些知识&#xff08;问到…

【快速全面掌握 WAMPServer】03.玩转安装和升级

网管小贾 / sysadm.cc 大多数情况我们在了解和学习任何一款软件之前都会先去尝试一下软件的安装&#xff0c;毕竟只有安装好了软件&#xff0c;再通过使用它来进一步学习和掌握。 那么同样的道理&#xff0c;我们要学习和掌握如何动手搭建 PHP 的调试环境&#xff0c;那么作为…

千巡翼X4轻型无人机 赋能智慧矿山

千巡翼X4轻型无人机 赋能智慧矿山 传统的矿山测绘需要大量测绘员通过采用手持RTK、全站仪对被测区域进行外业工作&#xff0c;再通过方格网法、三角网法、断面法等进行计算&#xff0c;需要耗费大量人力和时间。随着无人机航测技术的不断发展&#xff0c;利用无人机作业可以大…

Jupyter Notebook 开启远程登录

Jupyter Notebook可以说是非常好用的小工具&#xff0c;但是不经过配置只能够在本机访问 安装jupyter notebook conda install jupyter notebook 生成默认配置文件 jupyter notebook --generate-config 将会在用户主目录下生成.jupyter文件夹&#xff0c;其中jupyter_noteb…

Vue ThreeJs实现银河系行星运动

预览 可通过右上角调整参数&#xff0c;进行光影练习 代码 <template><div id"body"></div> </template> <script>import * as THREE from three import { OrbitControls } from three/examples/jsm/controls/OrbitControls import …

(12)Linux 常见的三种进程状态

&#x1f4ad; 前言&#xff1a;本章我们专门讲解进程的状态。我们先学习具体的 Linux 系统状态&#xff0c;再去介绍 OS 学科面对的概念如何理解 —— 运行态、终止态、阻塞态以及挂起态。 进程状态&#xff08;Process Status&#xff09; 什么是进程状态&#xff1f; 进程…

深入浅出图解C#堆与栈 C# Heap(ing) VS Stack(ing) 第四节 参数传递对堆栈的影响 2

深入浅出图解C#堆与栈 C# Heaping VS Stacking 第四节 参数传递对堆栈的影响 2 [深入浅出图解C#堆与栈 C# Heap(ing) VS Stack(ing) 第一节 理解堆与栈](https://mp.csdn.net/mdeditor/101021023)[深入浅出图解C#堆与栈 C# Heap(ing) VS Stack(ing) 第二节 栈基本工作原理](htt…

蓝桥杯嵌入式ADC

1.ADC原理图 2.CubeMX配置 3.ADC相关代码

sheng的学习笔记-卷积神经网络

源自吴恩达的深度学习课程&#xff0c;仅用于笔记&#xff0c;便于自行复习 导论 1&#xff09;什么是卷积神经网络 卷积神经网络&#xff0c;也就是convolutional neural networks &#xff08;简称CNN&#xff09;&#xff0c;使用卷积算法的神经网络&#xff0c;常用于计…

Python从入门到熟练

文章目录 Python 环境Python 语法与使用基础语法数据类型注释数据类型介绍字符串列表元组集合字典 类型转换标识符运算符算数运算符赋值运算符复合运算符 字符串字符串拼接字符串格式化 判断语句bool 类型语法if 语句if else 语句if elif else 语句 循环语句while循环for 循环r…

2023年度业务风险报告:四个新风险趋势

目录 倒票的黄牛愈加疯狂 暴增的恶意网络爬虫 愈加猖獗的羊毛党 层出不穷的新风险 业务风险呈现四个趋势 防御云业务安全情报中心“2023年业务风险数据”统计显示&#xff0c;恶意爬虫风险最多&#xff0c;占总数的37.8%&#xff1b;其次是虚假账号注册&#xff0c;占18.79%&am…