spring boot @Valid 与 @Validated 使用 及 统一异常处理

Spring Boot 2.x 参数校验实战:别再傻傻分不清 @Valid 和 @Validated 了 本文深入解析Spring Boot 2.x中@Valid与@Validated的区别与应用场景,帮助开发者正确使用参数校验机制。通过对比两者的核心特性、分组校验实现及自定义校验注解,提升RESTful API的数据完整性和业务逻辑正确性。结合JSR 380规范和实战案例,详细展示如何优化校验性能与统一异常处理。 阅读详情

spring boot @Valid 与 @Validated 使用 及 统一异常处理

1.@Valid使用
1.实体类添加验证规则

有多种校验规则

@Data
public class PaperDTO {
    /**
     * 试卷id
     */
    @NotNull(message = "必填字段不能为空")
    @JsonFormat(shape = JsonFormat.Shape.STRING)
    private Long id;
    /**
     * 试卷名
     */
    @NotNull(message = "必填字段不能为空")
    private String name;
    /**
     * 试卷类型
     */
    @NotNull(message = "必填字段不能为空")
    private Long paperType;
    /**
     * 试卷难度
     */
    @NotNull(message = "必填字段不能为空")
    private Long difficuty;
    /**
     * 总分
     */
    @NotNull(message = "必填字段不能为空")
    private BigDecimal score;
    //若需要嵌套校验则在需要校验的结构体上添加@Valid
    @Valid
    private List<User> users
}
2.在Controller层方法添加校验注解
@PostMapping("/addPaper")
public PaperDTO doAddPaper(@RequestBody @Valid PaperDTO paperDTO) {
    //处理传入数据
    return paperDTO;
}
2.@Validated 分组校验使用
1.添加分组的接口

IdGroup.class

public interface IdGroup {
}

AddGroup.class

public interface AddGroup {
}

UpdateGroup.class

public interface UpdateGroup {
}
2.需要校验结构体添加校验规则
@Data
public class PaperDTO {
    /**
     * 试卷id
     */
    @NotNull(groups = {IdGroup.class,UpdateGroup.class}, message = "必填字段不能为空")
    @JsonFormat(shape = JsonFormat.Shape.STRING)
    private Long id;
    /**
     * 试卷名
     */
    @NotNull(groups = {AddGroup.class,UpdateGroup.class}, message = "必填字段不能为空")
    private String name;
    /**
     * 试卷类型
     */
    @NotNull(groups = {AddGroup.class,UpdateGroup.class}, message = "必填字段不能为空")
    private Long paperType;
    /**
     * 试卷难度
     */
    @NotNull(groups = {AddGroup.class,UpdateGroup.class}, message = "必填字段不能为空")
    private Long difficuty;
    /**
     * 总分
     */
    @NotNull(groups = {AddGroup.class,UpdateGroup.class}, message = "必填字段不能为空")
    private BigDecimal score;
}
3.Controller层添加校验注解

这时,只会校验对应分组的校验规则

如果需要嵌套校验,同添加@Valid注解即可

//发布指定试卷
@PostMapping("publishPaper")
public Boolean doPublishPaper(@RequestBody @Validated(IdGroup.class) PaperDTO request) {
    //处理传入试卷id
    return response;
}
//添加试卷
@PostMapping("addPaper")
public Boolean doPublishPaper(@RequestBody @Validated(AddGroup.class) PaperDTO request) {
    //处理传入试卷
    return response;
}
//修改试卷
@PostMapping("updatePaper")
public Boolean doPublishPaper(@RequestBody @Validated(UpdateGroup.class) PaperDTO request) {
    //处理传入试卷
    return response;
}
3.@ControllerAdvice统一异常处理

这个统一异常处理定义的响应,需要CommonResponse 结构体,没有也无所谓,将错误信息按自己想要的结构体封装好返回也一样

统一异常类,最好继承RuntimeException,这样不用强制调用产生统一异常的方法每个都处理统一异常

public class PaperServiceException extends RuntimeException {
    /**
     * 异常码
     * */
    private final String code;
    /**
     * 异常发生时请求url
     * */
    private final String url;
    /**
     * 异常信息
     * */
    private final String message;
    public PaperServiceException(){
        this.code = "230000";
        this.message = "无信息异常";
        this.url = "";
    }

    public PaperServiceException(String code,String message){
        this.code = code;
        this.message = message;
        this.url = "";
    }

    public PaperServiceException(String code,String url,String message){
        this.code = code;
        this.message = message;
        this.url = url;
    }
    public String getUrl() {
        return url;
    }

