SpringBoot项目实战:自定义异常和统一参数验证(附源码)

你好,我是田哥

在实际开发过程中,不可避免的是需要处理各种异常,异常处理方法随处可见,所以代码中就会出现大量的try {...} catch {...} finally {...} 代码块,不仅会造成大量的冗余代码,而且还影响代码的可读性,所以对异常统一处理非常有必要。为此,我们定义了一个统一的异常类BusinessException

自定义异常和统一校验参数已用于 充电桩项目 中。

自定义异常

/**
 * @author tianwc  公众号:java后端技术全栈、面试专栏
 * @version 1.0.0
 * @date 2023年06月11日 22:41
 * 博客地址:<a href="http://woaijava.cc/">博客地址</a>
 * <p>
 * 自定义异常
 */
@Getter
public class BusinessException extends RuntimeException {
    /**
     * http状态码
     */
    private int code;

    private Object object;

    public BusinessException(String message, int code, Object object) {
        super(message);
        this.code = code;
        this.object = object;
    }

    public BusinessException(ResultCode resultCode) {
        this.code = resultCode.getCode();
        this.object = resultCode.getMessage();
    }

    public BusinessException(ResultCode resultCode, String message) {
        this.code = resultCode.getCode();
        this.object = message;
    }

    public BusinessException(String message) {
        super(message);
    }
}

一些常见需要对参数进校验,项目中自定义了一个校验工具类ParamValidate

public class ParamValidate {

    public static void isNull(Object object, String message) {
        if (object == null) {
            throw new BusinessException(ResultCode.PARAMETER_EMPTY, message);
        }
    }

    public static void isTrue(boolean expression, String message) {
        if (!expression) {
            throw new BusinessException(ResultCode.PARAMETER_ERROR, message);
        }
    }

    public static void notEmpty(Collection collection, String message) {
        isNull(collection, message);
        if (collection.size() == 0) {
            throw new BusinessException(ResultCode.PARAMETER_ERROR, message);
        }
    }
}

工具使用:

@RestController
@RequestMapping("/test")
public class TestController {

    @Resource
    private MessageTemplateSingleton messageTemplateSingleton;

    @GetMapping("/index1")
    public CommonResult<MessageTemplateSingleton.Template> index() {
        ParamValidate.isNull(null, "参数为空");
        MessageTemplateSingleton.Template template = messageTemplateSingleton.getTemplate(1);
        return CommonResult.success(template);
    }
}

自定义异常统一处理:

@RestControllerAdvice
@Slf4j
public class ChargeStationAdvice {

    @ExceptionHandler(Exception.class)
    public CommonResult<String> doException(Exception e) {

        log.error("统一处理自定义异常机制,触发异常 msg ", e);
        String message = null;
        int errorCode = ResultCode.FAILED.getCode();
        //自定义异常
        if (e instanceof BusinessException) {
            BusinessException exception = (BusinessException) e;
            message = exception.getMessage();
            errorCode = exception.getCode();
        } else if (e instanceof HttpRequestMethodNotSupportedException) {
            message = "不支持GET/POST方法";
        } else if (e instanceof NoHandlerFoundException) {
            message = "请求接口不存在";
        }  else{
             message = "系统异常";
        }
        return CommonResult.failed(errorCode, message);
    }
}

测试:

GET http://localhost:9001/test/index1

返回:

{
  "code": 400007,
  "message": null,
  "data": null
}

6f5d67d9bcd831da45c3da7676e29e80.png

到此我们的自定义异常的定义、处理、测试就搞定了。

但是,我们在上面使用到的是统一异常处理,我们在方法参数验证时候,也会用到统一异常处理。

统一参数验证

我们后台使用spring 为我们提供好的统一校验的工具spring-boot-starter-validation对请求进行校验。

pom依赖:

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

这里通过注解封装了几种常用的校验

  • @NotNull 不能为null

  • @NotEmpty 不能为null、空字符串、空集合

  • @NotBlank 不能为null、空字符串、纯空格的字符串

  • @Min 数字最小值不能小于x

  • @Max 数字最大值不能大于x

  • @Email 字符串为邮件格式

  • @Max 数字最大值不能大于x

  • @Size 字符串长度最小为x、集合长度最小为x

  • @Pattern 正则表达式

因为校验不通过时,会抛出各种异常,所以,我们需要对这些异常进行统一处理。

@RestControllerAdvice
@Slf4j
public class ChargeStationAdvice {

