化繁为简,使用Hibernate Validator实现参数校验

这篇具有很好参考价值的文章主要介绍了化繁为简,使用Hibernate Validator实现参数校验。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

前言

环境配置

导入依赖

基础校验

校验注解

参数绑定

@PathVariable

@RequestParam

@RequestBody

@Validated

@Valid

单参校验

对象校验

分组校验

顺序校验


前言

        在之前的悦享校园的开发中使用了SSM框架,由于当时并没有使用参数参数校验工具,方法的入参判断使用了大量的if else语句,代码十分臃肿,因此最近在重构代码时,将框架改为SpringBoot后,引入了Hibernate Validator校验工具对参数进行优雅校验(SSM同样可用)。本文将通过实例来演示如何使用该框架。

环境配置

JDK 1.8

Spring Boot 2.7.12

导入依赖

        <!--SpringBoot 2.3开始,校验包单独组件,需要手动引入 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>

基础校验

在正式开始之前,需要先对以下的内容作以了解,方便后续的学习。

校验注解

Hibernate Validator,提供了丰富的校验注解来供我们使用,这里列举一些比较常用的:

注解 解释
@Null

验证对象是否为空

@NotNull

验证对象是否为非空

@NotBlank

用于String对象,验证字符串不为空且trim()后长度大于0

@Length

验证对象的长度是否符合

@Size

验证对象长度是否在给定的范围之内(用于Array,Collection,Map,String)

@Min

入参对象的值不能小于该值(用于Number和String)

@Max

入参对象的值不能大于该值(用于Number和String)

@Digits

验证number和string的构成是否合法

@Past

验证date和calendar对象是否在当前时间之前

@Future

验证date和calendar对象是否在当前时间之后

@Pattern

验证是否符合正则表达式规则

@Email 验证邮箱
@Positive

验证输入的对象是否非负数

@Range

验证输入的对象的值是否在指定范围内

参数绑定

@PathVariable

该注解用于接收具有Restful风格的参数,如/api/v1/1001,最终userId的值为1001

如下代码中,使用name属性可以指定GetMapping中的id名称与之对应,从而可以自定义参数名称userId,而不是使用默认名称id

@GetMapping("/v1/{id}")
public void getMsg(@PathVariable(name = "id") Integer userId){}

@RequestParam

该注解用于接收查询参数,如/api/v1/product?user="123",则user的值为123。该注解也可用于接收form-data类型的数据。

当在参数前使用@RequireParam时,当请求该方法时,对应的参数必须存在,否则会引发异常,可使用@RequireParam(required = false)指明该参数非必须,该注解在入参为null时可提供默认值。

@GetMapping("/v1/product")
public void getMsg(@RequestParam String user){}

@RequestBody

该注解用于接收JSON格式的数据,如请求为{"name":123,"age":18},需要有对应的实体类作为映射。

@PostMapping("/v1/user")
public void getMsg(@RequestBody User user){}

@Validated

该注解可以作用于类、方法、参数上,用于开启参数校验。

@Valid

该注解可以作用于方法、参数、字段、构造器上,同样可以用于参数校验。

单参校验

将@Validated注解用于类上,可以不用在每个方法的参数上重复开启校验,使用前面提的基础校验即可对参数作约束。 

校验方法

@RestController
@RequestMapping("/v1/hello")
@Slf4j
@Validated
public class HelloController {

    /**
     * GetMapping 请求
     * @param name 用户名称
     * @param uid  用户uid
     * @return
     */
    @GetMapping("/{id}")
    public ResultDataVO getMsg(@RequestParam String name,
                               @Max(value = 10,message = "最大值不能超过10")
                               @PathVariable(name = "id") int uid) {
        log.info("访问hello下的msg方法。");
        String result = "Hello,"+name+" id "+uid;

        return ResultDataVO.success(result);
    }
}

请求参数化繁为简,使用Hibernate Validator实现参数校验,spring boot,后端,validation,java 响应结果

化繁为简,使用Hibernate Validator实现参数校验,spring boot,后端,validation,java

 由于我们没有给String参数赋值,因此默认为空字符串。但由于在uid上使用了@Max注解,因此当入参为100时便会出现异常,而返回的JSON格式为全局的响应处理,在后续的文章会提到。

对象校验

