参数校验的使用

  • 前言
  • 一、何为参数校验?
  • 二、如何进行参数校验
  • 2.1普通参数类型校验
  • 2.2对象类型参数校验
  • 2.3对象中还有对象的校验
  • 2.3自定义注解对参数进行校验
  • 2.3.1 创建一个注解
  • 2.3.2 实现ConstraintValidator接口
  • 总结



前言

在服务端中需要接收前端发送过来的请求并且进行处理,而这些请求往往是附带参数的,对参数的处理是非常重要的一环,下面简单介绍一下使用注解来对参数进行校验


一、何为参数校验?

参数校验,顾名思义就是对请求(url)所附带的参数进行验证。

https://www.baidu.com/s?ie=UTF-8&wd=JSR303

上面这段请求中?后面的内容就是参数(参数是以键值对的形式出现),还有的参数并不会出现在url上,他们会包含在请求体中,通过url是看不到了。

二、如何进行参数校验

2.1普通参数类型校验

在控制器的方法的参数前打上对应的注解,即可对参数进行相应功能的校验。
如要对一个传入的id进行约束,要求不能超过100,相应代码为:

@RestController
@RequestMapping("/banner")
@Validated
public class BannerController {
	@PostMapping("/test/{id}")
   		public String test(@PathVariable @Max(100) int id){
   			return null;
   		}
}

在int id前面打上@Max(100)这个注解,可以实现对id的校验功能,如果请求传入的id值超过了100,那么就会报出相应的错误。

注意:需要在类的前面加上@Validated注解才能够开启校验,只打上@Max注解是不会生效的。

2.2对象类型参数校验

当参数是一个自定义的类时,这是应该怎么样对参数进行校验呢?

需要将注解打在类的成员变量上,然后再控制器方法的参数前打上@Validated注解开启,对类的内部成员进行校验
自定义的类为:

public class PersonDTO {

    @Length(max = 5)
    private String name;

    @Range(min = 18,max = 30)
    private Integer age;
	
	//getter 和 setter
	.....
}

在类的成员变量上打上要验证的注解

控制器的方法为:

@PostMapping("/test/{id}")
    public String test(@PathVariable @Max(10) int id,
                        @RequestBody @Validated PersonDTO personDTO){
        return null;
    }

需要在personDTO这个参数前打上@Validated注解,开启对自定义类型的成员进行校验

2.3对象中还有对象的校验

在上面对象校验的基础上,PersonDTO增加一个成员变量,也是自定义的类型。

public class PersonDTO {

    @Length(max = 5)
    private String name;

    @Range(min = 18,max = 30)
    private Integer age;
	
	@Valid
    private SchoolDTO schoolDTO;
    
	//getter 和 setter
	.....
}

public class SchoolDTO {

    @Length(min = 2)
    private String schoolName;
    
	//getter 和 setter
	.....
}

schoolName这个成员变量打上需要校验的注解,schoolDTO这个成员变量需要打上@Valid注解

2.3自定义注解对参数进行校验

在一些特定业务中,普通注解不能够满足特定参数的校验,那么就需要自定义一些注解来对参数进行校验。

在app中创建账户需要确认密码,这个过程就需要对两次密码进行校验,这时候就需要自定义一个注解去校验这个两个密码是否一致。实现这个自定义注解的方式主要有两步

2.3.1 创建一个注解
@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = PasswordEqualsValidation.class)
public @interface PasswordEquals {

    String message() default "两次密码不一致";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};

}

@Documented表示该注解中的注释会被写入文档中
@Target(ElementType.TYPE)表示该注解作用在类、接口或枚举上
@Retention(RetentionPolicy.RUNTIME)表示该注解在运行时任然保留
@Constraint(validatedBy = PasswordEqualsValidation.class)是表示该注解关联PasswordEqualsValidation这个类

message是该注解中的成员

2.3.2 实现ConstraintValidator接口
public class PasswordEqualsValidation implements ConstraintValidator<PasswordEquals, PersonDTO> {

    @Override
    public boolean isValid(PersonDTO personDTO, ConstraintValidatorContext constraintValidatorContext) {
        String password1 = personDTO.getPassword1();
        String password2 = personDTO.getPassword2();
        boolean flag = false;
        if(password1 != null && password2 != null && password1.equals(password2)){
            flag = true;
        }
        return flag;
    }
}

创建PasswordEqualsValidation去实现 ConstraintValidator接口,然后重写isValid方法,对密码进行校验,最后和PasswordEquals 注解关联,使得注解具有作用。
ConstraintValidator接口后面有两个参数要填,第一个是要关联的参数,第二个参数是注解要打在哪个地方上,这个地方所对应的类型。

import lombok.*;
import org.hibernate.validator.constraints.Length;

@Setter
@Getter
@PasswordEquals
public class PersonDTO {

    @Length(max = 5)
    private String name;
    private Integer age;

    private String password1;
    private String password2;

}

因为这里是把注解打在PersonDTO 上,所以第二个参数就是PersonDTO 。

重写的isValid方法就是对密码进行验证是否符合要求


总结

参数校验还是比较重要的一块,初期如果能够将这一块内容处理好,将会节省非常多的时间和精力。