    public String getCode() {
        return code;
    }


    @Override
    public String getMessage() {
        return message;
    }

    @Override
    public String toString() {
        return "PaperServiceException{" +
                "错误码(code)=" + code +
                ", 请求地址(url)='" + url + '\'' +
                ", 详细信息(message)='" + message + '\'' +
                '}';
    }
}

统一异常类型类

public class PaperServiceExceptionType {
    public static final String PUBLISH_ERROR = "230401";
    /**
     * 字段校验错误
     * */
    public static final String VALID_ERROR = "230001";
    /**
     * 数据初始化错误
     * */
    //........自定义各种错误类型码
    private PaperServiceExceptionType(){

    }
}

使用ControllerAdvice统一异常处理

//合并了@ControllerAdvice与@RestController
@Slf4j
@RestControllerAdvice
public class ExceptionController {
    /**
     *  校验错误拦截处理
     *
     * @param exception 错误信息集合
     * @return 错误信息
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public CommonResponse<String> validationBodyException(MethodArgumentNotValidException exception){
    	//对校验错误信息进行封装,并输出到日志
        BindingResult result = exception.getBindingResult();
        StringBuilder errorMessage = new StringBuilder();
        if (result.hasErrors()) {

            List<ObjectError> errors = result.getAllErrors();
            errors.forEach(p ->{

                FieldError fieldError = (FieldError) p;
                log.error(PaperServiceExceptionType.VALID_ERROR+":数据校验错误 : object{"+fieldError.getObjectName()+"},field{"+fieldError.getField()+
                        "},errorMessage{"+fieldError.getDefaultMessage()+"}");
                errorMessage.append(fieldError.getDefaultMessage());
            });

        }
        //封装错误到响应信息
        CommonResponse<String> response = new CommonResponse<>();
        ResHeader header = new ResHeader();
        response.setHeader(header);
        header.setErrorCode(PaperServiceExceptionType.VALID_ERROR);
        header.setMessage(errorMessage.toString());
        response.setBody(PaperServiceExceptionType.VALID_ERROR+":传入数据错误"+errorMessage.toString());
        return response;
    }
    /**
     * 请求方式不支持
     */
    @ExceptionHandler({HttpRequestMethodNotSupportedException.class})
    public CommonResponse<String> handleException(HttpRequestMethodNotSupportedException e) {
        log.error(e.getMessage(), e);
        CommonResponse<String> response = new CommonResponse<>();
        ResHeader header = new ResHeader();
        response.setHeader(header);
        header.setErrorCode(PaperServiceExceptionType.VALID_ERROR);
        header.setMessage("不支持' " + e.getMethod() + "'请求");
        response.setBody(PaperServiceExceptionType.VALID_ERROR+":传入请求错误不支持" + e.getMethod() + "'请求");
        return response;
    }
    //请求的数据格式错误的处理
    @ExceptionHandler(HttpMessageNotReadableException.class)
    public CommonResponse<String> handleException(HttpMessageNotReadableException e) {
        log.error(e.getMessage(), e);
        CommonResponse<String> response = new CommonResponse<>();
        ResHeader header = new ResHeader();
        response.setHeader(header);
        header.setErrorCode(PaperServiceExceptionType.VALID_ERROR);
        header.setMessage("传入数据格式错误");
        response.setBody(PaperServiceExceptionType.VALID_ERROR+":传入数据格式错误");
        return response;
    }
    @ExceptionHandler(PaperServiceException.class)
    public CommonResponse<String> handleMyException(HttpServletRequest request, PaperServiceException exception){
        CommonResponse<String> response = new CommonResponse<>();
        ResHeader header = new ResHeader();
        /**
         * 获取异常发生时请求的url
         * */
        PaperServiceException exceptionVO = new PaperServiceException(exception.getCode()
                ,String.valueOf(request.getRequestURL()),exception.getMessage());
        /**
         * 日志保存异常的信息
         * */
        log.error("服务出错:",exception.toString());
        /**
         * 设置返回的响应的头部异常码以及信息
         * */
        header.setErrorCode(String.valueOf(exception.getCode()));
        header.setMessage(exception.getMessage());
        response.setHeader(header);
        response.setBody(exceptionVO.getCode()+":"+exceptionVO.getMessage());
        return response;
    }
    //其他异常处理
    @ExceptionHandler(Exception.class)
    public CommonResponse<String> handleMyException(HttpServletRequest request, Exception exception){
        CommonResponse<String> response = new CommonResponse<>();
        ResHeader header = new ResHeader();
        /**
         * 获取异常发生时请求的url
         * */
       String url = String.valueOf(request.getRequestURL());
        /**
         * 日志保存异常的信息
         * */
        log.error("服务出错:",exception.toString());
        /**
         * 设置返回的响应的头部异常码以及信息
         * */
        header.setErrorCode(PaperServiceExceptionType.SYSTEM_ERROR);
        header.setMessage("服务器处理数据时发生异常"+url+exception.toString());
        exception.printStackTrace();
        response.setHeader(header);
        response.setBody(PaperServiceExceptionType.SYSTEM_ERROR+":"+"服务器处理数据发生异常");
        return response;
    }
}
springboot全局异常实现以及@Valid和@Validated优雅实现入参验证 springboot全局异常,@Valid和@Validated实现入参验证。 阅读详情