当我们在使用中,往往会遇到多个参数的情况,由于get请求对参数长度有限制,且参数会拼接在URL中, 因此对于此场景我们一般使用对象的方式来接收参数,而对于我们的参数也将传入也将用JSON格式。

由于使用JSON格式传参,将使用@RequestBody注解,除此之外还要使用@Validated或@Valid注解,关于两者的选择,只需要记住分组校验使用@Validated,否则二者均可。

即使在类上添加了@Validated注解,此处仍然需要以上两个注解之一,否则参数校验将无效。

校验方法

@RestController
@RequestMapping("/v1/hello")
@Slf4j
@Validated
public class HelloController {

    /**
     * 对象校验示例
     * @param user
     * @return 
     */
    @PostMapping("/msg")
    public ResultDataVO(@RequestBody @Valid UserDTO user){
        return ResultDataVO.success(user.toString());
    }
}

UserDTO

@Data
@AllArgsConstructor
@NoArgsConstructor
public class UserDTO {

    /**
     * id
     */
    @Min(value = 1,message = "id值不合法")
    @Positive
    private Integer id;
    /**
     * 昵称
     */
    @NotBlank(message = "用户名不能为空")
    @Length(min = 4,max=10,message = "用户名必须在4-10个字符之间")
    private String username;
    /**
     * 年龄
     */
    @Range(min = 1,max=120,message = "年龄不在合法范围内")
    @NotNull(message = "age不能为空")
    private Integer age;
}

上述代码中,参数为UserDTO对象,其中包含三个待校验的字段,由于未涉及到分组校验,因此校验方法中参数前使用@Valid注解(@Validated注解亦可),注意入参的字段名称需要和UserDTO中的名称一致。

请求参数

化繁为简,使用Hibernate Validator实现参数校验,spring boot,后端,validation,java 响应结果

化繁为简,使用Hibernate Validator实现参数校验,spring boot,后端,validation,java

分组校验

假设有这样的场景,在用户登录和修改密码中,两者分别需要如下参数,登录时需要用户名、密码,而修改时需要密码、新密码,为了方便管理,只使用了一个DTO类来存放上述的字段,此时由于这些参数需要在不同的场景下校验,而加上基础校验的注解会导致所有参数均被校验,面对此问题,我们将使用分组校验来解决。

可以看到如何代码中,均是使用了@Validate注解,且注解中含有一个分组接口,使用该接口可以帮助我们告知程序该对哪些参数进行校验。

校验方法

@RestController
@Slf4j
@RequestMapping("/local/auth")
@Validated
public class LocalAuthController {

    @Autowired
    private LocalAuthService localAuthService;

    /**
     * 用户登录接口
     * @param localAuthDTO 账号对象
     * @return
     */
    @PostMapping("/login")
    LocalAuthVO loginCheck(@RequestBody @Validated(AuthCheckSequence.class) LocalAuthDTO localAuthDTO){
        return localAuthService.userLoginCheck(localAuthDTO);

    }

    /**
     * 用户修改密码接口
     * @param localAuthDTO 账号对象
     * @return
     */
    @PutMapping("/password")
    ResultDataVO userChangePassword(@RequestBody
                                    @Validated(AuthChangeSequence.class)
                                    LocalAuthDTO localAuthDTO){
        return localAuthService.userModifyPassword(localAuthDTO);
    }
}

分组接口

AuthChangeSequence 

/**
 * 分组校验,用户登录
 */

public interface AuthCheckSequence {

}

AuthCheckSequence 

/**
 * 分组校验,密码修改
 */
public interface AuthChangeSequence {

}

LocalAuthDTO 

@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class LocalAuthDTO {

    /**
     * 用户名
     */
    @NotBlank(message = "用户名不能为空",groups = AuthCheckSequence.class)
    @Pattern(regexp = "^[a-zA-Z0-9]{3,8}$", message = "用户名必须由3-8个字母或数字组成",
    groups = AuthCheckSequence.UsernameCheck.class)
    private String username;

    /**
     * 密码
     */
    @NotBlank(message = "密码不能为空",groups = AuthCheckSequence.class)
    @Size(min = 6,max = 18, message = "密码长度必须在6到18位之间",groups = AuthCheckSequence.PasswordCheck.class)
    private String password;

    /**
     * 新密码,修改密码时使用
     */
    @NotBlank(message = "新密码不能为空",groups = AuthChangeSequence.class)
    @Size(min = 6,max = 18, message = "新密码长度必须在6到18位之间",groups = AuthChangeSequence.ChangePassword.class)
    private String newPassword;
}

