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 表示中断后续操作*/@Overridepublic 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;}/*** 目标方法执行后* 该方法在控制器处理请求方法调用之后、解析视图之前执行* 可以通过此方法对请求域中的模型和视图做进一步修改*/@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndViewmodelAndView) {//System.out.println("postHandle: " + request.getRequestURI());}/*** 页面渲染后* 该方法在视图渲染结束后执行* 可以通过此方法实现资源清理、记录日志信息等工作*/@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exceptionex) {//System.out.println("afterCompletion: " + request.getRequestURI());}

2、注册拦截器

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

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

四、验证效果

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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Armpro脱壳软件搭建教程附源代码

PHP8.0版本&#xff0c;数据库8.0版本 1.配置注册机文件&#xff0c;打开将arm.zip/res目录下&#xff0c;mt管理器搜索将其全部修改为你自己的域名或者是服务器IP 2.然后建立数据库 数据库账号arm 数据库用户名arm 数据库密码EsZfXY4tD3h2NNA4 3.导入数据库 4.配置Redi…

[每周一更]-(第44期):GIT版本控制之忽略文件

基础概念 在 Git 中&#xff0c;可以通过 .gitignore 文件来指定不需要纳入版本控制的文件或文件夹&#xff0c;这些被忽略的文件或文件夹不会被提交到仓库中。 在项目根目录下创建一个名为 .gitignore 的文件&#xff0c;并在其中列出需要忽略的文件或文件夹。一些常见的示例…

SASS循环

<template><div><button class"btn type-1">默认按钮</button><button class"type-2">主要按钮</button><button class"type-3">成功按钮</button><button class"type-4">信息…

企业数据可视化-亿发数据化管理平台提供商,实现一站式数字化运营

近些年来&#xff0c;国内企业数据化管理升级进程持续加速&#xff0c;以物联网建设、人工智能、大数据和5G网络等新技术的发展&#xff0c;推动了数字经济的蓬勃发展&#xff0c;成为维持经济持续稳定增长的重要引擎。如今许多国内中小型企业纷纷摒弃传统管理模式&#xff0c;…

[卷积神经网络]FCOS--仅使用卷积的Anchor Free目标检测

项目源码&#xff1a; FCOShttps://github.com/tianzhi0549/FCOS/ 一、概述 作为一种Anchor Free的目标检测网络&#xff0c;FCOS并不依赖锚框&#xff0c;这点类似于YOLOx和CenterNet&#xff0c;但CenterNet的思路是寻找目标的中心点&#xff0c;而FCOS则是寻找每个像素点&…

css中sprite(css精灵)是什么,有什么优缺点

概念 将多个小图片拼接到一个图片中 。通过 background-position 和元素尺寸调节需要显示的背景图案。 优点 减少 HTTP 请求数&#xff0c;极大地提高页面加载速度 增加图片信息重复度&#xff0c;提高压缩比&#xff0c;减少图片大小 更换⻛格方便&#xff0c; 只需在一张或…

六、Redis 分布式系统

六、Redis 分布式系统 六、Redis 分布式系统6.1 数据分区算法6.1.1 顺序分区6.1.2 哈希分区 6.2 系统搭建与运行6.2.1 系统搭建6.2.2 系统启动与关闭 6.3 集群操作6.3.1 连接集群6.3.2 写入数据6.3.3 集群查询6.3.4 故障转移6.3.5 集群扩容6.3.6 集群收缩 6.4 分布式系统的限制…

mysql保姆安装教程

一.下载install文件 1.进入Mysql官网&#xff0c;点击下载 2.选择MySQL Installer for Windows 3.推荐选择第二个安装包 4.不登陆&#xff0c;开始下载 5.等待下载完成 二.安装前的配置 通过电脑“设置”&#xff0c;检查电脑是否包含中文名&#xff0c;如果包含请重命名 …

紫光展锐5G扬帆出海 | 东南亚成为5G新热土

东南亚是一块充满活力和潜力的市场&#xff0c;这里人口基数大、年轻消费群体占比高&#xff0c;电子市场在过去几年显著增长。 增速“狂飙”的东南亚手游 近年来&#xff0c;东南亚手游下载量逐年增长&#xff0c;2023 年第一季度下载量突破 21 亿次&#xff0c;贡献了全球近…

2023年12月27日学习记录_加入噪声

目录 1、今日计划学习内容2、今日学习内容1、add noise to audio clipssignal to noise ratio(SNR)加入 additive white gaussian noise(AWGN)加入 real world noises 2、使用kaggel上的一个小demo&#xff1a;CNN模型运行时出现的问题调整采样率时出现bug 3、明确90dB下能否声…

【SD】IP-Adapter 进阶 - 同款人物【2】

测试模型&#xff1a;###最爱的模型\flat2DAnimerge_v30_2.safetensors [b2c93e7a89] 原图&#xff1a; 加入 control1 [IP-Adapter] 加入 control 2 [OpenPose] 通过openpose骨骼图修改人物动作。 加入 control 3 lineart 加入cotrol3 …

Unity中Shader 齐次坐标

文章目录 前言一、什么是齐次坐标二、齐次坐标增加分量 w 的意义1、当 w ≠ \neq  0时&#xff1a;2、当 w 0时&#xff1a;3、用方程组&#xff0c;直观的看一下w的意义 前言 在之前的文章中&#xff0c;我们进行了正交相机视图空间转化到裁剪空间的推导。 Unity中Shade…

三大强势大语言模型怎么选?看这篇文章就够了!

现在的人可以有多懒&#xff1f;啊&#xff0c;不&#xff0c;是多聪明&#xff1f;&#xff08;毕竟人和动物的根本区别在于能否制造和使用工具。&#xff09; 遇到任何事情&#xff0c;可以随时大小问。你甚至都不需要手动输入&#xff0c;因为语言输入已经帮你简化了这个步…

linux调试笔记

文章目录 基本启动调试与附加进程断点程序运行控制tui模式查看堆栈与变量监视变量多线程调试 扩展自定义跳转命令解析自定义类型禁用动态库自动加载设置源码路径断点时执行命令gdbserver远程调试 gdb脚本QtCreator调试Linux下处理编译、运行时的一些问题undefined symbol问题-n…

Android ImageView如何使用.svg格式图片

我们知道imageview常用的图片格式是.jpg/.png或者drawable里的部分.xml文件。但有时UI会给过来.svg格式的文件&#xff0c;下面讲解如何使用.svg格式图片文件 step1:AS点击File -> New -> Vector Asset step2:选中要使用的.svg文件&#xff0c;按需要命名和调整&#x…

Mysql For Navicate (老韩)

Navicate创建数据库 先创建一个数据库;然后在数据库中创建一张表;在表格当中填入相应的属性字段;打开表, 然后填入相应的实例字段; – 使用数据库图形化App和使用指令来进行操作各有各的好处和利弊; 数据库的三层结构(破除MySQL神秘) 所谓安装Mysql数据库, 就是在主机安装一…

231227-9步在RHEL8.8配置本地yum源仓库

Seciton 1&#xff1a;参考视频 RHEL8配置本地yum源仓库-安徽迪浮_哔哩哔哩_bilibili Seciton 2&#xff1a;具体操作 &#x1f3af; 第1步&#xff1a;查看光驱文件/dev/sr0是否已经挂载&#xff1f;此处已挂在 [lgklocalhost ~]$ df -h &#x1f3af; 第1步&#xff1a;查看…

在处理金额时用long还是BigDecimal,所引发的讨论

亲爱的小伙伴们&#xff0c;由于微信公众号改版&#xff0c;打乱了发布时间&#xff0c;为了保证大家可以及时收到文章的推送&#xff0c;可以点击上方蓝字关注测试工程师成长之路&#xff0c;并设为星标就可以第一时间收到推送哦&#xff01; 周末在闲逛的时候 无意间看到一个…

Vue3数据交互axios

我是南城余&#xff01;阿里云开发者平台专家博士证书获得者&#xff01; 欢迎关注我的博客&#xff01;一同成长&#xff01; 一名从事运维开发的worker&#xff0c;记录分享学习。 专注于AI&#xff0c;运维开发&#xff0c;windows Linux 系统领域的分享&#xff01; 本…

自定义html5中日期选取器的样式

自定义html5中日期选取器的样式 1. 前言1.1 关于 h5 的新特性1.2 使用浏览器 2. html5中日期选取器默认样式3. 自定义日期样式3.1 简单定义3.2 花式样式定义 4. 改变日期格式5. 参考 1. 前言 1.1 关于 h5 的新特性 可看下面的文章 HTML5 新特性之HTML5 的输入&#xff08;inpu…