相关推荐

SpringBoot+@Validate+全局异常拦截实现自定义规则参数校验(校验get请求参数不能为空且在指定枚举类型中)

上面实现SpringBoot参数校验时以自带的注解进行校验,如果需要进行自定义校验规则,比如请求时必须携带某个请求码,而且该请求码字符串必须在指定范围,即从枚举类中指定包含的。上面是以post请求为例,下面以get请求为例。

BADAO_LIUMANG_QIZHI的博客 4569

springboot中@Validated+@ControllerAdvice+@ExceptionHandler注解对全局异常的处理

前言 为了解决什么问题: 1.前端传入大量繁琐数据需要校验,会产生大量 if else语句以及try catch语句导致代码冗杂,不美观。用@Validated注解可以很好的解决。它根据实体类配置的校验规则在进入controller接口的时候就会自动校验参数。 2.controller中每一个接口请求都要对异常进行处理,若接口不断增多,不同的异常也会不断增多,会导致异常太过紊乱,不好维护且不好拓展。因此用@ControllerAdvice+@ExceptionHandler对异常做统一处理。 正文 为了更方

qq_38425803的博客 2262

SpringBoot+@Validated实现参数验证(非空、类型、范围、格式等)-若依前后端导入Excel数据并校验为例

在上面搭建SpringBoot+Vue并实现Excel导入的基础上,为避免导入的excel中数据格式不规范导致产生大量脏数据,所以需要对excel的数据进行校验,比如不能为空、类型是否为数字、数字范围等等规则。若依官方对这块有专门说明说明比较简单,具体实现流程如下,也可参考其用户导入的实现代码和流程。这里对用户账号做了非空校验,需要在实体类上对应属性添加查看@NotBlank注解的实现发现其来自javax.validation。注:博客:关注公众号霸道的程序猿。

BADAO_LIUMANG_QIZHI的博客 5842

随手记录8:@Validated统一参数校验失败统一异常处理

随手记录8:@Validated完成请求参数统一校验并且异常处理类中统一进行处理简介demo下载项目结构内容代码内容1.接受请求参数的实体类2.在controller方法中完成异常信息的拼装校验返回的操作3.优化上面的方法统一异常处理中完成参数的校验;4.统一异常处理类案例效果内容1. 传递json格式的参数信息直接抛出异常在全局异常处理类中进行异常处理2. 传递的表单参数 (抛出的异常和上面的不一样)分组操作1.分组请求的req2.分组请求的controller入口代码校验案例效果1.测试默认分组的案例2

weixin_43812522的博客 3999

SolidWorks的GB库(钢型材库,包括铝型材、铝管等结构)安装及使用教程(生成铝型材为例)

1、GB库的下载 2、GB库的安装教程 3、GB库的使用教程

树下等苹果的博客 12万+

2024秋招,腾讯测试与质量管理工程师一面

家人们,秋招都开奖了吗,拿到自己心仪的offer了吗,还是在准备明年的春招呢?今天我记录一下,之前面试腾讯测开的一面过程面试官人非常好,我回答中有问题的地方,及时帮我指正同时耐心回答我的反问只可惜我当时的能力不足以达到鹅厂的标准,遗憾错过。

chowley的博客 1056

Spring Boot 中的数据校验:@Valid 与 @Validated 的使用及统一异常处理

当内置的校验注解不能满足需求时,可以自定义注解。例如,自定义一个校验手机号码格式的注解。Class

算命de博客 1250

【AAAI2025】【小目标检测】FBRT-YOLO:更快速、更优的实时航拍图像检测方法