    @ExceptionHandler(Exception.class)
    public CommonResult<String> doException(Exception e) {

        log.error("统一异常处理机制,触发异常 msg ", e);
        String message = null;
        int errorCode = ResultCode.FAILED.getCode();
        //自定义异常
        if (e instanceof BusinessException) {
            BusinessException exception = (BusinessException) e;
            message = exception.getMessage();
            errorCode = exception.getCode();
        } else if (e instanceof HttpRequestMethodNotSupportedException) {
            message = "不支持GET/POST方法";
        } else if (e instanceof NoHandlerFoundException) {
            message = "请求接口不存在";
        } else if (e instanceof MissingServletRequestParameterException) {
            errorCode = ResultCode.PARAMETER_EMPTY.getCode();
            message = String.format("缺少必要参数[%s]", ((MissingServletRequestParameterException) e).getParameterName());
        } else if (e instanceof MethodArgumentNotValidException) {
            BindingResult result = ((MethodArgumentNotValidException) e).getBindingResult();
            FieldError error = result.getFieldError();
            errorCode = ResultCode.PARAMETER_EMPTY.getCode();
            message = error == null ? ResultCode.PARAMETER_ERROR.getMessage() : error.getDefaultMessage();
        } else if (e instanceof BindException) {
            errorCode = ResultCode.PARAMETER_EMPTY.getCode();
            message = e.getMessage();
        } else if (e instanceof ConstraintViolationException) {
            Optional<ConstraintViolation<?>> first = ((ConstraintViolationException) e).getConstraintViolations().stream().findFirst();
            errorCode = ResultCode.PARAMETER_EMPTY.getCode();
            message = first.get().getMessage();
        }
        return CommonResult.failed(errorCode, message);
    }
}

上面几个异常进行解释说明:

MissingServletRequestParameterException :加了@RequestParam注解,但是接口调用时没有传指定的参数(注意:是没有传,而不是传了,但是值是null)。

MethodArgumentNotValidException :经过测试,当校验的参数放在对象中,接口的请求方式是post请求,用@Valid @RequestBody方式接受参数时,如果报错,会被该捕获器捕获。

BindException :经过测试,当校验参数写在类中,接口请求方式是get请求时,报错会被该捕获器捕获。

ConstraintViolationException :传了值,但是不符合要求。@NotNull(message = “最大值不能为空”) @Min(value = 10,message = "参数必须大于10"),要求传非null值,且值必须大于10,否则会返回错误信息。经过测试,当校验参数直接写在接口上,而不是写在类中,报错会被该捕获器捕获。

参数校验实体类:

import javax.validation.constraints.Min;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.io.Serializable;

/**
 * @author tianwc  公众号:java后端技术全栈、面试专栏
 * @version 1.0.0
 * @date 2023年05月09日 20:03
 * 博客地址:<a href="http://woaijava.cc/">博客地址</a>
 */
@Data
public class TestDto implements Serializable {
    @NotNull
    @Min(value = 10,message = "参数必须大于10")
    private Long id;
    @NotEmpty(message = "name参数不能为空")
    private String name;
}

注意:每个注解对应的包路径。

我们在Controller层使用TestDto,并使用@Valid注解,使校验的注解生效:

@Slf4j
@RestController
@RequestMapping("/test")
public class TestController {

    @Resource
    private MessageTemplateSingleton messageTemplateSingleton; 

    @PostMapping("/index2")
    public CommonResult<MessageTemplateSingleton.Template> index2(@RequestBody @Valid TestDto testDto) {
        log.info("入参={}", testDto);
        MessageTemplateSingleton.Template template = messageTemplateSingleton.getTemplate(1);
        return CommonResult.success(template);
    }
}

注意:注解 @Valid 的全路径为:javax.validation.Valid;

测试:

POST http://localhost:9001/test/index2

Content-Type: application/json; charset=UTF-8

{   "id": 11,   "name": "" }

返回:

{
  "code": 400007,
  "message": "name参数不能为空",
  "data": null
}

到此,我们统一参数校验也搞定了。

关于“充电桩项目”相关文章:

a6b24d7a4e3974036470a7958d757ef1.png

52a5201148a4845f883e6024a45004ed.png

分布式微服务项目实战:充电桩项目

手把手项目实战,搞完,直接写在简历上!

好了,今天就分享这么多。

如果有需要简历修改、简历优化、简历包装、面试辅导、模拟面试、技术辅导、技术支持等,欢迎加我微x(tj20120622)。

