异常统一处理实现

异常处理

4.6.1 异常问题分析

在service方法中有很多的参数合法性校验,当参数不合法则抛出异常,下边我们测试下异常处理。

请求创建课程基本信息,故意将必填项设置为空。

测试发现报500异常,如下:

http://localhost:63040/content/courseHTTP/1.1 500 
Content-Type: application/json
Transfer-Encoding: chunked
Date: Wed, 07 Sep 2022 11:40:29 GMT
Connection: close{"timestamp": "2022-09-07T11:40:29.677+00:00","status": 500,"error": "Internal Server Error","message": "","path": "/content/course"
}

问题:并没有输出我们抛出异常时指定的异常信息。

所以,现在我们的需求是当正常操作时按接口要求返回数据,当非正常流程时要获取异常信息进行记录,并提示给用户。

异常处理除了输出在日志中,还需要提示给用户,前端和后端需要作一些约定:

1、错误提示信息统一以json格式返回给前端。

2、以HTTP状态码决定当前是否出错,非200为操作异常。

如何规范异常信息?

代码中统一抛出项目的自定义异常类型,这样可以统一去捕获这一类或几类的异常。

规范了异常类型就可以去获取异常信息。

如果捕获了非项目自定义的异常类型统一向用户提示“执行过程异常,请重试”的错误信息。

如何捕获异常?

代码统一用try/catch方式去捕获代码比较臃肿,可以通过SpringMVC提供的控制器增强类统一由一个类去完成异常的捕获。

如下图:

4.6.2 统一异常处理实现

根据上边分析的方案,统一在base基础工程实现统一异常处理,各模块依赖了base基础工程都 可以使用。

首先在base基础工程添加需要依赖的包:

<dependency><groupId>org.springframework</groupId><artifactId>spring-web</artifactId>
</dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>

1、定义一些通用的异常信息

package com.xuecheng.base.execption;/*** @description 通用错误信息* @author Mr.M* @date 2022/9/6 11:29* @version 1.0*/
public enum CommonError {UNKOWN_ERROR("执行过程异常,请重试。"),PARAMS_ERROR("非法参数"),OBJECT_NULL("对象为空"),QUERY_NULL("查询结果为空"),REQUEST_NULL("请求参数为空");private String errMessage;public String getErrMessage() {return errMessage;}private CommonError( String errMessage) {this.errMessage = errMessage;}}

2、自定义异常类型

package com.xuecheng.base.execption;/*** @description 学成在线项目异常类* @author Mr.M* @date 2022/9/6 11:29* @version 1.0*/
public class XueChengPlusException extends RuntimeException {private static final long serialVersionUID = 5565760508056698922L;private String errMessage;public XueChengPlusException() {super();}public XueChengPlusException(String errMessage) {super(errMessage);this.errMessage = errMessage;}public String getErrMessage() {return errMessage;}public static void cast(CommonError commonError){throw new XueChengPlusException(commonError.getErrMessage());}public static void cast(String errMessage){throw new XueChengPlusException(errMessage);}}

3、响应用户的统一类型

package com.xuecheng.base.execption;import java.io.Serializable;/*** 错误响应参数包装*/
public class RestErrorResponse implements Serializable {private String errMessage;public RestErrorResponse(String errMessage){this.errMessage= errMessage;}public String getErrMessage() {return errMessage;}public void setErrMessage(String errMessage) {this.errMessage = errMessage;}
}

4、全局异常处理器

从 Spring 3.0 - Spring 3.2 版本之间,对 Spring 架构和 SpringMVC 的Controller 的异常捕获提供了相应的异常处理。

  • @ExceptionHandler
    Spring3.0提供的标识在方法上或类上的注解,用来表明方法的处理异常类型。
  • @ControllerAdvice
    Spring3.2提供的新注解,从名字上可以看出大体意思是控制器增强, 在项目中来增强SpringMVC中的Controller。通常和 @ExceptionHandler 结合使用,来处理SpringMVC的异常信息。
  • @ResponseStatus
    Spring3.0提供的标识在方法上或类上的注解,用状态代码和应返回的原因标记方法或异常类。
    调用处理程序方法时,状态代码将应用于HTTP响应。

