首页 > 其他分享 >springboot3使用validation进行参数验证

springboot3使用validation进行参数验证

时间:2024-03-17 22:56:45浏览次数:25  
标签:验证 boot 校验 springboot3 message validation public Result

前言

  今天学习了使用validation整合springboot进行字段的校验,体验下来感觉很不错,有了validation可以省下一大堆控制器里面的数据校验,例如前端发送了一个请求到我们后端,请求中包含的数据字段一般情况下都是通过前端校验过的然后发送到后端进行处理,但是考虑到整体后端代码的可靠性和健壮性,不能100%得相信前端发送来的数据(万一某些前端数据来自一些闲的没事的人发来搞事情的呢),所以为了整体系统的可靠性后端也要对发来的数据进行校验,避免后期不必要的麻烦。

  那么言归正传,如果我们在控制器中加入大量的if进行数据校验,那么最终控制器(controller层)中的代码就会显得很臃肿,可读性降低,看起来也不够优雅,用validation就可以”优雅“地解决这个问题。

plugins {
    id 'java'
    id 'org.springframework.boot' version '3.2.3'
    id 'io.spring.dependency-management' version '1.1.4'
}

apply from: './father.gradle'

group = 'org.example'
version = '0.0.1-SNAPSHOT'

java {
    sourceCompatibility = '17'
}

configurations {
    compileOnly {
        extendsFrom annotationProcessor
    }
}

repositories {
    mavenLocal()
    mavenCentral()
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'org.springframework.boot:spring-boot-starter-validation'

    testImplementation 'org.springframework.boot:spring-boot-starter-test'

    runtimeOnly 'com.mysql:mysql-connector-j'

    //MP
    // https://mvnrepository.com/artifact/com.baomidou/mybatis-plus-spring-boot3-starter
    implementation 'com.baomidou:mybatis-plus-spring-boot3-starter:3.5.5'

    //druid
    // https://mvnrepository.com/artifact/com.alibaba/druid
    implementation 'com.alibaba:druid:1.2.21'
//swagger
    // https://mvnrepository.com/artifact/org.springdoc/springdoc-openapi-starter-webmvc-ui
    implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.2.0'

}

tasks.named('test') {
    useJUnitPlatform()
}

这个脚本中,我导入了 implementation 'org.springframework.boot:spring-boot-starter-validation' 其版本由springboot进行管理。maven导入:

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

下面是要用到的类:

点击查看代码Result类
@AllArgsConstructor
@NoArgsConstructor
@Data
public class Result<T> {
    private int code;
    private String msg;
    private T data;

    public static <T> Result<T> success(T data) {
        return  new Result<>(Code.SUCCESS, "请求成功", data);
    }

    public static <T> Result<T> failed(String msg) {
        return  new Result<>(Code.FAILED, msg,null);
    }
}

点击查看代码code类
public class Code {
    public static  final int SUCCESS = 10100;
    public static  final int FAILED = 10101;
    public static  final int BUSY = 10102;
    public static  final int GRANT_ERR = 10103;
}

原本我们在校验前端发来的数据的时候需要在控制器中写很多if,现在我们可以这样写,这是dmeo:

@GetMapping("/get")

    public Result<User> getUserBy(@Pattern(regexp = "^[1-9]\\d*$",message = "id不合法") @RequestParam String id) {

        return Result.success(userMapper.selectById(id));
    }

我们在字段前面加上 @Pattern(regexp = "^[1-9]\\d*$",message = "id不合法") 我们用正则表达式进行参数的校验,当然这只是validation的其中一个注解,如果前端发来的参数可以成功匹配表达式,那么程序继续执行,如果不能,则会抛出异常,如果是在控制器中对参数进行校验会抛出HandlerMethodValidationException异常(实验得知),但如果是在实体类中的参数上面加上validation的注解,在请求体参数使用@Valid注解则会抛出MethodArgumentNotValidException异常,例如下面的方法会抛出MethodArgumentNotValidException异常:

@PostMapping("/save")
    public Result save(@Valid @RequestBody User user){
        userMapper.insert(user);
        return Result.success(null);
    }
点击查看代码User实体
@AllArgsConstructor
@NoArgsConstructor
@Data
public class User {

    @Size(min = 18, max = 18, message = "身份证长度不正确")
    private String idcard;

    @Size(min = 2,message = "姓名至少两个字")
    private String name;

    @Past(message =  "出生日期必须是过去时间")
    private java.sql.Date birth;

    @Pattern(regexp = "^[男|女]$",message = "性别只能是男或女")
    private String sex;

    @Positive(message = "年龄必须是正整数")
    @Max(value = 120,message =  "年龄不能超过120岁")
    private Integer age;


    @TableId
    @Positive(message = "工号整数")
    private Integer worknum;


}