个人技术博客可刷题:http://woaijava.cc/

回复77 ,获取《面试小抄2.0版》

回复电子书,获取后端必读的200本电子书籍

文章推荐

中厂,面试就问了4道题,凉了!

分布式问题,你知道几个?

应届生,实力已超6年,太卷了!

手把手教你写简历,包装、优化!

面试不问java,问MySQL,如何破局?

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

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

相关文章

母婴商家怎么建立自己的品牌,母婴产品传播渠道总结

随着互联网的发展逐渐深入我们的生活&#xff0c;线上传播的模式也越来越被大家熟知。越来越多的行业开始重视线上传播。那么母婴商家怎么建立自己的品牌&#xff0c;母婴产品传播渠道总结。 其实&#xff0c;母婴产品线上用户群体众多&#xff0c;且母婴产品用户目的明确&…

深入解析IT专业分类、方向及就业前景:高考毕业生如何选择适合自己的IT专业?重点探索近年来人工智能专业发展及人才需求

目录 一、IT专业的就业前景和发展趋势二、了解IT专业的分类和方向三、你对本专业的看法和感想四、本专业对人能力素养的要求五、建议和思考其它资料下载 当今社会&#xff0c;信息技术行业以其迅猛的发展和无限的潜力成为了吸引无数年轻人的热门选择。特别是对于高考毕业生来说…

你的企业还没搭建这个帮助中心网页,那你太落后了!

作为现代企业&#xff0c;拥有一个完善的帮助中心网页已经成为了不可或缺的一部分。帮助中心网页不仅可以提供给用户有关产品或服务的详细信息&#xff0c;还可以解答用户的疑问和提供技术支持&#xff0c;使用户在使用产品或服务时遇到问题可以很快地得到解决。因此&#xff0…

论文阅读和分析:Binary CorNET Accelerator for HR Estimation From Wrist-PPG

主要贡献&#xff1a; 一种完全二值化网络(bCorNET)拓扑结构及其相应的算法-架构映射和高效实现。对CorNET进行量化后&#xff0c;减少计算量&#xff0c;又能实现减轻运动伪影的效果。 该框架在22个IEEE SPC受试者上的MAE为6.675.49 bpm。该设计采用ST65 nm技术框架&#xff…

数据结构--队列2--双端队列--java双端队列

介绍 双端队列&#xff0c;和前面学的队列和栈的区别在于双端队列2端都可以进行增删&#xff0c;其他2个都是只能一端可以增/删。 实现 链表 因为2端都需要可以操作所以我们使用双向链表 我们也需要一共头节点 所以节点设置 static class Node<E>{E value;Node<E…

jetpack compose —— Card

jetpack compose Card 组件提供了一种简单而强大的方式来呈现卡片式的用户界面。 一、什么是 Card 组件 二、基本用法 三、属性和修饰符 四、嵌套使用和复杂布局 一、什么是 Card 组件 Card 是 Jetpack Compose 中的一个常用组件&#xff0c;用于呈现卡片式的用户界面。它…

Javaweb学习路线(3)——SpringBoot入门、HTTP协议与Tomcat服务器

一、SpringBoot入门 &#xff08;一&#xff09;第一个Springboot案例 1、创建Springboot工程&#xff0c;添加依赖。 2、定义类&#xff0c;添加方法并添加注释 3、运行测试。 pom.xml&#xff08;框架自动生成&#xff09; <?xml version"1.0" encoding&quo…

不同等级的Pads工程师,薪资差距有多大?

作为一种广泛应用在PCB设计的EDA工具&#xff0c;Pads软件在中国的电子设计行业中有着重要地位&#xff0c;尤其是不同等级的Pads工程师&#xff0c;在薪资、工作范围等有很大的差异&#xff0c;本文将从中国出发&#xff0c;多方面分析对比不同等级的Pads工程师&#xff0c;希…

24个Jvm面试题总结及答案

1.什么是Java虚拟机&#xff1f;为什么Java被称作是“平台无关的编程语言”&#xff1f; Java虚拟机是一个可以执行Java字节码的虚拟机进程。Java源文件被编译成能被Java虚拟机执行的字节码文件。 Java被设计成允许应用程序可以运行在任意的平台&#xff0c;而不需要程序员为每…

【VMware】虚拟机安装centos7