通过上面的两个注解便可实现微服务端全局异常处理,具体代码如下:

@Slf4j@ControllerAdvice//控制器增强
public class GlobalExceptionHandler {//处理XueChengPlusException异常// 此类异常是程序员主动抛出的,可预知异常@ResponseBody//将信息返回为 json格式@ExceptionHandler(XueChengPlusException.class)//此方法捕获XueChengPlusException异常@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)//状态码返回500public RestErrorResponse doXueChengPlusException(XueChengPlusException e){log.error("捕获异常:{}",e.getErrMessage());e.printStackTrace();String errMessage = e.getErrMessage();//写异常处理的逻辑//....return new RestErrorResponse(errMessage);}//捕获不可预知异常 Exception@ResponseBody//将信息返回为 json格式@ExceptionHandler(Exception.class)//此方法捕获Exception异常@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)//状态码返回500public RestErrorResponse doException(Exception e){log.error("捕获异常:{}",e.getMessage());e.printStackTrace();if(e.getMessage().equals("不允许访问")){return new RestErrorResponse("没有操作此功能的权限");}return new RestErrorResponse(CommonError.UNKOWN_ERROR.getErrMessage());}@ResponseBody//将信息返回为 json格式@ExceptionHandler(MethodArgumentNotValidException.class)//此方法捕获MethodArgumentNotValidException异常@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)//状态码返回500public RestErrorResponse doMethodArgumentNotValidException(MethodArgumentNotValidException e){BindingResult bindingResult = e.getBindingResult();//校验的错误信息List<FieldError> fieldErrors = bindingResult.getFieldErrors();//收集错误StringBuffer errors = new StringBuffer();fieldErrors.forEach(error->{errors.append(error.getDefaultMessage()).append(",");});return new RestErrorResponse(errors.toString());}}

4.6.3 异常处理测试

在异常处理测试之前首先在代码中抛出自定义类型的异常,这里以新增课程的service方法为例进行代码修改。

 @Overridepublic CourseBaseInfoDto createCourseBase(Long companyId,AddCourseDto dto) {...
//合法性校验if (StringUtils.isBlank(dto.getName())) {throw new XueChengPlusException("课程名称为空");}if (StringUtils.isBlank(dto.getMt())) {throw new XueChengPlusException("课程分类为空");}if (StringUtils.isBlank(dto.getSt())) {throw new XueChengPlusException("课程分类为空");}if (StringUtils.isBlank(dto.getGrade())) {throw new XueChengPlusException("课程等级为空");}if (StringUtils.isBlank(dto.getTeachmode())) {throw new XueChengPlusException("教育模式为空");}if (StringUtils.isBlank(dto.getUsers())) {throw new XueChengPlusException("适应人群");}if (StringUtils.isBlank(dto.getCharge())) {throw new XueChengPlusException("收费规则为空");}。。。if ("201001".equals(charge)) {BigDecimal price = dto.getPrice();if (ObjectUtils.isEmpty(price)) {throw new XueChengPlusException("收费课程价格不能为空");}courseMarketNew.setPrice(dto.getPrice().floatValue());}。。。

1、首先使用httpclient测试

请求新增课程接口,故意将必填项设置为空。

测试结果与预期一致,可以捕获异常并响应异常信息,如下:

http://localhost:63040/content/courseHTTP/1.1 500 
Content-Type: application/json
Transfer-Encoding: chunked
Date: Wed, 07 Sep 2022 13:17:14 GMT
Connection: close{"errMessage": "处理异常,请重试。"
}

2、前后端调试

仍然测试新增课程接口,当课程收费的时候必须填写价格,这里设置课程为收费,价格设置为空。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-f3RhXU3C-1690971452584)()]

