springboot2.x入门(六)—@validated注解结合全局异常控制器实现统一参数校验

2023-11-03

写接口的时候,参数校验是不是还一个一个的判空或者判断格式是否正确,业务代码没写几行,写了一堆if StringUtils.isBlank,对不对,我说的对不对!!!小啦,逼格小啦~!。今天我就来深入浅出的讲讲spring boot+@Validated+@controlleradvice+自定义注解实现统一参数校验。

一、@Validated注解介绍

@Validation是一套帮助我们继续对传输的参数进行数据校验的注解,通过配置Validation可以很轻松的完成对数据的约束。

@Validated作用在类、方法和参数上


@Target({ElementType.TYPE, ElementType.METHOD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Validated {
    Class<?>[] value() default {};
}

@Validated的校验注解及其说明

 

二 @Validated的使用方法

    @PostMapping("valid")
    public Response valid(@Validated @RequestBody RequestBean requestBean) {
        Response response = Response.success();
        return response;
    }

使用实体类接收body参数,如果非body参数,将校验注解(例如NotBlank)直接写在参数前面。实体类的话就写在属性上,就像下面这样。

public class RequestBean implements Serializable {
    @NotBlank(message = "缺少appId")
    private String appId;
    @NotBlank(message = "缺少requestData")
    private String requestData;



    public String getAppId() {
        return appId;
    }

    public void setAppId(String appId) {
        this.appId = appId;
    }


    public String getRequestData() {
        return requestData;
    }

    public void setRequestData(String requestData) {
        this.requestData = requestData;
    }
}

@Validated如果没有出现校验失败,则会抛出MethodArgumentNotValidException,这个时候我们可以用统一异常管理类,来组装异常信息返回给前台。操作如下。

我们用统一异常管理类捕获参数校验异常,因为是写demo,所以下面的统一异常处理的不够细粒度,等有机会专门写一篇文章用来介绍统一异常管理。

@ControllerAdvice
public class GlobalExceptionHandler {

    private static final String logExceptionFormat = "Capture Exception By GlobalExceptionHandler: Code: %s Detail: %s";
    private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);


    @ResponseBody
    @ExceptionHandler({NullPointerException.class, RuntimeException.class, ClassCastException.class,
            IOException.class, IndexOutOfBoundsException.class, HttpRequestMethodNotSupportedException.class})
    public Response nullPointerExceptionHandler(NullPointerException ex) {
        return responseFormat(ResponseEnum.FAIL.getCode(), ex);
    }

 /**
     * @param exception
     * @return
     * @throws Exception
     */
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public Response MethodArgumentNotValidHandler(
            MethodArgumentNotValidException exception) {
        //按需重新封装需要返回的错误信息
        List<ArgumentInvalidResponse> invalidArguments = new ArrayList<ArgumentInvalidResponse>();
        //解析原错误信息,封装后返回,此处返回非法的字段名称,原始值,错误信息
        for (FieldError error : exception.getBindingResult().getFieldErrors()) {
            ArgumentInvalidResponse invalidArgument = new ArgumentInvalidResponse();
            invalidArgument.setErrorMessage(error.getDefaultMessage());
            invalidArgument.setField(error.getField());
            invalidArgument.setRejectedValue(error.getRejectedValue());
            invalidArguments.add(invalidArgument);
        }
        return Response.fail(ResponseEnum.PARAMETER_ERROR.getCode(), ResponseEnum.PARAMETER_ERROR.getMessage(), invalidArguments);
    }



    private <T extends Throwable> Response<Object> responseFormat(Integer code, T ex) {
        ex.printStackTrace();
        logger.error(String.format(logExceptionFormat, code, ex.getMessage()));
        String message = String.format(logExceptionFormat, code, ex.getMessage());
        return Response.fail(code, message, null);
    }

}

 创建一个专门用于组装参数校验失败信息的对象

public class ArgumentInvalidResponse {
    private String errorMessage;
    private String field;
    private Object rejectedValue;


    public String getField() {
        return field;
    }

    public void setField(String field) {
        this.field = field;
    }

    public Object getRejectedValue() {
        return rejectedValue;
    }

    public void setRejectedValue(Object rejectedValue) {
        this.rejectedValue = rejectedValue;
    }

    public String getErrorMessage() {
        return errorMessage;
    }

    public void setErrorMessage(String errorMessage) {
        this.errorMessage = errorMessage;
    }
}

三、测试

{
    "code": 40005,
    "message": "PARAMETER_VALIDATION_FAILED",
    "data": [
        {
            "errorMessage": "缺少requestData",
            "field": "requestData"
        },
        {
            "errorMessage": "缺少appId",
            "field": "appId"
        }
    ]
}

 这样我们就完成了基于注解的参数校验,有的小伙伴可能会说,有的字段框架自带的注解不满足日常需求,比如我想校验身份证,手机号等等怎么办,那就得用到自定义校验注解了,这个我们下次再写。

有问题的在下方留言,大家可以关注我的公众号:codesls。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

springboot2.x入门(六)—@validated注解结合全局异常控制器实现统一参数校验 的相关文章

随机推荐

  • Java从入门到实战总结-1.1、Java基础之环境搭建和eclipse安装

    Java从入门到实战总结 1 1 Java基础之环境搭建和eclipse安装 文章目录 Java从入门到实战总结 1 1 Java基础之环境搭建和eclipse安装 1 Hello Java 1 1 Java起源 1 2 Java演变 2
  • MTK9612方案电视STR开机后屏黑有声的问题分析

    问题描述 客户反馈问题 机顶盒连接tv tv str 关机 机顶盒一直开着 过了几个小时 一次 或者第二天过来 一次 str开机 出现tv 黑屏 抓取分析log 考虑到开了ac logleve 7后比较难复制问题 麻烦这样操作 开机停到mb
  • 如何设置网页标签的LOGO

    问题描述 我们打开很多页面都会发现浏览器标签上有LOGO 那么我们该怎么样给自己的网站也设置一个酷炫的LOGO呢 解决办法 1 首先取一张图片 打开 http www bitbug net 或者百度 搜索ico图标制作 制作成16 16px
  • 求二叉树第K层节点的个数

    题目 求二叉树第k层节点的个数 思路 1 递归 求根为root的二叉树第k层节点的个数 就是要求 root left第k 1层节点的个数 root right第k 1层节点的个数 public static int getNumberOfK
  • Idea中使用Tomcat部署并启动Web项目

    首先在Idea中选择编辑运行配置 如下图 左上角的 号 选择Tomcat服务 如下图 自定义服务名称和项目在浏览器的访问路径 配置Tomcat服务器路径 如下图 然后在服务器中部署项目 下面的警告提示 Warning No artifact
  • 深度学习(五)caffe环境搭建

    ubuntu 系统下的Caffe环境搭建 原文地址 http blog csdn net hjimce article details 48781693 作者 hjimce 对于caffe的系统一般使用linux系统 当然也有windows
  • 运算放大器基本参数-增益带宽积(直观解释)

    运算放大器在理想情况下增益为无限大 但是在显示生活中其增益是有限的 增益带宽积指的就是运放的增益和其带宽的乘积 对于一个运放来说这个参数为一个常数 也就意味着增益和带宽成反比 下图通过直观的实验来验证 上图为输入1kHz时输入与输出的波形
  • Proxyee Down简介

    以前写过一篇用Proxyee下载百度网盘大文件的文章 后来一直没在用过 现在发现Proxyee出了新版 功能也增加了 所以重新来介绍一下 现在它的Github地址也变了 现在的地址是 https github com proxyee dow
  • myeclipse中No entries available错误解决方法

    在hibernate中 每个数据表对应的其实是一个实体类 每个实体类有一个对应的hbm xml配置文件和你匹配 myeclipse中有个MyEclipse Database Explorer视图 它提供了myeclipse与数据库直接连接的
  • C++多态理解与认识

    1 什么是多态 多态是指函数调用的多种形态 使我们调用函数更加灵活 多态分为静态多态与动态多态 1 静态多态 静态多态指的是编译时的多态 通过函数重载实现 根据函数命名规则找到函数地址 从而实现调用不同的方法 2 动态多态 运行时 父类指针
  • DVWA-XSS 级别通关详解(图文详细)

    目录 DVWA XSS 级别通关详解 low级别 1 反射性xss 2 存储型xss 3 DOM型xss Medium级别 1 反射型xss 2 存储型xss 3 DOM型xss hight级别 1 反射型xss 2 存储型xss 3 DO
  • 一文搞懂基于用户的协同过滤推荐算法

    本文针对无上下文信息的隐性反馈数据集 每一条行为记录仅仅包含用户ID和物品ID 介绍基于用户的协同过滤算法原理 基于用户的协同过滤推荐算法本质 找到和待推荐用户相似的用户群 推进该用户群感兴趣且待推荐用户没购买过的物品 例如下图中 用户a购
  • java基础

    一 java环境的搭建 搭建Java环境的步骤如下 1 下载Java Development Kit JDK 可以从Oracle官方网站或者其他可靠的网站下载适用于您的操作系统的JDK版本 OpenJDK JDK Updates Proje
  • Linux运维相关命令(不定时更新)

    日志 查找 查看最近n行 gt gt gt tail n 100 filename 查找包含字符 a 的行 gt gt gt grep a filename 修改 删除包含字符 a 的行 gt gt gt sed i e a d filen
  • 求职经历,三轮技术面 +HR 面,面试也不过如此

    众所周知 阿里主要以 Java 为主 因此我投递的职位是 Java 高级 资深开发 我当时是在 Boss 直聘 App 上看到的职位 下图是当时的职位招聘信息 面试过程中注意策略 我求职的阿里的 Java 技术岗位一共有三轮技术面试和一轮
  • Python time和datetime时间戳和时间字符串相互转换

    Python time和datetime时间戳和时间字符串相互转换 时间戳是指格林威治时间1970年01月01日00时00分00秒开始计算所经过的秒数 是一个浮点数 time和datetime都是Python中的内置模块 不需要安装 直接可
  • golang 自定义命令行flag包简单使用

    一 为什么需要使用golang自定义命令行 不恰当的比喻 当我们写了一个服务代码后 按照简单的思维 我们会在业务代码中将要连接的数据库 用户名 主机名 端口号 密码写死 那么也就意味着我们启动该服务后都只能固定连接某一个数据库 而如果我们将
  • 使用Python操作MySQL的小技巧

    更多编程教程请到 菜鸟教程 https www piaodoo com 友情链接 好看站 http www nrso net 高州阳光论坛https www hnthzk com 1 获取插入数据的主键id import pymysql d
  • passwd Authentication token manipulation error----linux

    分享一下我老师大神的人工智能教程 零基础 通俗易懂 http blog csdn net jiangjunshow 也欢迎大家转载本篇文章 分享知识 造福人民 实现我们中华民族伟大复兴 author skatetime 2009 04 11
  • springboot2.x入门(六)—@validated注解结合全局异常控制器实现统一参数校验

    写接口的时候 参数校验是不是还一个一个的判空或者判断格式是否正确 业务代码没写几行 写了一堆if StringUtils isBlank 对不对 我说的对不对 小啦 逼格小啦 今天我就来深入浅出的讲讲spring boot Validate