请求参数

化繁为简,使用Hibernate Validator实现参数校验,spring boot,后端,validation,java

响应结果

化繁为简,使用Hibernate Validator实现参数校验,spring boot,后端,validation,java

从上图所示请求结果可以看出,使用@Validated注解+分组校验接口后,将只对该参数中标明了对应分组接口的字段进行校验,并不会对全部参数进行校验。 

顺序校验

由于用户人数增多,我们将在对用户进行分组,将在LocalAuthDTO中引入新的字段,而我们所期望的是能够按照用户类型,用户名,密码的顺序来校验,而不是像之前对象校验最终显示的结果那样,随机进行校验并返回结果,因此需要使用在分组校验的基础上做一些改进,使其可以按照我们所指定的顺序执行校验,以前面登录为例:

校验方法

@RestController
@Slf4j
@RequestMapping("/local/auth")
@Validated
public class LocalAuthController {

    @Autowired
    private LocalAuthService localAuthService;

    /**
     * 用户登录接口
     * @param localAuthDTO 账号对象
     * @return
     */
    @PostMapping("/login")
    LocalAuthVO loginCheck(@RequestBody @Validated(AuthCheckSequence.class) LocalAuthDTO localAuthDTO){
        return localAuthService.userLoginCheck(localAuthDTO);

    }
}

 AuthCheckSequence

通过在该分组接口中新建接口,并使用@GroupSequence注解中参数的顺序来实现校验参数的顺序。如下将标识使用AuthCheckSequence分组的参数将按照用户类型、用户名、密码的顺序进行校验。

@GroupSequence({AuthCheckSequence.UserTypeCheck.class, AuthCheckSequence.UsernameCheck.class, AuthCheckSequence.PasswordCheck.class})
public interface AuthCheckSequence {

    /**
     * 用户类型
     */
    interface UserTypeCheck {};

    /**
     * 用户名校验
     */
    interface UsernameCheck {};

    /**
     * 密码校验
     */
    interface PasswordCheck {};
}

LocalAuthDTO

@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class LocalAuthDTO {

     /**
     * 用户类型 1.用户 2.商家 3.管理员,目前仅支持用户和商家类型注册
     */
    @NotNull(message = "用户类型不能为空",groups = AuthCheckSequence.UserTypeCheck.class)
    @Range(min = 1,max = 3,message = "用户类型不合法",groups =         
 AuthCheckSequence.UserTypeCheck.class)
    private Integer userType;

    /**
     * 用户名
     */
    @NotBlank(message = "用户名不能为空",groups = AuthCheckSequence.UsernameCheck.class)
    @Pattern(regexp = "^[a-zA-Z0-9]{3,8}$", message = "用户名必须由3-8个字母或数字组成",
    groups = AuthCheckSequence.UsernameCheck.class)
    private String username;

    /**
     * 密码
     */
    @NotBlank(message = "密码不能为空",groups = AuthCheckSequence.PasswordCheck.class)
    @Size(min = 6,max = 18, message = "密码长度必须在6到18位之间",groups = AuthCheckSequence.PasswordCheck.class)
    private String password;
}

请求参数

化繁为简,使用Hibernate Validator实现参数校验,spring boot,后端,validation,java

 响应结果

化繁为简,使用Hibernate Validator实现参数校验,spring boot,后端,validation,java文章来源地址https://www.toymoban.com/news/detail-652889.html