通过测试发现,前端正常提示代码 中抛出的异常信息。

至此,项目异常处理的测试完毕,我们在开发中对于业务分支中错误的情况要抛出项目自定义的异常类型。

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

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

相关文章

Vue3和typeScript路由传参

1 params传的参数&#xff0c;页面刷新就消失,而query传的参数&#xff0c;页面刷新还会存在&#xff0c;所以通常用query。 query传参 跳转页面&#xff1a;拿到router对象,调用push方法做跳转. import { useRoute,useRouter} from "vue-router"; export default…

iOS 搭建组件化私有库

一、创建私有库索引 步骤1是在没有索引库的情况下或者是新增索引的时候才需要用到&#xff08;创建基础组件库&#xff09; 首先在码云上建立一个私有库索引&#xff0c;起名为SYComponentSpec 二、本地添加私有库索引 添加私有库索引 pod repo add SYComponentSpec https:/…

Transformer 论文学习笔记

重新学习了一下&#xff0c;整理了一下笔记 论文&#xff1a;《Attention Is All You Need》 代码&#xff1a;http://nlp.seas.harvard.edu/annotated-transformer/ 地址&#xff1a;https://arxiv.org/abs/1706.03762v5 翻译&#xff1a;Transformer论文翻译 特点&#xff1…

ElasticSearch基础篇-Java API操作

ElasticSearch基础-Java API操作 演示代码 创建连接 POM依赖 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:sch…

33.利用abs 解决绝对值问题(matlab程序 )

1.简述 abs函数的功能是绝对值和复数的模 语法 Y abs(X) 说明 Y abs(X) 返回数组 X 中每个元素的绝对值。如果 X 是复数&#xff0c;则 abs(X) 返回复数的模。 示例 标量的绝对值 y abs(-5) y 5 向量的绝对值 创建实值的数值向量。 x [1.3 -3.56 8.23 -5 -0.01…

【POP3/IMAP/SMTP】QQ邮箱设置

什么是 POP3/IMAP/SMTP 服务 POP3 &#xff08;Post Office Protocol - Version 3&#xff09;协议用于支持使用电子邮件客户端获取并删除在服务器上的电子邮件。 IMAP &#xff08;Internet Message Access Protocol&#xff09;协议用于支持使用电子邮件客户端交互式存取服务…

二十三种设计模式第二十二篇--中介者模式

说到这个模式就有趣了&#xff0c;不知道大家在生活中喷到过中介没&#xff1f;其实中介这个词吧&#xff0c;我也说不上好还是坏&#xff0c;有时候他可以帮助人们更快的达到某个目的&#xff0c;但有的时候吧&#xff0c;这个有贼坑人&#xff0c;相信网络上有各种被中介坑的…

【力扣】822. 翻转卡片游戏

以下为力扣官方题解&#xff0c;及本人代码 822. 翻转卡片游戏 题目题意示例 1示例 2提示 官方题解哈希集算法总结复杂度 本人代码Java提交结果&#xff1a;通过 题目 题意 在桌子上有 n n n 张卡片&#xff0c;每张卡片的正面和背面都写着一个正数&#xff08;正面与背面上…

Java程序员面试题

Java程序员面试题目 1.Java基础1.1 Java有list&#xff0c;list有很多种&#xff0c;你平时开发喜欢用哪个list&#xff1f;&#xff08;容易&#xff09;1.2 Java的map&#xff0c;你知道有哪几种map&#xff0c;你平时喜欢用哪个&#xff1f;&#xff08;容易&#xff09; 2.…

空指针NPE原因之一:判断顺序错误

不管是&&或者|| 一般都是将null或非null放在第一个判断 在Java中&#xff0c;逻辑运算符&&和||具有短路特性。这意味着如果使用&&运算符&#xff0c;如果第一个条件为false&#xff0c;将不会执行第二个条件&#xff0c;因为整个表达式已经确定为fals…

