springboot怎么返回404_深度分析:SpringBoot异常捕获与封装处理,看完你学会了吗?...

4ac284dd3746d36312d39edbbf17cfd4.png

简介

日常开发过程中,难免有的程序会因为某些原因抛出异常,而这些异常一般都是利用try ,catch的方式处理异常或者throw,throws的方式抛出异常不管。这种方法对于程序员来说处理也比较麻烦,对客户来说也不太友好,所以我们希望既能方便程序员编写代码,不用过多的自己去处理各种异常编写重复的代码又能提升用户的体验,这时候全局异常处理就显得很重要也很便捷了,是一种不错的选择。

全网独家Spring/Cloud/MVC/Boot,脑图+面试+进阶,就问你服不服?​zhuanlan.zhihu.com
379aac3243c13901b64a113867f25152.png

一、 全局异常捕获与处理

Springboot对于异常的处理做了不错的支持,它提供了两个可用的注解。

@ControllerAdvice:用来开启全局的异常捕获

@ExceptionHandler:说明捕获哪些异常,对哪些异常进行处理。

@ControllerAdvice
public class MyExceptionHandler {@ExceptionHandler(value =Exception.class)public String exceptionHandler(Exception e){System.out.println("发生了一个异常"+e);return e.getMessage();}
}

上面这段代码的意思是,只要是代码运行过程中有异常就会进行捕获,并输出出这个异常。然后我们随便编写一个会发生异常的代码,测试出来的异常是这样的。

d43d1928cd5cfb33baeb6c3035ae06d5.png

这对于前后端分离来说并不好,前后端分离之后唯一的交互就是json了,我们也希望将后端的异常变成json返回给前端处理,所以就需要统一结果返回和统一异常处理。

二、统一结果返回与统一异常

Result类:封装返回结果。

public class Result<T> {private Integer code;//状态码private String message;//提示消息private T data;//数据public Result() {}/*** @param code 响应码* @param message 响应信息*/public Result(Integer code, String message) {this.code = code;this.message = message;}/*** @param code 响应码* @param message 响应信息* @param data 数据*/public Result(Integer code, String message, T data) {this.code = code;this.message = message;this.data = data;}/*** @param resultEnum 自定义枚举类,包含 code 和 message*/public Result(ResultEnum resultEnum) {this.code = resultEnum.getCode();this.message = resultEnum.getMessage();}/*** @param resultEnum 自定义枚举类,包含 code 和 message* @param data 数据*/public Result(ResultEnum resultEnum, T data) {this.code = resultEnum.getCode();this.message = resultEnum.getMessage();this.data = data;}/*** 自定义异常返回的结果* @param definitionException 自定义异常处理类* @return 返回自定义异常*/public static Result<Object> defineError(DefinitionException definitionException) {return new Result<>(definitionException.getErrorCode(), definitionException.getErrorMessage());}/*** 其他异常处理方法返回的结果* @param resultEnum 自定义枚举类,包含 code 和 message* @return 返回其他异常*/public static Result<Object> otherError(ResultEnum resultEnum) {return new Result<>(resultEnum);}//这里写get和set方法
}

注意:其中省略了get,set方法。

ResultEnum:自定义枚举类。

public enum ResultEnum {// 数据操作定义SUCCESS(200, "成功"),TIME_OUT(130, "访问超时"),NO_PERMISSION(403, "拒绝访问"),NO_AUTH(401, "未经授权访问"),NOT_FOUND(404, "无法找到资源"),METHOD_NOT_ALLOWED(405, "不支持当前请求方法"),SERVER_ERROR(500, " 服务器运行异常"),NOT_PARAM(10001, "参数不能为空"),NOT_EXIST_USER_OR_ERROR_PASSWORD(10002, "该用户不存在或密码错误"),NOT_PARAM_USER_OR_ERROR_PASSWORD(10003, "用户名或密码为空");;/*** 响应码*/private final Integer code;/*** 响应信息*/private final String message;/*** 有参构造* @param code  响应码* @param message 响应信息*/ResultEnum(Integer code, String message) {this.code = code;this.message = message;}public Integer getCode() {return code;}public String getMessage() {return message;}
}

注意:枚举类中定义了常见的错误码以及错误的提示信息。这里我们就定义好了统一的结果返回,其中里面的静态方法是用来当程序异常的时候转换成异常返回规定的格式。

DefinitionException:自定义异常处理类。