tips:validation注解一般用于controller层和实体类属性上

那如何处理未验证通过的请求呢?下面给出一个异常捕获器的处理方式,将message中的错误信息返回给前端:

@ExceptionHandler(MethodArgumentNotValidException.class)
    public Result exceptionHandler(MethodArgumentNotValidException exception){
        List<ObjectError> allErrors = exception.getAllErrors();
        StringBuilder stringBuilder=new StringBuilder();
        for (ObjectError error : allErrors) {
            stringBuilder.append(error.getDefaultMessage()).append("\n");
        }
        return Result.failed(stringBuilder.toString());
    }

这是MethodArgumentNotValidException异常处理器也就是异常信息由实体类属性校验产生(本人这么理解,如有错误望指正);HandlerMethodValidationException处理的代码几乎与以上一样;处理的方式可以多种样具体处理方式可以看业务的具体需求,当然也可以不给出那么详细的错误信息,校验失败直接抛给全局异常处理器返回BAD_REQUEST信息,这样也会减轻一些工作量。

标签:验证,boot,校验,springboot3,message,validation,public,Result
From: https://www.cnblogs.com/sky-su/p/18079380

相关文章

  • 最详细的Keycloak教程(建议收藏):Keycloak实现手机号、验证码登陆——(三)基于springboot&k
    在前面两节分别介绍了Keycloak的下载与使用和keycloak与springboot的集成。接下来第三节让我们一步步的去完成一个简单的前后端分离项目,并且可以扩展实现sso。一、简介本文将介绍如何使用SpringBoot、Keycloak和Vue构建一个具有前后端分离架构的Web应用程序。通过将前......
  • RuoYi-Vue开源项目2-前端登录验证码生成过程分析
    前端登录验证码实现过程生成过程分析生成过程分析验证码的生成过程简单概括为:前端登录页面加载时,向后端发送一个请求,返回验证码图片给前端页面展示前端页面加载触发代码: import{getCodeImg}from"@/api/login"; created(){ this.getCode(); this.......
  • 每日一练:LeeCode-125、验证回文串【字符串+双指针】
    如果在将所有大写字符转换为小写字符、并移除所有非字母数字字符之后,短语正着读和反着读都一样。则可以认为该短语是一个回文串。字母和数字都属于字母数字字符。给你一个字符串s,如果它是回文串,返回true;否则,返回false。示例1:输入:s="Aman,aplan,acana......
  • pikachu靶场第三关-密码爆破之验证码绕过(on client)(附代码审计)
    源代码如下:if(isset($_POST['submit'])){if($_POST['username']&&$_POST['password']){$username=$_POST['username'];$password=$_POST['password'];$sql="select*......
  • 125. 验证回文串c
    回文串置逆,栈,双指针。booljudge(charc){if(c>='a'&&c<='z')returntrue;if(c>='A'&&c<='Z')returntrue;if(c>='0'&&c<='9')returntrue;return......
  • R语言弹性网络Elastic Net正则化惩罚回归模型交叉验证可视化
    原文链接:http://tecdat.cn/?p=26158原文出处:拓端数据部落公众号 弹性网络正则化同时应用L1范数和L2范数正则化来惩罚回归模型中的系数。为了在R中应用弹性网络正则化。在 LASSO回归中,我们为alpha参数设置一个'1'值,并且在岭回归中,我们将'0'值设置为其alpha参数......
  • springboot3+vue3(十一)springboot多环境开发
    在开发中我们往往会遇到,本地环境、测试环境、生产环境分别一套配置。如数据库连接,端口号等配置各不相同的问题。 1、多文件配置    2、多文件分组配置如果配置文件有很多的配置信息几百行的情况,为了方便维护我们可以根据功能的情况进行分组拆分。如:服务器相关配......
  • 验证子序列(动态规划)
    验证子序列(动态规划)392.判断子序列-力扣(LeetCode)题目描述:给定字符串s和t,判断s是否为t的子序列。字符串的一个子序列是原始字符串删除一些(也可以不删除)字符而不改变剩余字符相对位置形成的新字符串。(例如,"ace"是"abcde"的一个子序列,而"aec"不是)。进阶:如果......
  • springboot3/14
    在做系统首页配置时,#注意点,所有页面的静态资源都需要使用thymeleaf去接管;@{}页面国际化在项目中使用国际化我们需要配置i18n文件如果需要在项目中进行按钮自动切换功能,需要自己去定义一个国际化组件LocaleResolver配置完成后,记得将写好的组件配置到spring容器中@Bean在网页......
  • 98. 验证二叉搜索树c
    /***Definitionforabinarytreenode.*structTreeNode{*intval;*structTreeNode*left;*structTreeNode*right;*};*/boolinorder(structTreeNode*root,long*pre){if(!root)returntrue;boola=inorder(root->le......