【Python】模块学习之matplotlib柱状图、饼状图、动态图及解决中文显示问题

目录 前言 安装 pip安装 安装包安装 柱状图 主要方法 参数说明 示例代码 效果图 解决中文显示问题 修改后的图片 饼状图 主要方法 示例代码 效果图 动态图 主要方法 动态图官方使用介绍 示例代码 颜色设置 内建颜色 字体设置 资料获取方法 前言 众所周…

【Golang 接口自动化04】 解析接口返回JSON串

目录 前言 解析到结构体 json数据与struct字段是如何相匹配的呢&#xff1f; 解析到interface Go类型和JSON类型 实例代码 simpleJson 总结 资料获取方法 前言 上一次我们一起学习了如何解析接口返回的XML数据&#xff0c;这一次我们一起来学习JSON的解析方法。 JSO…

[驱动开发]gpio子系统及中断实现led亮灭

编写LED灯的驱动&#xff0c;使用GPIO子系统&#xff0c;里面添加按键的中断处理 1.应用程序发送指令控制发光二极管亮灭 2.按键1按下&#xff0c;led1电位反转&#xff1b;按键2按下&#xff0c;led2电位反转&#xff1b;按键3按下&#xff0c;led3电位反转 //头文件 #i…

PHP并发处理详解

在今天的网络世界中&#xff0c;高并发是一个无法避免的问题。随着用户的增加和业务的复杂性&#xff0c;我们的应用可能会面临大量的并发请求。这时&#xff0c;如果我们不能很好地处理并发&#xff0c;就可能会导致应用的性能下降&#xff0c;甚至崩溃。在很多情况下&#xf…

想做上位机,学C#还是QT?

学习C#还是Qt&#xff0c;取决于你的具体需求和偏好。 如果你计划开发跨平台的桌面应用程序&#xff0c;并且希望使用一种更轻量级、直观的界面框架&#xff0c;那么Qt可能是一个不错的选择。Qt是一个功能丰富且成熟的跨平台框架&#xff0c;支持多种开发语言&#xff08;包括…

flask用DBUtils实现数据库连接池

flask用DBUtils实现数据库连接池 在 Flask 中&#xff0c;DBUtils 是一种实现数据库连接池的方案。DBUtils 提供了持久性&#xff08;persistent&#xff09;和透明的&#xff08;transient&#xff09;两种连接池类型。 首先你需要安装 DBUtils 和你需要的数据库驱动。例如&…

springboot 入门

前提是已安装java环境&#xff0c;分为三部分 一、项目构建 二、项目组成 三、常用注解 Demo源码 spring-demo: springboot 入门项目 一、springboot-stater 使用IDEA快速构建springboot项目 1、新建项目 2、选择maven&#xff0c;在选择next 3、填写好项目信息 4、pom…

分布式应用:ELK企业级日志分析系统

目录 一、理论 1.ELK 2.ELK场景 3.完整日志系统基本特征 4.ELK 的工作原理 5.ELK集群准备 6.Elasticsearch部署&#xff08;在Node1、Node2节点上操作&#xff09; 7.Logstash 部署&#xff08;在 Apache 节点上操作&#xff09; 8.Kiabana 部署&#xff08;在 Node1 节点…

maven安装(windows)

环境 maven&#xff1a;Apache Maven 3.5.2 jdk环境&#xff1a;jdk 1.8.0_192 系统版本&#xff1a;win10 一、安装 apache官网下载需要的版本&#xff0c;然后解压缩&#xff0c;解压路径尽量不要有空格和中文 官网下载地址 https://maven.apache.org/download.cgihttps:…

SpringBoot基础认识

创建SpringBoot模块 首先需要引设置maven并引用maven环境 1.打开项目结构&#xff0c;new module&#xff0c;选择Spring Initializr&#xff0c;URL选默认&#xff1a; group填写分组如com.kdy &#xff0c; Artifact起个模块名如springboot_quickstart&#xff0c;Type选择M…