//@ControllerAdvice+@ResponseBody,开启全局的异常捕获,返回JSON
@RestControllerAdvice 
public class GlobalExceptionHandler {/*** 处理自定义异常* @return Result* @ExceptionHandler 说明捕获哪些异常,对那些异常进行处理。*/@ExceptionHandler(value = DefinitionException.class)public Result<Object> customExceptionHandler(DefinitionException e) {return Result.defineError(e);}/*** 处理其他异常* @return Result*/@ExceptionHandler(value = Exception.class)public Result<Object> exceptionHandler(Exception e) {return Result.otherError(ErrorEnum.INTERNAL_SERVER_ERROR);}
}

说明:将对象解析成json,是为了方便前后端的交互。

三、代码测试与结果

测试类

ResultController:测试的controller类

@RestController
public class ResultController {//获取学生信息@GetMapping("/student")public Result<Student> getStudent() {Student student = new Student();student.setId(1);student.setAge(18);student.setName("XuWwei")return new Result<>(ResultEnum.SUCCESS, student);}//自定义异常处理@RequestMapping("/getDeException")public Result<Object> DeException() {throw new DefinitionException(400, "我出错了");}//其他异常处理@RequestMapping("/getException")public Result Exception(){Result result = new Result();int a=1/0;return result;}

Student:学生类

public class Student {/*** 唯一标识id*/private Integer id;/*** 姓名*/private String name;/*** 年龄*/private Integer age;
}

注意:其中省略了get,set方法。

测试结果

启动项目,一个一个测试

  1. 正常测试

6487fb9f891a86a740d7f90d1febc956.png

可以看到数据是正常返回json,没有异常。

  1. 自定义异常

eb1b3a219eb10d06ae0412dc0558ae59.png

可以看到这个自定义的异常被捕获到了,并且返回了一个json。

