ConstraintValidator类如何实现自定义注解校验前端传参

yizhihongxing

要实现自定义注解校验前端传参,需要使用到Java中的ConstraintValidator类。以下是实现的步骤:

  1. 创建自定义注解

首先需要创建一个自定义注解,并定义需要校验的参数和校验条件。下面的示例定义了一个名为CheckPassword的注解,用来校验密码是否符合规定的长度和包含数字、字母和特殊字符:

import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;

@Documented
@Constraint(validatedBy = PasswordValidator.class)
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface CheckPassword {
    String message() default "Invalid password format";
    int minLength() default 6;
    int maxLength() default 20;
    boolean needNumber() default true;
    boolean needLowerCase() default true;
    boolean needUpperCase() default true;
    boolean needSpecialChar() default true;
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}
  1. 创建校验器

通过实现ConstraintValidator接口,我们可以自定义校验逻辑,并将其与注解绑定起来。以下是实现PasswordValidator校验器的示例代码:

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.regex.Pattern;

public class PasswordValidator implements ConstraintValidator<CheckPassword, String> {
    private int minLength;
    private int maxLength;
    private boolean needNumber;
    private boolean needLowerCase;
    private boolean needUpperCase;
    private boolean needSpecialChar;

    @Override
    public void initialize(CheckPassword constraintAnnotation) {
        this.minLength = constraintAnnotation.minLength();
        this.maxLength = constraintAnnotation.maxLength();
        this.needNumber = constraintAnnotation.needNumber();
        this.needLowerCase = constraintAnnotation.needLowerCase();
        this.needUpperCase = constraintAnnotation.needUpperCase();
        this.needSpecialChar = constraintAnnotation.needSpecialChar();
    }

    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        if (value == null || value.isEmpty()) {
            return true; // empty value is valid
        }
        if (value.length() < minLength || value.length() > maxLength) {
            return false;
        }
        if (needNumber && !Pattern.compile("[0-9]").matcher(value).find()) {
            return false;
        }
        if (needLowerCase && !Pattern.compile("[a-z]").matcher(value).find()) {
            return false;
        }
        if (needUpperCase && !Pattern.compile("[A-Z]").matcher(value).find()) {
            return false;
        }
        if (needSpecialChar && !Pattern.compile("[!\"#$%&'()*+,-./:;<=>?@\\[\\\\\\]^_`{|}~]").matcher(value).find()) {
            return false;
        }
        return true;
    }
}

initialize()方法中,我们可以获得注解的参数,以便根据不同的参数设置不同的校验规则。isValid()方法是校验逻辑的核心,返回true表示参数符合要求,而返回false则表示参数不符合要求。

  1. 在Controller中使用自定义注解

当我们需要校验某个Controller方法中的参数时,只需在参数上使用自定义的注解即可。例如,以下示例中的registerUser()方法就使用了CheckPassword注解对密码进行了校验:

import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api")
@Validated // enable validation globally
public class UserController {
    @PostMapping("/register")
    public ResponseEntity<String> registerUser(
            @RequestParam String username,
            @CheckPassword @RequestParam String password,
            @RequestParam String email) {
        // do something...
    }
}

@CheckPassword注解之前加上@Validated注解,可以启用全局参数校验。这样,当前端使用HTTP POST方法调用/api/register接口时,就会对password参数进行校验。如果校验失败,将返回HTTP状态码为400的错误响应,其中包含一个错误消息,消息内容为自定义注解中message属性指定的内容。

  1. 示例说明

示例1:校验数字验证码

对于一个需要使用短信验证码的场景,当我们想要验证用户输入的短信验证码是否正确时,就可以使用自定义注解来实现。定义一个名为CheckSmsCode的注解,用于验证短信验证码是否正确:

import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;

@Documented
@Constraint(validatedBy = SmsCodeValidator.class)
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface CheckSmsCode {
    String message() default "Invalid sms code";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

定义SmsCodeValidator校验器,用于校验短信验证码是否正确:

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

public class SmsCodeValidator implements ConstraintValidator<CheckSmsCode, String> {
    @Override
    public void initialize(CheckSmsCode constraintAnnotation) {
    }

    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        // validate sms code here
        return false; // TODO: implement this
    }
}

在Controller中使用自定义注解:

import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api")
@Validated // enable validation globally
public class SmsController {
    @PostMapping("/verify")
    public ResponseEntity<String> verifySmsCode(
            @RequestParam String phone,
            @CheckSmsCode @RequestParam String smsCode) {
        // do something...
    }
}

示例2:校验密码强度

对于一个需要使用复杂密码的场景,当我们想要验证用户输入的密码是否符合要求时,也可以使用自定义注解来实现。定义一个名为CheckPassword的注解,用于验证密码是否符合要求:

import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;