FBRT-YOLO是一种新型实时航拍图像检测方法,针对小目标检测的精度与效率平衡问题提出创新解决方案。该方法通过两个轻量级模块显著提升性能:特征互补映射模块(FCM)将浅层空间位置信息深度整合至网络深层,缓解信息失衡;多核感知单元(MKP)采用多尺度卷积增强多目标感知能力。实验表明,在VisDrone、UAVDT和AI-TOD数据集上,FBRT-YOLO在检测精度和速度方面均优于现有实时检测器,特别适用于资源受限的飞行设备。该模型通过精简网络结构,在保持高性能的同时降低了计算负担,为航拍实时检测提供了高效解

weixin_44184852的博客 2903

Spring Boot参数校验避坑指南:@Validated和@Valid的正确使用姿势

本文深入解析Spring Boot中@Validated与@Valid注解的核心区别与正确使用姿势,涵盖从基础注解、依赖配置到分组校验、自定义注解等高级特性。重点探讨了如何结合统一异常处理机制构建健壮的参数校验体系,并提供了性能优化与最佳实践指南,帮助开发者有效规避常见陷阱。

cream的博客 740

快乐8 Ai大模型XGBoost LightGBM预测系统

随机森林回归:通过集成多个决策树模型,提高预测的准确性和稳定性。XGBoost:一种基于梯度提升的强大模型,擅长处理结构化数据。LightGBM:一种高效的基于决策树算法的分布式梯度提升框架,具有快速的训练速度和低内存消耗。高预测准确率:通过集成多种模型,提供更为精准的预测结果。多种预测方法:支持同尾号、重号、温号、连号和综合预测等多种预测策略,满足不同用户的需求。实时日志:在预测过程中,用户可以实时查看系统的预测进度和结果。

m0_72636583的博客 1万+

S32DS新建工程、编译调试下载、导入工程详细介绍

新建了一个工程之后,下面简单介绍下基本的UI界面。其中最左下角那个是界面,这个界面很重要,是图形化配置界面,然后可以根据这些配置自动生成代码。其中,左边那些配置文件,都是系统帮我们创建好了的,我们其实可以直接用就行。有PE工具的调试,以及Jlink工具的调试。我目前使用到PE工具调试可以查看寄存器值,而Jlink调试查看不了寄存器值。连接了开发板之后,点击Debug就可以吧程序下载到芯片上了,而且可以进入到调试界面。

luobeihai的博客 2万+

SpringBoot项目接口统一响应处理、统一异常处理、统一配置、接口验证