到了这里,关于化繁为简,使用Hibernate Validator实现参数校验的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C++分治(分而治之)算法:将复杂问题化繁为简

    导语: 在计算机科学领域,分治算法是一种常见且强大的问题求解方法。它将一个复杂的问题分解成若干个规模较小且相互独立的子问题,并通过递归地解决这些子问题来得到最终的结果。本文将介绍C++中实现分治算法的基本原理及示例,帮助读者更好地理解和应用这一算法

    2024年01月25日
    浏览(35)
  • 化繁为简,MyBatis-Plus 里面的增删改查

    在当前盛行的 SpringBoot 项目中,整合持久层这一块,目前主流的有两种:JPA 和 MyBatis-Plus。至于哪个用的更多一些,这个主要还是看每个公司的技术架构,但硬是要说一个最为常用的,我认为是 MyBatis-Plus,而在这里也是对 MyBatis-Plus 的一个使用进行演示 好了,废话不多说,直

    2024年02月04日
    浏览(27)
  • 华为OD机试 - 字符串化繁为简(Java & JS & Python)

    题目描述 给定一个输入字符串,字符串只可能由英文字母( \\\'a\\\' ~ \\\'z\\\'、\\\'A\\\' ~ \\\'Z\\\' )和左右小括号( \\\'(\\\'、\\\')\\\' )组成。 当字符里存在小括号时,小括号是成对的,可以有一个或多个小括号对,小括号对不会嵌套,小括号对内可以包含1个或多个英文字母,也可以不包含英文字母。

    2024年02月09日
    浏览(36)
  • 【C++】万字一文全解【继承】及其特性__[剖析底层化繁为简](20)

    前言 大家好吖,欢迎来到 YY 滴C++系列 ,热烈欢迎! 本章主要内容面向接触过C++的老铁 主要内容含: 欢迎订阅 YY 滴C++专栏!更多干货持续更新!以下是传送门! YY的《C++》专栏 YY的《C++11》专栏 YY的《Linux》专栏 YY的《数据结构》专栏 YY的《C语言基础》专栏 YY的《初学者易

    2024年02月01日
    浏览(30)
  • 化繁为简 面板式空调网关亮相上海智能家居展 智哪儿专访青岛中弘赵哲海

    面对中央空调协议不开放和智能家居协议不统一的问题,青岛中弘选择中央空调控制器这一细分赛道入局智能家居市场,始终贯彻“所有空调,一个网关”的产品技术理念,逐渐探索出一条中弘的发展路径和商业模式。 在2023年的SSHT上海国际智能家居展上,青岛中弘展示了其

    2024年02月09日
    浏览(47)
  • 【腾讯云 TDSQL-C Serverless 产品体验】TDSQL-C MySQL Serverless云数据库化繁为简

    随着互联网的发展,企业的规模也在不断的发展,企业内部的在线业务量也随之骤增,海量的数据访问和存储压力已经日益不满足公司业务的需求了,而且搭建传统集中式数据库也增加运维工作量和公司软硬件成本,对于突发的业务,无法满足更快更稳定的业务性能。 企业级

    2024年02月08日
    浏览(42)
  • Spring Boot使用 Hibernate-Validator校验参数时的长度校验

    今天在使用Validator框架数据验证的时候碰到了三个类似的注解,都是用来限制长度,但是用法上有区别:  @Size是一个Bean验证注释,用于验证关联的String具有的长度受最小值和最大值限制的值.  @Length是一个Hibernate特定的注释,与@Size具有相同的含义; 两者的区别: ​ 用@length限

    2024年02月14日
    浏览(32)
  • Hibernate Validator 组件

    Hibernate Validator 组件介绍 Hibernate Validator 是一个基于 Java 的验证框架,它提供了强大且灵活的验证功能,用于验证 JavaBean 对象的状态。它是基于 JSR 380 规范(Bean Validation 2.0)的实现,并且可以与任何 Java 应用程序集成。 Hibernate Validator 的目标是提供一种方便、易于使用的验证

    2024年02月11日
    浏览(27)
  • 【hibernate validator】(五)分组约束

    https://blog.zysicyj.top/ 定义一个超级跑车 使用组继承 定义序列组 使用序列组 定义一个具有重定义的默认组的类 使用重新定义的默认组 实现和使用默认组序列 必须集合@Valid哦,否则报错 本文由 mdnice 多平台发布

    2024年02月11日
    浏览(28)
  • Hibernate-Validator(数据校验框架)

    hibernate-validator 是 Hibernate 项目中的一个数据校验框架,它能够将数据校验从业务代码中脱离出来,增加代码可读性,同时也让数据校验变得更加方便、简单。 官网地址:http://hibernate.org/validator/documentation Java程序开发中,当你要处理一个程序的业务逻辑时,请求参数的数据校验

    2023年04月27日
    浏览(28)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包