@Documented
@Constraint(validatedBy = PasswordValidator.class)
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface CheckPassword {
    String message() default "Invalid password format";
    int minLength() default 6;
    int maxLength() default 20;
    boolean needNumber() default true;
    boolean needLowerCase() default true;
    boolean needUpperCase() default true;
    boolean needSpecialChar() default true;
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

定义PasswordValidator校验器,用于校验密码强度是否符合要求:

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.regex.Pattern;

public class PasswordValidator implements ConstraintValidator<CheckPassword, String> {
    private int minLength;
    private int maxLength;
    private boolean needNumber;
    private boolean needLowerCase;
    private boolean needUpperCase;
    private boolean needSpecialChar;

    @Override
    public void initialize(CheckPassword constraintAnnotation) {
        this.minLength = constraintAnnotation.minLength();
        this.maxLength = constraintAnnotation.maxLength();
        this.needNumber = constraintAnnotation.needNumber();
        this.needLowerCase = constraintAnnotation.needLowerCase();
        this.needUpperCase = constraintAnnotation.needUpperCase();
        this.needSpecialChar = constraintAnnotation.needSpecialChar();
    }

    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        if (value == null || value.isEmpty()) {
            return true; // empty value is valid
        }
        if (value.length() < minLength || value.length() > maxLength) {
            return false;
        }
        if (needNumber && !Pattern.compile("[0-9]").matcher(value).find()) {
            return false;
        }
        if (needLowerCase && !Pattern.compile("[a-z]").matcher(value).find()) {
            return false;
        }
        if (needUpperCase && !Pattern.compile("[A-Z]").matcher(value).find()) {
            return false;
        }
        if (needSpecialChar && !Pattern.compile("[!\"#$%&'()*+,-./:;<=>?@\\[\\\\\\]^_`{|}~]").matcher(value).find()) {
            return false;
        }
        return true;
    }
}

在Controller中使用自定义注解:

import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api")
@Validated // enable validation globally
public class UserController {
    @PostMapping("/register")
    public ResponseEntity<String> registerUser(
            @RequestParam String username,
            @CheckPassword @RequestParam String password,
            @RequestParam String email) {
        // do something...
    }
}

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:ConstraintValidator类如何实现自定义注解校验前端传参 - Python技术站

(0)
上一篇 2023年5月29日
下一篇 2023年5月29日

相关文章

  • Vue中computed计算属性和data数据获取方式

    下面是关于Vue中computed计算属性和data数据获取方式的完整攻略。 1. 什么是computed计算属性 在Vue中,computed计算属性是一种特殊的属性。它的值不是直接提供的,而是通过计算而来的。computed计算属性是基于它所依赖的数据属性的值进行计算。当依赖的数据属性的值发生改变时,计算属性的值会自动刷新。 computed计算属性常用…

    Vue 2023年5月28日
    00
  • 详解Vue与VueComponent的关系

    详解 Vue 与 Vue Component 的关系 Vue 是一款流行的前端框架,使用 Vue 可以方便地实现动态数据绑定、组件化以及声明式渲染等功能。而 Vue Component 则是 Vue 框架中组件的概念。本文将详细讲解 Vue 和 Vue Component 的关系,并通过两条示例说明。 Vue 和 Vue Component 的关系 Vue …

    Vue 2023年5月27日
    00
  • 在vue项目中优雅的使用SVG的方法实例详解

    让我来为你详细讲解一下在Vue项目中优雅地使用SVG的方法。 在Vue项目中优雅地使用SVG的方法 什么是SVG? SVG(Scalable Vector Graphics)是一种基于XML语法的矢量图形格式,用于描述二维图形和绘图程序。相对于传统的像素图形格式(如JPG、PNG、BMP等),SVG图像拥有无限的放大缩小比例,因此可以良好地适应各种分辨率的设…

    Vue 2023年5月28日
    00
  • Vue项目打包优化实践指南(推荐!)

    我来为您详细讲解一下“Vue项目打包优化实践指南(推荐!)”的完整攻略。 1. 引言 Vue.js 是目前比较流行的前端框架之一,但是它在打包构建时会生成大量的文件,导致构建时间比较长,而且更占用服务器资源。因此,为了加快项目的运行速度,并降低服务器的负载,我们需要对 Vue 项目进行打包优化。 2. 打包优化实践指南 2.1 开启 gzip 压缩 优先考虑…

    Vue 2023年5月28日
    00
  • 使用vue3搭建后台系统的详细步骤

    使用Vue3搭建后台系统的详细步骤: 1. 安装Vue CLI 使用Vue CLI可以帮助我们快速地搭建Vue项目环境,可以使用以下命令安装: npm install -g @vue/cli 2. 创建项目 可以使用以下命令创建一个基于Vue3的项目: vue create my-project 3. 安装其他依赖 除了Vue CLI生成的默认依赖外,我们还…

    Vue 2023年5月27日
    00
  • 详解vue 组件之间使用eventbus传值

    下面是详解vue组件之间使用eventbus传值的完整攻略: 什么是event bus event bus 是Vue.js内置的一个在组件之间通信的机制,它可以让组件之间的通信变得更加简单方便。event bus是一个可以充当中央事件处理器的实例,可以用它来触发事件、监听事件或广播事件。 在组件中使用event bus 在Vue中使用event bus的步骤…

    Vue 2023年5月29日
    00
  • vue如何动态绑定img的src属性(v-bind)

    在Vue中,可以使用v-bind指令动态绑定HTML元素的属性。对于img标签的src属性,我们也可以使用v-bind进行动态绑定。 具体实现步骤如下: 绑定数据到Vue实例的data中 首先,需要将图片的URL地址存储在Vue实例的data中,作为动态绑定的数据。例如: <template> <div> <img :src=&…

    Vue 2023年5月28日
    00
  • vue axios post发送复杂对象问题

    当使用 Vue.js 结合 axios 提交一个复杂对象时,我们可能会遇到一个问题,即该请求传输时无法正确解析该对象。这可能是因为该对象被序列化成了字符串,导致后端无法正确解析该请求。下面将详细介绍如何解决这一问题。 问题原因 axios 内部使用了 JSON.stringify 将该对象进行序列化,并将其存储在请求正文中。这样,后端无法正确解析该请求。 解…

    Vue 2023年5月28日
    00
合作推广
合作推广
分享本页
返回顶部