使用注解的方式完成对前端传递的数据验证

前端传递的数据可能不是我们想要的,比如我们规定用户名和密码不能为空,生日必须为过去时间。以往的做法是拿到这些字段进行判断,然后通过抛异常的方式返回错误信息,十分的繁琐而且需要重复这种操作。有了框架之后,这些框架会对这些操作进行封装,只需要在JavaBean对象的字段上使用对应的注解就能完成这些操作。

1. 自定义javabean某些字段不给前端展示

  • 存在这么一个场景,前端需要查询所有的用户数据,然后我们写了一个方法将所有的数据都返回过去。但是这些数据中有一些敏感信息,比如密码等。这些站在安全方面不应该返回过去。我们应该在返回的时候讲User对象中的password字段隐藏起来。
  • 导入JsonView注解包
import com.fasterxml.jackson.annotation.JsonView;
  • 在User对象中定义两个接口
public class User {
    //简略试图
    public interface UserSimpleView{};
    //详细试图
    public interface UserDetailView extends UserSimpleView{};
    private Integer id;
    private String username;
    private String password;
    private Date birthday;
}

  • 使用@JsonView注解标注字段对应的get方法
    //使用项目试图标注当前get方法,表明只有使用详细试图的时候才会展示用户密码
    @JsonView(UserDetailView.class)
    public String getPassword() {
        return password;
    }
  • 配合controller隐藏password字段的展示
    //这里使用了@JsonView(User.UserSimpleView.class)则表示当前返回数据不包含password字段,
      如果使用@JsonView(UserDetailView.class)则返回数据的时候包含password字段
    @JsonView(User.UserSimpleView.class)
    @PostMapping
    public User create(@Valid @RequestBody User user, BindingResult erros) {
        if (erros.hasErrors()) {
            erros.getAllErrors().stream().forEach(error -> System.out.println(error.getDefaultMessage()));
        }
        System.out.println(user.getUsername());
        System.out.println(user.getPassword());
        System.out.println(user.getId());
        System.out.println(user.getBirthday());
        user.setId(1);
        return user;
    }

2. 使用注解验证javabean对象

  • 这里需要使用到hibernate中的validator,只需要导入对应的依赖就可以。它其中可以完成验证字段的注解如图: image.png
  • 这里只挑选几个了解一下,使用@NotBlank注解标注对应字段,则表示当前字段不能为空。
    @NotBlank(message = "密码不能为空")
    private String password;

  • 使用@Past注解标注当前日期必须为过去时间的日期
    @Past(message = "生日必须是过去的日期")
    private Date birthday;

  • controller配合完成字段的验证
    @PostMapping
    /**
     * 使用@Valid注解标注需要验证的字段,和BindingResult类获取错误信息
     */
    public User create(@Valid @RequestBody User user, BindingResult erros) {
        //当验证字段发生错误时
        if (erros.hasErrors()) {
            //这里是拿到所有的错误遍历错误,打印错误信息。在开发中就可以通过抛出异常将错误返回给前端
            erros.getAllErrors().stream().forEach(error -> System.out.println(error.getDefaultMessage()));
        }
        return user;
    }

3. 自定义验证注解

  • 框架封装的验证字段的注解可能并不能满足我们的需求,那么就需要自定义注解完成字段的验证
  • 自定义类实现ConstraintValidator接口,ConstraintValidator接口中需要使用泛型声明注解名称和需要验证的字段参数类型
public class MyConstraintValidator implements ConstraintValidator<MyConstraint,Object> {
    /**
     * 这里可以注入其他的类,然后使用这个类对传进来的值进行验证
     *
     */
    @Override
    public void initialize(MyConstraint myConstraint) {
        System.out.println("my validator init");
    }

    @Override
    public boolean isValid(Object o, ConstraintValidatorContext constraintValidatorContext) {
	//这里就可以使用注入的其他类对拿到字段的值完成逻辑判断
	  根据判断返回true或false
        System.out.println("校验值"+o);
        return false;
    }
}
  • 定义注解
//Target声明注解可以写在哪些地方
@Target({ElementType.METHOD,ElementType.FIELD})
//Retention声明注解在什么时候启用
@Retention(RetentionPolicy.RUNTIME)
//声明注解使用的校验逻辑是哪个类
@Constraint(validatedBy = MyConstraintValidator.class)
public @interface MyConstraint {
    String message();
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};

}

  • 将自定义注解标注到username字段上
    @MyConstraint(message = "这是一个测试")
    private String username;

  • 当前端使用@Valid验证字段发生错误的时候就会生成对应的错误信息

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×