ResponseBodyAdvice 接口实现自定义返回数据类型 api接口中都是需要定义一个统一的响应头来返回json数据 一般方法是通过在返回时构造一个响应头对象如下: public class ApiR extends HashMap<String, Object> { private static final long serialVersionUID = 1L; pub...

IManiy的博客 1982

转换shp坐标系之前,设置转换的投影

1.点击目录》工具箱》系统工具箱》Data Management Tools.tbx》投影和变换》创建自定义地理(坐标)变换 2.名称自定义 2.输入地理坐标系可以根据所需要转换的shp文件属性中查询出来 把图层拖入arcgis中,右键属性即可查看 3.复制坐标系,点击“输入地理坐标系”右侧的按钮后,粘贴在顶部搜索框中,并按enter键,选择对应的坐标系 4.点击“输出地理坐标系”右侧的按钮后,选择转换后的坐标系,如4326,选择后点击确认按钮。 5.自定义方法中选择

Wangwangwang___的博客 1863

手把手教你利用Spring Boot实现各种参数校验

Java API规范 (JSR303) 定义了Bean校验的标准validation-api,但没有提供实现。hibernate validation是对这个规范的实现,并增加了校验注解如@Email、@Length等。Spring Validation是对hibernate validation的二次封装,用于支持spring mvc参数自动校验。接下来,我们以spring-boot项目为例,介绍Spring Validation的使用。如果spring-boot版本小于2.3.x,spring-boot

CXY_QIQI的博客 1178

华为OD机试2025C卷-双十一最大花费金额[100分](Java_Python3_C++_C语言_JsNode_Go)实现100%通过率

双十一最大花费金额 - 动态规划解法 摘要:本文介绍了华为OD机试中"双十一最大花费金额"问题的动态规划解法。该问题要求在给定N件商品价格和优惠券面额X的情况下,选择若干商品使总花费不超过X且尽可能大。核心解法采用布尔型动态规划数组,记录每个金额是否可被拼出。算法时间复杂度为O(N*X),空间复杂度为O(X)。通过倒序遍历避免重复选择同一商品,最后从X向下查找第一个可达金额作为答案。文中提供了C++和Java的实现代码,并解释了与经典0-1背包问题的关系。 关键点: 问题本质是0-1背包/子集和问题的变体

2503_91057718的博客 46

Qt软件开发-Qt编译zlib完成文件压缩解压(win10)

在软件开发中进行有需求需要将生成的一些文件打包上传到服务器,或者从服务器下载压缩包下来内部解压。或者自己做一些打包工具,那么使用zlib开源就可以很方便的完成。接下来介绍在zlib在windows下如何利用Qt进行编译,调用,介绍mingw、msvc,32/64位编译办法,完成zip文件打包生成例子。可以单文件压缩打包,多文件压缩打包,目录压缩打包等等。

2216

Spring Boot 参数校验全指南:@Valid 与 @Validated 的区别与实战用法总结

在后端开发中,参数校验是防御性编程的第一道防线。与其在业务代码里写满,不如利用 Bean Validation 规范,优雅地实现“配置式校验”和“快速失败(Fail-Fast)”。本文将总结@Valid和@Validated的区别,并演示它们在不同层级(Controller/Service/Config)的最佳实践。

czlczl20020925的博客 863

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

Spring Boot中的参数校验

在软件开发中,通常需要对参数进行校验,比如某些参数不能为空,而且不光前端要校验,后端也要校验。那么后端在哪里校验参数?是在控制层还是service层?参数校验有多种实现方式,采用哪一种校验方式呢? 一般来说,把无业务语义的校验放在action层,用validation做校验,比如数据类型,是否为空,数据长度、格式等,有业务语义的校验放在service层。当然实际中往往并没有那么清晰,当校验足够简单时

xiaoyi52的专栏 2922

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

SpringBoot使用validation

如果实体类上既有未分组的注解,也有已分组的注解,如果未分组的注解写在前面,那么方法参数上需要先写@Valid注解,然后再写@Validated(Add.class)2.方法参数前添加注解@NotEmpty(message = “请选择要删除的记录”)使用场景:添加用户时需要输入密码,修改用户时不需要输入密码,这是可以使用分组进行区分。添加@Valid和@Validated(Add.class)注解。使用场景:query传参和path传参。1.类上添加注解@Validated。添加@Valid注解。

牧小七的博客 219

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

Spring Boot参数校验实战:@Validated与统一异常处理的完美结合

本文详细介绍了Spring Boot中@Validated与统一异常处理的结合使用,通过参数校验提升系统健壮性。文章对比了@Validated与@Valid的核心区别,展示了常用校验注解实战和自定义校验方法,并提供了统一异常处理的最佳实践,帮助开发者高效处理校验失败场景。

prometheus5watch的博客 878

Java注解校验实战

java/** * 校验组定义 */ public interface ValidationGroups { // 新增操作 interface Create {} // 更新操作 interface Update {} // 删除操作 interface Delete {} // 默认组(不指定group时使用) interface Default {} }手机号校验身份证号校验:@IdCard枚举值校验字段互斥密码强度:理解两者的区别和适用场景校验组:使用分组管理不同场景的校验规则自定义注解。

stone_tmp的博客 737

Spring Boot参数校验实战:@Validated与@Valid的5个高频使用场景解析

本文深入解析Spring Boot中`@Validated`与`@Valid`的5个高频使用场景,包括REST API参数校验、Feign客户端校验、动态分组校验、嵌套对象校验及统一异常处理。通过实战代码示例,帮助开发者掌握高效参数校验技巧,提升系统健壮性。特别强调`@Validated`在类级别校验与`@Valid`在对象级联校验中的差异化应用。

weixin_30300225的博客 444

Spring Boot参数校验实战:从@Validated到自定义注解的进阶指南

本文详细介绍了Spring Boot参数校验的实战技巧,从基础的@Validated和@Valid注解使用到自定义校验注解的进阶应用。通过实际案例演示了分组校验、嵌套对象校验等高级功能,并提供了异常处理和性能优化的最佳实践,帮助开发者构建健壮、高效的参数校验体系。

weixin_30363509的博客 321

Spring Boot 实现各种参数校验,写得太好了,建议收藏!

业务需求总是比框架提供的这些简单校验要复杂的多,我们可以自定义校验来满足我们的需求。自定义spring validation非常简单,假设我们自定义加密id(由数字或者a-f的字母组成,32-256长度)校验,主要分为两步:自定义约束注解// 默认错误消息String message() default "加密id格式错误";// 分组Class<?// 负载Class<?实现ConstraintValidator接口编写约束校验器@Override// 不为null才进行校验。

jike007gt的博客 553
上一篇: spring boot整合 redis作为缓存
下一篇: Spring Cloud + Vue Admin Template 前后端分离开发 导航帖
WSimpossible
博客等级 码龄7年 2粉丝 6原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值