  1. 其他异常

4ba61124a6dade205e173242981328ba.png

可以看到这个异常被捕获到了,并且返回了一个json。

注意:这种方法是不能处理404异常的,捕获不到。

四、404异常特殊处理

1、修改配置文件

​ 默认情况下,SpringBoot是不会抛出404异常的,所以**@ControllerAdvice**也不能捕获到404异常。我们可以通过配置文件来让这个注解能捕获到404异常,在application.properties中添加以下配置:

#当发现404异常时直接抛出异常
spring.mvc.throw-exception-if-no-handler-found=true
#关闭默认的静态资源路径映射,这样404不会跳转到默认的页面
spring.resources.add-mappings=false

但是关闭默认的静态资源路径映射会让静态资源访问出现问题,也就是不适合前后端一体的情况。

但是我们可以手动配置静态资源路径映射,就能正常访问静态资源了。

@Configuration
public class ResourceConfig implements WebMvcConfigurer {@Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {//可以访问localhost:8080/static/images/image.jpgregistry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");}
}

2、修改error跳转路径

​ 关闭默认的静态资源路径映射显然不太合理,可能会导致其他的错误发生,所以也可以通过修改默认错误页面的跳转路径来达到我们的目的。

在GlobalExceptionHandler类中添加NotFoundExceptionHandler类,这个类继承了ErrorController,可以重写error的跳转路径

//处理404NotFoundException
@Controller
class NotFoundExceptionHandler implements ErrorController {//设置错误页面路径@Overridepublic String getErrorPath() {return "/error";}//当访问error路径时,返回一个封装的异常的Json@RequestMapping("/error")@ResponseBodypublic Result<Object> error() {return Result.otherError(ResultEnum.NOT_FOUND);}
}

五、拓展异常类

​ GlobalExceptionHandler的exceptionHandler方法将所有的异常统一返回500系统错误,这不符合我们的设想,所以我们可以通过判断异常的类型,来返回不同的值。

将exceptionHandler改成以下代码:

/*** 处理其他异常* @return Result*/
@ExceptionHandler(value = Exception.class)
public Result<Object> exceptionHandler(Exception e) {if (e instanceof NullPointerException){//捕获空指针异常return Result.otherError(ResultEnum.NOT_PARAM);}else if (e instanceof IllegalAccessException){//非法访问异常return Result.otherError(ResultEnum.NO_PERMISSION);} else{return Result.otherError(ResultEnum.SERVER_ERROR);}
}

注意:更多异常可以通过else if来细分。

六、总结

​springboot的异常处理,需要通过@ControllerAdvice注解以及 @ExceptionHandler注解,来拦截所有的异常,并通过一个封装返回值返回。但是,这两个注解无法捕获404NotFound异常,因为SpringBoot默认是不会抛出404异常的,所以要通过继承ErrorController来修改404异常的跳转路径,达到捕获404异常的目的。

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

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

相关文章

新生成长记;关于zzulioj1056,幸运数字

刚刚接触代码的我&#xff0c;对计算机愈来愈好奇&#xff0c;开学的两个月&#xff0c;几乎没看书只顾着做题&#xff0c;当然&#xff0c;不会就百度&#xff0c;或者看大佬的博客&#xff0c;这些都是好东西&#xff0c;实在看不懂的&#xff0c;就拿着跑去问学长&#xff0…

获取form表单_【第1535期】前端 Form 的表单的一个通用解决方案

前言今日早读文章由阿里布达投稿分享。布达&#xff0c;Alibaba Fusion项目组的。花名潕量。主要专注在设计系统、组件、可视化搭建这个领域正文从这开始&#xff5e;&#xff5e;Fusion Next - Form 表单解决方案前端的Form 表单主要用于解决数据获取、数据校验、数据赋值 这三…

react取消捕获_React学习笔记(三)

React学习笔记&#xff08;三&#xff09;&#xff0c;组件的生命周期React中组件也有生命周期&#xff0c;也就是说也有很多钩子函数供我们使用, 组件的生命周期&#xff0c;我们会分为四个阶段&#xff0c;初始化、运行中、销毁、错误处理(16.3之后)初始化在组件初始化阶段会…

快捷键_AutoCAD 2021中的默认快捷键、新建或编辑快捷键

文&#xff1a;CAD钟日铭。欢迎关注和点赞支持。在使用AutoCAD进行制图的过程中&#xff0c;掌握一些快捷键会提高操作效率。所谓的快捷键是指用于启动命令的键组合。例如&#xff0c;按CtrlN组合键(快捷键)新建图形文件&#xff0c;按 CtrlO组合键可打开图形文件&#xff0c;按…

出现画面抖动_连续抖动20小时!虎门大桥桥面如波浪翻滚,专家:个人感觉没问题...

前两天(5月5日)&#xff0c;虎门大桥桥面出现如波浪翻滚的起伏&#xff0c;引发广泛的关注&#xff1a;次日&#xff0c;广东交通集团通报&#xff0c;虎门大桥震动是涡振现象&#xff0c;悬索桥结构安全。专家初步判断此次涡振和桥上设置水马有关。但直到6日早上11时&#xff…

安全模式 提权_记一次渗透挖洞提权实战

摘要&#xff1a;这是一次挖掘cms通用漏洞时发现的网站&#xff0c;技术含量虽然不是很高&#xff0c;但是也拿出来和大家分享一下吧&#xff0c;希望能给一部分人带来收获。0x01 进入后台在通过googlehack语法挖掘beescms时发现了这个站点利用网上的payload&#xff0c;在/mx_…

win7无法连接打印机拒绝访问_“Windows无法连接打印机,操作失败,错误为0x000003e3”...

请求大家帮助&#xff0c;昨天在共享打印机时出现“Windows无法连接打印机&#xff0c;操作失败&#xff0c;错误为0x000003e3”。在百度百科查询的资料修改了都不行(在不重装系统前提下&#xff0c;联想台式机都是win732位系统)&#xff0c;给大家一一列举&#xff0c;请求广大…

类型全部为string_python小讲堂丨学了这么久的,这6种基本数据类型你真的理解了吗...

哈喽&#xff0c;大家好&#xff0c;欢迎来到python小讲堂&#xff0c;间歇性的努力&#xff0c;会导致持续性的一事无成&#xff0c;即使今天是除夕&#xff0c;我们也不能懈怠啊&#xff0c;今天我给大家带来的是关于python的6种基本数据类型的深入讲解&#xff0c;话不多说让…

防抖 节流_【前端面试】节流与防抖

我们用两张图表示什么是节流和防抖。防抖节流由图可见&#xff0c;防抖的意思是&#xff0c;当用户在一段时间内连续频繁的试图执行一个函数的时候&#xff0c;只有最后一次&#xff0c;函数被真正的执行。节流的意思是&#xff0c;当用户在某一个时刻执行了一次函数的时候&…

没数据时y轴不显示_Matplotlib数据可视化

1.Matplotlib介绍什么是MatplotlibMatplotlib是一个Python的绘图库&#xff0c;它可与 NumPy 一起使用&#xff0c;可以代替MMatplotlib安装由于Matplotlib是第三方库&#xff0c;所以我们需要安装它才可以使用。注意&#xff0c;Matplotlib3.0要求python3版本才可安装使用。安…

循环划线_经济内外双循环下的思考!

原创&#xff1a;群赢说到这个内外双循环&#xff0c;我们汽车后市场朋友们&#xff0c;应该知道车子发动机水冷系统就是一个双循环&#xff0c;内部小循环&#xff0c;外部大循环。在发动机温度不高的时候&#xff0c;水在做小循环&#xff0c;在发动机周边流动。当发动机温度…

计算机组成原理实验软件仿真系统_计算机系统组成原理(基础)

网上关于计算机系统的讨论众说纷纭。刚开始&#xff0c;我卯足了劲想寻找一个标准答案&#xff0c;后来发现这并不存在&#xff01;因为计算机系统层次不一&#xff0c;看你从什么角度来理解这个问题。在这篇文章里&#xff0c;我的介绍一切从简&#xff0c;不求锦上添花&#…

1110: 最近共同祖先(函数专题)

1110: 最近共同祖先&#xff08;函数专题&#xff09; 时间限制: 1 Sec 内存限制: 128 MB 提交: 3818 解决: 3290 [提交] [状态] [讨论版] [命题人:admin] 题目描述 如上图所示&#xff0c;由正整数1, 2, 3, …组成了一棵无限大的二叉树。从某一个结点到根结 点&#xff08;编…

echart freemarker 模板_SpringBoot集成Freemarker模板生成Echarts图片(三)

紧接着前面两篇&#xff0c;本篇采用Freemarker模板来生成Echarts图片。一. 项目结构二. Freemarker模板(1)柱状图{"title": {"text": "${title}","textStyle": {"color": "red","fontSize": 15,"…

ios 系统提示框_ios13终于能屏蔽系统更新了!附详细教程

很多人会遇到这样的烦恼&#xff0c;ios频繁更新&#xff0c;自己用惯了当前系统版本&#xff0c;系统总提示新的更新请求&#xff0c;不小心点到之后&#xff0c;系统就会自动更新安装&#xff0c;有很多小伙伴更新后&#xff0c;手机变卡顿&#xff0c;耗电量加大&#xff0c…

判断是否有小数_一线老师笔记:数学判断题拿高分的技巧

01什么是判断题&#xff1f;判断是关于对象和它属性有所肯定或者否定的思维形式。在研究数学中&#xff0c;经常要对现实世界的空间形式和数量关系&#xff0c;作出肯定或者否定的回答&#xff0c;因而要大量使用判断&#xff0c;并把一些正确的判断作为进一步研究问题的依据。…

mysql 导入 sqlite_Mysql 数据导入SQlite

SQlite 有一个很强大的管理工具名字叫做Sqlite Developer (官方网站)。在Sqlite Developer中有关于数据导入的强大功能。可以将MSSQL Oracl Aeecss等等数据库导入到Mysql中。但是&#xff0c;默认在Win7环境中没有Mysql的倒入方式。你需要一个叫做“Mysql ODBC”的win客户端工具…

centos 安装mysql 5.7.9_CentOS 6.6下RPM方式安装MySQL 5.7.9

说明&#xff1a;从MySQL5.7.4起&#xff0c;以RPM包的方式安装后的MySQL的部署&#xff0c;默认是安全的&#xff0c;并且有这些特点&#xff1a;1. 在大多数情况下&#xff0c;你只需要安装MySQL-server和MySQL-client安装包就可以安装上一个标准功能的MySQL。对于一个标准安…

mongodb 导入 mysql_将mongodb 数据指定字段导出,然后指定字段导入mysql 实例 及相关问题解决...

需求&#xff1a;将mongodb 数据指定字段导出&#xff0c;然后再指定字段导入mysql 表中直接上图吧&#xff0c;最后 会将遇到几个问题及解决方案贴出&#xff0c;以便遇到类似问题可以迅速解决(期间所用命令具体用法不在本文详解之内)将mongodb 数据指定字段导出&#xff0c;…

mysql外部排序_深入浅出MySQL优先队列(你一定会踩到的order by limit 问题)

0.先抛问题假设字段category无索引且有重复值&#xff0c;order by category 和 limit 组合使用的结果会和预期不符。问题复现&#xff1a;表结构(就是两个字段)CREATE TABLE ratings (id int(11) NOT NULL AUTO_INCREMENT,category int(11) DEFAULT NULL,PRIMARY KEY (id)) EN…