JSR380验证框架

依赖

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

demo

@Size(min=10,max=200 ,message="描述需要控制在10到200字符"@Min(value=18,message="年龄不能小于18")
@Max(value=150,message="年龄不能大于150")
list<@NotBlank String> roles; 
      
public Optional<@Past localdate> getDateOfBirth(){
	return Optional.of(dateofBirth)
}

常用的验证注解

  • @NotNull 论证注解的属性值不是空的。
  • @AssertTrue 验证注解的属性值是否为真。
  • @Size 验证注解的属性值的大小介于属性min和max之间;可应用于string,collection,map和数组属性。
  • @Min 验证注解属性的值不小于值属性的值
  • @Max 验证被注解的属性的值不大于值属性的值
  • @Email 验证注解的属性是一个有效的电子邮件地址。
  • @Pattern 验证注解的属性是否匹配正则表达式
  • @NotEmpty 验证属性不是空或空;可以应用于string,collection,map或array值。
  • @NotBlank 只能应用于文本值,并验证该属性不是空的或空白的。
  • @Positive 和 @PositiveOrZero 适用于数值,并验证它们是严格意义上的正数,或包括0在内的正数
  • @Negative 和 @NegativeOrZero 适用于数值,并脸证它们是严格意上的负值,或包括0在内的负值。
  • @Past 和 @PastOrPresent 验证一个日期值是在过去或过去(包括现在),可应用于日期类型,包括在JAVA中新增的日期类型。
  • @Futuren 和 @FutureOrPresent 验证一个日期值是在未来,或者说是在未来,包括现在。

基础使用

domain

@Data
public class UserDto implements Serializable {
    @NotNull
    @NotBlank
    @Size(min = 4, max = 50, message = "用户名长度必须在4到50个字符之间")
    private String username;

    @NotNull
    @NotBlank
    @Size(min = 4, max = 50, message = "用户密码长度必须在4到50个字符之间")
    private String password;

    @NotNull
    @NotBlank
    @Size(min = 4, max = 50, message = "用户密码长度必须在4到50个字符之间")
    private String matchingPassword;

    @NotNull
    @NotBlank
    @Email
//正则验证邮箱格式    @Pattern(regexp = "^[_A-Za-z0-9-\\+]+(\\.[_A-Za-z0-9-]+)*@" + "[A-Za-z0-9-]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$")
    private String email;

    @NotNull
    @NotBlank
    @Size(min = 4, max = 50, message = "姓名长度必须在4到50个字符之间")
    private String name;
}

controller

@RestController
@RequestMapping("/authorize")
public class AuthorizeResource {

    //需要加@Valid使验证生效
    @PostMapping("/register")
    public UserDto register(@Valid @RequestBody UserDto userDto) {
        return userDto;
    }

}

结果

{
    "username": "zhangsan",
    "password": "qwerty12345T!",
    "matchingPassword": "12345678",
    "email": "zs@local.top",
    "name": "张三李四"
}
{
  "timestamp": "2024-03-06T08:39:48.102+00:00",
  "status": 400,
  "error": "Bad Request",
  "trace": " rejected value [张三李四111111111111111111111111111111111111111111111111111111111111111111]; codes [Size.userDto.name,Size.name,Size.java.lang.String,Size]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [userDto.name,name]; arguments []; default message [name],50,4]; default message [姓名长度必须在4到50个字符之间]] \r\n\tat ",
    "message": "Validation failed for object='userDto'. Error count: 1",
    "errors": [
        {
            "codes": [
                "Size.userDto.name",
                "Size.name",
                "Size.java.lang.String",
                "Size"
            ],
            "arguments": [
                {
                    "codes": [
                        "userDto.name",
                        "name"
                    ],
                    "arguments": null,
                    "defaultMessage": "name",
                    "code": "name"
                },
                50,
                4
            ],
            "defaultMessage": "姓名长度必须在4到50个字符之间",
            "objectName": "userDto",
            "field": "name",
            "rejectedValue": "张三李四111111111111111111111111111111111111111111111111111111111111111111",
            "bindingFailure": false,
            "code": "Size"
        }
    ],
    "path": "/authorize/register"
}

自定义验证规则

demo1 邮箱验证
1、定义注解

@Target({ TYPE, FIELD, ANNOTATION_TYPE })
@Retention(RUNTIME)
@Constraint(validatedBy = EmailValidator.class) //指定验证器类
@Documented
public @interface ValidEmail {

    String message() default "{ValidEmail.email}";

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

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

2、验证器
实现ConstraintValidator接口

public class EmailValidator implements ConstraintValidator<ValidEmail, String> {
    private static final String EMAIL_PATTERN = "^[_A-Za-z0-9-\\+]+(\\.[_A-Za-z0-9-]+)*@" + "[A-Za-z0-9-]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$";

    @Override
    public void initialize(final ValidEmail constraintAnnotation) {}

    @Override
    public boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext) {
        return validateEmail(s);
    }

    private boolean validateEmail(String s) {
        Pattern pattern = Pattern.compile(EMAIL_PATTERN);
        Matcher matcher = pattern.matcher(s);
        return matcher.matches();
    }
}

3、加上注解

    @NotNull
    @NotBlank
    @ValidEmail(message = "邮箱格式不正确")
//    @Email
//    @Pattern(regexp = "^[_A-Za-z0-9-\\+]+(\\.[_A-Za-z0-9-]+)*@" + "[A-Za-z0-9-]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$")
    private String email;

结果

{
  "timestamp": "2024-03-06T08:54:06.189+00:00",
  "status": 400,
  "error": "Bad Request",
  "trace": "codes [userDto.email,email]; arguments []; default message [email]]; default message [邮箱格式不正确]] \r\n\tat ",
    "message": "Validation failed for object='userDto'. Error count: 1",
    "errors": [
        {
            "codes": [
                "ValidEmail.userDto.email",
                "ValidEmail.email",
                "ValidEmail.java.lang.String",
                "ValidEmail"
            ],
            "arguments": [
                {
                    "codes": [
                        "userDto.email",
                        "email"
                    ],
                    "arguments": null,
                    "defaultMessage": "email",
                    "code": "email"
                }
            ],
            "defaultMessage": "邮箱格式不正确",
            "objectName": "userDto",
            "field": "email",
            "rejectedValue": "zs@local",
            "bindingFailure": false,
            "code": "ValidEmail"
        }
    ],
    "path": "/authorize/register"
}

密码的验证规则

  • 密码的验证比较复杂,使用passay框架进行验证
  • 封装验证逻辑在注解中,有效的剥离验证逻辑和业务逻辑
  • 对于2个以上属性的复合验证,可以写一个应用于类的注解
<dependency>
  <groupId>org.passay</groupId>
  <artifactId>passay</artifactId>
  <version>1.6.0</version>
</dependency>

注解

@Documented
@Constraint(validatedBy = PasswordConstraintValidator.class)
@Target({ TYPE, FIELD, ANNOTATION_TYPE })
@Retention(RUNTIME)
public @interface ValidPassword {

    String message() default "Invalid Password";

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

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

}

验证器

public class PasswordConstraintValidator implements ConstraintValidator<ValidPassword, String> {

    @Override
    public void initialize(ValidPassword constraintAnnotation) {
    }

    @Override
    public boolean isValid(String password, ConstraintValidatorContext constraintValidatorContext) {
        PasswordValidator validator = new PasswordValidator(List.of(// 长度规则:8 - 30 位
                new LengthRule(8, 30),
                // 至少有一个大写字母
                new CharacterRule(EnglishCharacterData.UpperCase, 1),
                // 至少有一个小写字母
                new CharacterRule(EnglishCharacterData.LowerCase, 1),
                // 至少有一个数字
                new CharacterRule(EnglishCharacterData.Digit, 1),
                // 至少有一个特殊字符
                new CharacterRule(EnglishCharacterData.Special, 1),
                // 不允许连续 3 个字母,按字母表顺序
                // alphabetical is of the form 'abcde', numerical is '34567', qwery is 'asdfg'
                // the false parameter indicates that wrapped sequences are allowed; e.g. 'xyzabc'
                new IllegalSequenceRule(EnglishSequenceData.Alphabetical, 5, false),
                // 不允许 3 个连续数字
                new IllegalSequenceRule(EnglishSequenceData.Numerical, 5, false),
                // 不允许 QWERTY 键盘上的三个连续相邻的按键所代表的字符
                new IllegalSequenceRule(EnglishSequenceData.USQwerty, 5, false),
                // 不允许包含空格
                new WhitespaceRule()));
        RuleResult validate = validator.validate(new PasswordData(password));
        if (validate.isValid()) {
            return true;
        }
        return false;
    }
}

domain

@Data
public class UserDto implements Serializable {
    @NotNull
    @NotBlank
    @Size(min = 4, max = 50, message = "用户名长度必须在4到50个字符之间")
    private String username;

    @NotNull
    @ValidPassword
    private String password;

    @NotNull
    @ValidPassword
    private String matchingPassword;

    @NotNull
    @NotBlank
    @ValidEmail(message = "邮箱格式不正确")
    //    @Email
    //    @Pattern(regexp = "^[_A-Za-z0-9-\\+]+(\\.[_A-Za-z0-9-]+)*@" + "[A-Za-z0-9-]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$")
    private String email;

    @NotNull
    @NotBlank
    @Size(min = 4, max = 50, message = "姓名长度必须在4到50个字符之间")
    private String name;
}

结果

{
  "timestamp": "2024-03-06T09:23:38.543+00:00",
  "status": 400,
  "error": "Bad Request",
  "trace": "",
    "message": "Validation failed for object='userDto'. Error count: 3",
    "errors": [
        {
            "codes": [
                "ValidPassword.userDto.password",
                "ValidPassword.password",
                "ValidPassword.java.lang.String",
                "ValidPassword"
            ],
            "arguments": [
                {
                    "codes": [
                        "userDto.password",
                        "password"
                    ],
                    "arguments": null,
                    "defaultMessage": "password",
                    "code": "password"
                }
            ],
            "defaultMessage": "Invalid Password",
            "objectName": "userDto",
            "field": "password",
            "rejectedValue": "qwerty12345T!",
            "bindingFailure": false,
            "code": "ValidPassword"
        },
        {
            "codes": [
                "ValidEmail.userDto.email",
                "ValidEmail.email",
                "ValidEmail.java.lang.String",
                "ValidEmail"
            ],
            "arguments": [
                {
                    "codes": [
                        "userDto.email",
                        "email"
                    ],
                    "arguments": null,
                    "defaultMessage": "email",
                    "code": "email"
                }
            ],
            "defaultMessage": "邮箱格式不正确",
            "objectName": "userDto",
            "field": "email",
            "rejectedValue": "zs@local",
            "bindingFailure": false,
            "code": "ValidEmail"
        },
        {
            "codes": [
                "ValidPassword.userDto.matchingPassword",
                "ValidPassword.matchingPassword",
                "ValidPassword.java.lang.String",
                "ValidPassword"
            ],
            "arguments": [
                {
                    "codes": [
                        "userDto.matchingPassword",
                        "matchingPassword"
                    ],
                    "arguments": null,
                    "defaultMessage": "matchingPassword",
                    "code": "matchingPassword"
                }
            ],
            "defaultMessage": "Invalid Password",
            "objectName": "userDto",
            "field": "matchingPassword",
            "rejectedValue": "12345678",
            "bindingFailure": false,
            "code": "ValidPassword"
        }
    ],
    "path": "/authorize/register"
}

密码是否一致验证

@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Constraint(validatedBy = PasswordMatchesValidator.class)
public @interface PasswordMatches {
    String message() default "{javax.validation.constraints.NotNull.message}";

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

    Class<? extends Payload>[] payload() default {};
}
public class PasswordMatchesValidator implements ConstraintValidator<PasswordMatches, UserDto> {


    @Override
    public void initialize(PasswordMatches constraintAnnotation) {
    }

    @Override
    public boolean isValid(UserDto userDto, ConstraintValidatorContext constraintValidatorContext) {

        return Objects.equals(userDto.getPassword(), userDto.getMatchingPassword());
    }
}
@PasswordMatches(message = "密码不一致")
@Data
public class UserDto implements Serializable {
    @NotNull
    @NotBlank
    @Size(min = 4, max = 50, message = "用户名长度必须在4到50个字符之间")
    private String username;

    @NotNull
    @ValidPassword
    private String password;

    @NotNull
//    @ValidPassword
    private String matchingPassword;

    @NotNull
    @NotBlank
    @ValidEmail(message = "邮箱格式不正确")
//    @Email
//    @Pattern(regexp = "^[_A-Za-z0-9-\\+]+(\\.[_A-Za-z0-9-]+)*@" + "[A-Za-z0-9-]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$")
    private String email;

    @NotNull
    @NotBlank
    @Size(min = 4, max = 50, message = "姓名长度必须在4到50个字符之间")
    private String name;
}

passay 异常的国际化

  • 创建一个消息解析器
  • 配置验证器使用消息解析器
  • 在对应的注解中写消息的键值
@Configuration
@RequiredArgsConstructor
public class WebMvcConfig implements WebMvcConfigurer {

    private final MessageSource messageSource;

    /**
     * 配置 Passay 使用 Spring 的 MessageSource
     * @return
     */
    @Bean
    public MessageResolver messageResolver(){
        return new SpringMessageResolver(messageSource);
    }

    /**
     * 配置 Java Validation 使用国际化的消息资源
     * @return
     */
    @Bean
    public LocalValidatorFactoryBean getValidator(){
        LocalValidatorFactoryBean factoryBean = new LocalValidatorFactoryBean();
        factoryBean.setValidationMessageSource(messageSource);
        return factoryBean;

    }
}
@RequiredArgsConstructor
public class PasswordConstraintValidator implements ConstraintValidator<ValidPassword, String> {

    private final SpringMessageResolver springMessageResolver;

    @Override
    public void initialize(ValidPassword constraintAnnotation) {
    }

    @Override
    public boolean isValid(String password, ConstraintValidatorContext context) {
        PasswordValidator validator = new PasswordValidator(springMessageResolver,List.of(// 长度规则:8 - 30 位
                new LengthRule(8, 30),
                // 至少有一个大写字母
                new CharacterRule(EnglishCharacterData.UpperCase, 1),
                // 至少有一个小写字母
                new CharacterRule(EnglishCharacterData.LowerCase, 1),
                // 至少有一个数字
                new CharacterRule(EnglishCharacterData.Digit, 1),
                // 至少有一个特殊字符
                new CharacterRule(EnglishCharacterData.Special, 1),
                // 不允许连续 3 个字母,按字母表顺序
                // alphabetical is of the form 'abcde', numerical is '34567', qwery is 'asdfg'
                // the false parameter indicates that wrapped sequences are allowed; e.g. 'xyzabc'
                new IllegalSequenceRule(EnglishSequenceData.Alphabetical, 5, false),
                // 不允许 3 个连续数字
                new IllegalSequenceRule(EnglishSequenceData.Numerical, 5, false),
                // 不允许 QWERTY 键盘上的三个连续相邻的按键所代表的字符
                new IllegalSequenceRule(EnglishSequenceData.USQwerty, 5, false),
                // 不允许包含空格
                new WhitespaceRule()));

        RuleResult validate = validator.validate(new PasswordData(password));
        if (validate.isValid()) {
            return true;
        }
        context.disableDefaultConstraintViolation();
        context.buildConstraintViolationWithTemplate(String.join(",", validator.getMessages(validate)))
                .addConstraintViolation();
        return false;
    }
}

配置文件
image.png

messages.properties

# Passay properties
HISTORY_VIOLATION=Password matches one of {0} previous passwords.
ILLEGAL_WORD=Password contains the dictionary word '{0}'.
ILLEGAL_WORD_REVERSED=Password contains the reversed dictionary word '{0}'.
ILLEGAL_DIGEST_WORD=Password contains a dictionary word.
ILLEGAL_DIGEST_WORD_REVERSED=Password contains a reversed dictionary word.
ILLEGAL_MATCH=Password matches the illegal pattern '{0}'.
ALLOWED_MATCH=Password must match pattern '{0}'.
ILLEGAL_CHAR=Password {1} the illegal character '{0}'.
ALLOWED_CHAR=Password {1} the illegal character '{0}'.
ILLEGAL_QWERTY_SEQUENCE=Password contains the illegal QWERTY sequence '{0}'.
ILLEGAL_ALPHABETICAL_SEQUENCE=Password contains the illegal alphabetical sequence '{0}'.
ILLEGAL_NUMERICAL_SEQUENCE=Password contains the illegal numerical sequence '{0}'.
ILLEGAL_USERNAME=Password {1} the user id '{0}'.
ILLEGAL_USERNAME_REVERSED=Password {1} the user id '{0}' in reverse.
ILLEGAL_WHITESPACE=Password {1} a whitespace character.
ILLEGAL_NUMBER_RANGE=Password {1} the number '{0}'.
ILLEGAL_REPEATED_CHARS=Password contains {2} sequences of {0} or more repeated characters, but only {1} allowed: {3}.
INSUFFICIENT_UPPERCASE=Password must contain {0} or more uppercase characters.
INSUFFICIENT_LOWERCASE=Password must contain {0} or more lowercase characters.
INSUFFICIENT_ALPHABETICAL=Password must contain {0} or more alphabetical characters.
INSUFFICIENT_DIGIT=Password must contain {0} or more digit characters.
INSUFFICIENT_SPECIAL=Password must contain {0} or more special characters.
INSUFFICIENT_CHARACTERISTICS=Password matches {0} of {2} character rules, but {1} are required.
INSUFFICIENT_COMPLEXITY=Password meets {1} complexity rules, but {2} are required.
INSUFFICIENT_COMPLEXITY_RULES=No rules have been configured for a password of length {0}.
SOURCE_VIOLATION=Password cannot be the same as your {0} password.
TOO_LONG=Password must be no more than {1} characters in length.
TOO_SHORT=Password must be {0} or more characters in length.
TOO_MANY_OCCURRENCES=Password contains {1} occurrences of the character '{0}', but at most {2} are allowed.

jakarta.validation.constraints.AssertFalse.message     = must be false
jakarta.validation.constraints.AssertTrue.message      = must be true
jakarta.validation.constraints.DecimalMax.message      = must be less than ${inclusive == true ? 'or equal to ' : ''}{value}
jakarta.validation.constraints.DecimalMin.message      = must be greater than ${inclusive == true ? 'or equal to ' : ''}{value}
jakarta.validation.constraints.Digits.message          = numeric value out of bounds (<{integer} digits>.<{fraction} digits> expected)
jakarta.validation.constraints.Email.message           = must be a well-formed email address
jakarta.validation.constraints.Future.message          = must be a future date
jakarta.validation.constraints.FutureOrPresent.message = must be a date in the present or in the future
jakarta.validation.constraints.Max.message             = must be less than or equal to {value}
jakarta.validation.constraints.Min.message             = must be greater than or equal to {value}
jakarta.validation.constraints.Negative.message        = must be less than 0
jakarta.validation.constraints.NegativeOrZero.message  = must be less than or equal to 0
jakarta.validation.constraints.NotBlank.message        = must not be blank
jakarta.validation.constraints.NotEmpty.message        = must not be empty
jakarta.validation.constraints.NotNull.message         = must not be null
jakarta.validation.constraints.Null.message            = must be null
jakarta.validation.constraints.Past.message            = must be a past date
jakarta.validation.constraints.PastOrPresent.message   = must be a date in the past or in the present
jakarta.validation.constraints.Pattern.message         = must match "{regexp}"
jakarta.validation.constraints.Positive.message        = must be greater than 0
jakarta.validation.constraints.PositiveOrZero.message  = must be greater than or equal to 0
jakarta.validation.constraints.Size.message            = size must be between {min} and {max}

org.hibernate.validator.constraints.CreditCardNumber.message        = invalid credit card number
org.hibernate.validator.constraints.Currency.message                = invalid currency (must be one of {value})
org.hibernate.validator.constraints.EAN.message                     = invalid {type} barcode
org.hibernate.validator.constraints.Email.message                   = not a well-formed email address
org.hibernate.validator.constraints.ISBN.message                    = invalid ISBN
org.hibernate.validator.constraints.Length.message                  = length must be between {min} and {max}
org.hibernate.validator.constraints.CodePointLength.message         = length must be between {min} and {max}
org.hibernate.validator.constraints.LuhnCheck.message               = the check digit for ${validatedValue} is invalid, Luhn Modulo 10 checksum failed
org.hibernate.validator.constraints.Mod10Check.message              = the check digit for ${validatedValue} is invalid, Modulo 10 checksum failed
org.hibernate.validator.constraints.Mod11Check.message              = the check digit for ${validatedValue} is invalid, Modulo 11 checksum failed
org.hibernate.validator.constraints.ModCheck.message                = the check digit for ${validatedValue} is invalid, {modType} checksum failed
org.hibernate.validator.constraints.Normalized.message              = must be normalized
org.hibernate.validator.constraints.NotBlank.message                = may not be empty
org.hibernate.validator.constraints.NotEmpty.message                = may not be empty
org.hibernate.validator.constraints.ParametersScriptAssert.message  = script expression "{script}" didn't evaluate to true
org.hibernate.validator.constraints.Range.message                   = must be between {min} and {max}
org.hibernate.validator.constraints.ScriptAssert.message            = script expression "{script}" didn't evaluate to true
org.hibernate.validator.constraints.UniqueElements.message          = must only contain unique elements
org.hibernate.validator.constraints.URL.message                     = must be a valid URL

org.hibernate.validator.constraints.br.CNPJ.message                 = invalid Brazilian corporate taxpayer registry number (CNPJ)
org.hibernate.validator.constraints.br.CPF.message                  = invalid Brazilian individual taxpayer registry number (CPF)
org.hibernate.validator.constraints.br.TituloEleitoral.message      = invalid Brazilian Voter ID card number

org.hibernate.validator.constraints.pl.REGON.message                = invalid Polish Taxpayer Identification Number (REGON)
org.hibernate.validator.constraints.pl.NIP.message                  = invalid VAT Identification Number (NIP)
org.hibernate.validator.constraints.pl.PESEL.message                = invalid Polish National Identification Number (PESEL)

org.hibernate.validator.constraints.time.DurationMax.message        = must be shorter than${inclusive == true ? ' or equal to' : ''}${days == 0 ? '' : days == 1 ? ' 1 day' : ' ' += days += ' days'}${hours == 0 ? '' : hours == 1 ? ' 1 hour' : ' ' += hours += ' hours'}${minutes == 0 ? '' : minutes == 1 ? ' 1 minute' : ' ' += minutes += ' minutes'}${seconds == 0 ? '' : seconds == 1 ? ' 1 second' : ' ' += seconds += ' seconds'}${millis == 0 ? '' : millis == 1 ? ' 1 milli' : ' ' += millis += ' millis'}${nanos == 0 ? '' : nanos == 1 ? ' 1 nano' : ' ' += nanos += ' nanos'}
org.hibernate.validator.constraints.time.DurationMin.message        = must be longer than${inclusive == true ? ' or equal to' : ''}${days == 0 ? '' : days == 1 ? ' 1 day' : ' ' += days += ' days'}${hours == 0 ? '' : hours == 1 ? ' 1 hour' : ' ' += hours += ' hours'}${minutes == 0 ? '' : minutes == 1 ? ' 1 minute' : ' ' += minutes += ' minutes'}${seconds == 0 ? '' : seconds == 1 ? ' 1 second' : ' ' += seconds += ' seconds'}${millis == 0 ? '' : millis == 1 ? ' 1 milli' : ' ' += millis += ' millis'}${nanos == 0 ? '' : nanos == 1 ? ' 1 nano' : ' ' += nanos += ' nanos'}

ValidEmail.email=Invalid Email
PasswordMatches.userDto=Passwords do not match
login.page.title=Login
login.page.logout.msg=You have logged out.
login.page.bad-credential=Username or password is wrong
login.page.form.username=Username
login.page.form.password=Password
login.page.form.submit=Login
index.page.menu.sign-out=Sign Out
login.page.form.remember-me=Remember me

messages_zh_CN.properties

# Passay 属性
HISTORY_VIOLATION=密码和您最近用过的 {0} 个密码之一重复。
ILLEGAL_WORD=密码包含了黑名单字典中的词 {0}ILLEGAL_WORD_REVERSED=密码包含了保留字典中的词 {0}ILLEGAL_DIGEST_WORD=密码包含了字典中的词。
ILLEGAL_DIGEST_WORD_REVERSED=密码包含了保留字典中的词。
ILLEGAL_MATCH=密码匹配了非法结构 {0}ALLOWED_MATCH=密码必须要匹配结构 {0}ILLEGAL_CHAR=密码 {1} 非法字符 {0}ALLOWED_CHAR=密码 {1} 非法字符 {0}ILLEGAL_QWERTY_SEQUENCE=密码包含非法的QWERTY序列 {0}ILLEGAL_ALPHABETICAL_SEQUENCE=密码包含非法的字母序列 {0}ILLEGAL_NUMERICAL_SEQUENCE=密码包含非法的数字序列 {0}ILLEGAL_USERNAME=密码 {1} 用户 id {0}ILLEGAL_USERNAME_REVERSED=密码 {1} 倒序的用户 id {0}ILLEGAL_WHITESPACE=密码 {1} 空格。
ILLEGAL_NUMBER_RANGE=密码 {1} 数字 {0}.
ILLEGAL_REPEATED_CHARS=密码中包含 {2} 序列 {0} 的一个或多个重复字符, 但仅允许 {1}: {3}INSUFFICIENT_UPPERCASE=密码中必须包含至少 {0} 个大写字母。
INSUFFICIENT_LOWERCASE=密码中必须包含至少 {0} 个小写字母。
INSUFFICIENT_ALPHABETICAL=密码中必须包含至少 {0} 个字母。
INSUFFICIENT_DIGIT=密码中必须包含至少 {0} 个数字。
INSUFFICIENT_SPECIAL=密码中必须包含至少 {0} 个特殊字符。
INSUFFICIENT_CHARACTERISTICS=密码匹配了 {0} of {2} 字符规则, 但只允许 {1} 个。
INSUFFICIENT_COMPLEXITY=密码符合了 {1} 个复杂规则, 但需要符合 {2} 个。
INSUFFICIENT_COMPLEXITY_RULES=对于密码长度 {0},没有配置规则。
SOURCE_VIOLATION=密码不能和之前的 {0} 个历史密码相同。
TOO_LONG=密码长度不能超过 {1} 个字符。
TOO_SHORT=密码长度不能少于 {0} 个字符。
TOO_MANY_OCCURRENCES=密码包含 {1}{0}, 但是至多只允许 {2} 个。

jakarta.validation.constraints.AssertFalse.message     = 只能为false
jakarta.validation.constraints.AssertTrue.message      = 只能为true
jakarta.validation.constraints.DecimalMax.message      = 必须小于或等于{value}
jakarta.validation.constraints.DecimalMin.message      = 必须大于或等于{value}
jakarta.validation.constraints.Digits.message          = 数字的值超出了允许范围(只允许在{integer}位整数和{fraction}位小数范围内)
jakarta.validation.constraints.Email.message           = 不是一个合法的电子邮件地址
jakarta.validation.constraints.Future.message          = 需要是一个将来的时间
jakarta.validation.constraints.FutureOrPresent.message = 需要是一个将来或现在的时间
jakarta.validation.constraints.Max.message             = 最大不能超过{value}
jakarta.validation.constraints.Min.message             = 最小不能小于{value}
jakarta.validation.constraints.Negative.message        = 必须是负数
jakarta.validation.constraints.NegativeOrZero.message  = 必须是负数或零
jakarta.validation.constraints.NotBlank.message        = 不能为空
jakarta.validation.constraints.NotEmpty.message        = 不能为空
jakarta.validation.constraints.NotNull.message         = 不能为null
jakarta.validation.constraints.Null.message            = 必须为null
jakarta.validation.constraints.Past.message            = 需要是一个过去的时间
jakarta.validation.constraints.PastOrPresent.message   = 需要是一个过去或现在的时间
jakarta.validation.constraints.Pattern.message         = 需要匹配正则表达式"{regexp}"
jakarta.validation.constraints.Positive.message        = 必须是正数
jakarta.validation.constraints.PositiveOrZero.message  = 必须是正数或零
jakarta.validation.constraints.Size.message            = 个数必须在{min}{max}之间

org.hibernate.validator.constraints.CreditCardNumber.message        = 不合法的信用卡号码
org.hibernate.validator.constraints.Currency.message                = 不合法的货币 (必须是{value}其中之一)
org.hibernate.validator.constraints.EAN.message                     = 不合法的{type}条形码
org.hibernate.validator.constraints.Email.message                   = 不是一个合法的电子邮件地址
org.hibernate.validator.constraints.Length.message                  = 长度需要在{min}{max}之间
org.hibernate.validator.constraints.CodePointLength.message         = 长度需要在{min}{max}之间
org.hibernate.validator.constraints.LuhnCheck.message               = ${validatedValue}的校验码不合法, Luhn10校验和不匹配
org.hibernate.validator.constraints.Mod10Check.message              = ${validatedValue}的校验码不合法,10校验和不匹配
org.hibernate.validator.constraints.Mod11Check.message              = ${validatedValue}的校验码不合法,11校验和不匹配
org.hibernate.validator.constraints.ModCheck.message                = ${validatedValue}的校验码不合法, {modType}校验和不匹配
org.hibernate.validator.constraints.NotBlank.message                = 不能为空
org.hibernate.validator.constraints.NotEmpty.message                = 不能为空
org.hibernate.validator.constraints.ParametersScriptAssert.message  = 执行脚本表达式"{script}"没有返回期望结果
org.hibernate.validator.constraints.Range.message                   = 需要在{min}{max}之间
org.hibernate.validator.constraints.ScriptAssert.message            = 执行脚本表达式"{script}"没有返回期望结果
org.hibernate.validator.constraints.URL.message                     = 需要是一个合法的URL

org.hibernate.validator.constraints.time.DurationMax.message        = 必须小于${inclusive == true ? '或等于' : ''}${days == 0 ? '' : days += '天'}${hours == 0 ? '' : hours += '小时'}${minutes == 0 ? '' : minutes += '分钟'}${seconds == 0 ? '' : seconds += '秒'}${millis == 0 ? '' : millis += '毫秒'}${nanos == 0 ? '' : nanos += '纳秒'}
org.hibernate.validator.constraints.time.DurationMin.message        = 必须大于${inclusive == true ? '或等于' : ''}${days == 0 ? '' : days += '天'}${hours == 0 ? '' : hours += '小时'}${minutes == 0 ? '' : minutes += '分钟'}${seconds == 0 ? '' : seconds += '秒'}${millis == 0 ? '' : millis += '毫秒'}${nanos == 0 ? '' : nanos += '纳秒'}

ValidEmail.email=非法电子邮件地址
PasswordMatches.userDto=密码输入不一致

login.page.title=登录
login.page.logout.msg=您已退出登录
login.page.bad-credential=用户名或密码不正确
login.page.form.username=用户名
login.page.form.password=密码
login.page.form.submit=登录
index.page.menu.sign-out=退出登录
login.page.form.remember-me=记住我
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值