目录 一、创建虚拟机 1、自定义 2、选择需要安装的操作系统 3、选择虚拟机安装位置 4、选择处理器配置&#xff08;可先默认&#xff09; 5、设置虚拟内存&#xff08;一般4096&#xff09; 6、选择网络连接方式 7、选择I/O控制器 8、选择磁盘类型 9、选择磁盘 10、指定磁盘容…

国内云服务器全面对比

想要领取优惠券购买云服务可以前往我的云服务器领券购买。 经过疫情三年&#xff0c;大多行业开始复苏&#xff0c;企业开始布局以后得发展&#xff0c;云服务器作为企业发展几乎是必须的&#xff0c;一个企业从无到有&#xff0c;要经历很多&#xff0c;比如企业官网搭建&…

解密混沌工程——混沌工程价值

在数字化转型、十四五规划的大背景 下&#xff0c;大规模上云、分布式的核心改造等“云化”逐渐走进企业。 但是&#xff0c;云化的发展&#xff0c;使企业系统的复杂度呈指数级增长&#xff0c;故障越来越多。 企业在数字化转型中拥抱云计算、 信创国产化、分布式核心等新技…

DVWA-Command Injection

大约 命令注入攻击的目的是在易受攻击的应用程序中注入和执行攻击者指定的命令。 在这种情况下&#xff0c;执行不需要的系统命令的应用程序就像一个伪系统外壳&#xff0c;攻击者可能会使用它 作为任何授权的系统用户。但是&#xff0c;命令的执行权限和环境与 Web 服务具有的…

JVM 调优分析 如何进行JVM调优

文章目录 1.为什么需要进行JVM调优&#xff1f;2.什么情况下可能需要JVM调优3.JVM调优参数4.JVM调优参数设置参考5.JVM内部结构1. 类加载器&#xff08;Class Loader&#xff09;2. 运行时数据区&#xff08;Runtime Data Area&#xff09;3. 垃圾收集器&#xff08;Garbage Co…

jmeter如何将上一个请求的结果作为下一个请求的参数

目录 1、简介 2、用途 3、下载、简单应用 4、如何将上一个请求的结果作为下一个请求的参数 1、简介 在JMeter中&#xff0c;可以通过使用变量来将上一个请求的结果作为下一个请求的参数传递。 ApacheJMeter是Apache组织开发的基于Java的压力测试工具。用于对软件做压力测…

adb shell 调试 Android 串口 百度AI也很

在 Android 平台上进行串口调试需要使用 Android Debug Bridge (ADB) 工具。ADB 是一个命令行工具&#xff0c;可以通过 USB 连接 Android 设备&#xff0c;并执行各种命令来调试应用程序。 以下是使用 ADB shell 进行 Android 串口调试的步骤&#xff1a; 连接 Android 设备…

低代码开发平台介绍

低代码开发平台近两年发展迅猛&#xff0c;并迅速渗透到各个细分领域。本文简要介绍低代码开发的概念以及特性&#xff0c;并结合低代码开发的应用场景介绍两个低代码开发平台。 1、低代码开发概念 1.1 低代码开发介绍 低代码开发&#xff08;Low-code Development&#xff0…

3D格式转换工具HOOPS Exchange​助力Zuken打造电子设计自动化产品

行业&#xff1a;电子制造 挑战&#xff1a;对制造商来说&#xff0c;电子设计变得越来越复杂 - 电气和机械设计的融合需要将二维和三维数据结合起来 - 需要提供对多种不同CAD格式的支持 解决方案&#xff1a;HOOPS Exchange是用于快速、准确的CAD数据转换的领先SDK&#xff…

vue Electron ArcGis 桌面应用 Sqllite3 node-grp:老旧项目的起死回生

最近接收了一个三四年前做的项目。主要技术栈就是vue2electronsqllite3node-gyp。看到这个技术栈&#xff0c;基本可以知道感知这个项目的关键词&#xff1a;vue、Gis地图、本地数据库、桌面客户端。顿时深感亚历山大。 不多说&#xff0c;开干。 第一步&#xff0c;查看项目…

商家必备!餐饮外卖回评话术

我认识过很多做餐饮外卖的商家&#xff0c;他们总是有相同苦恼的问题&#xff0c;尤其是回复食客们的评价&#xff0c;尤其是差评。小编在这里就为各位商家提供了一些餐饮外卖回评的话术&#xff0c;希望能给有需要的小伙伴们提供帮助哦~ 一、好评回复模板 1.叮~您的好评我们已…