1

我正在尝试验证我的邮政编码,但我想的方法没有奏效,我不明白为什么。

ValidationException我创建了一个验证器,如果它无效则必须抛出一个。

@Service
public class ZipCodeValidator{

    public void validate(String zipCode){
        validateNotEmpty(zipCode);
        validateHasNoSpaces(zipCode);
    }

    private void validateNotEmpty(String zipCode){
       if (zipCode.length() != 0){
           throw new ValidationException("Postal Code can't be empty");
       }
    }

    private void validateHasNoSpaces(String zipCode) {
        if (zipCode.contains(" ")){
            throw new ValidationException("Postal Code can't contain spaces");
        }
    }

}

在我的服务中,我收到邮政编码我想抛出我的自定义异常(我将错误消息传递给它),如下所示:

    try{
        validator.validate(zipCode);
    }catch (ValidationException ex){
        throw new ZipCodeValidationException(ex.getMessage());
    }

但是它似乎不起作用,该异常没有被捕获,因此程序运行得更远。

我究竟做错了什么?

整个方法是错误的吗?你会推荐什么?

这是我的自定义异常

public class ZipCodeValidationException extends Exception{
    public ZipCodeValidationException(String message) {
        super(message);
    }
}
4

2 回答 2

1

嗨,请分两步找到我的答案,首先是正确的,然后是建议的实施方式。

更正:

ObjectUtils.isEmpty(arg)用于检查字符串是否为 0 长度或 null。这是您的代码的修改版本

public interface ZipcodeService {
        void validate(@Zipcode String zipCode) throws ZipCodeValidationException;
    }

    @Service
    public static class ZipcodeServiceImpl implements ZipcodeService {
        private final ZipCodeRegexMatcher zipCodeRegexMatcher;

        public ZipcodeServiceImpl() {
            zipCodeRegexMatcher = new ZipCodeRegexMatcher();
        }

        @Override
        public void validate(String zipCode) throws ZipCodeValidationException {
            // uncomment for Regex Validation
            // boolean valid = zipCodeRegexMatcher.isValid(zipCode);
            // uncomment for Simple text validation
            final boolean valid = !ObjectUtils.isEmpty(zipCode);

            if (!valid) {
                throw new ZipCodeValidationException("Invalid zipcode");
            }
        }
    }

这就是调用者的样子Controller

@GetMapping(path = "dummy")
    public String getDummy(@RequestParam("zipcode") String zipCode) {
        try {
            zipcodeService.validate(zipCode);
            return zipCode;
        } catch (ZipCodeValidationException e) {
            return e.getMessage();
        }
    }

建议方式:

添加以下条目pom.xml

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

创建注释和验证器,如下所示

@Constraint(validatedBy = {ZipcodeValidator.class})
    @Target({ElementType.FIELD, ElementType.PARAMETER})
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Zipcode {
        String message() default "Invalid Zipcode value";

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

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

    public static class ZipcodeValidator implements ConstraintValidator<Zipcode, String> {
        private final ZipCodeRegexMatcher zipCodeRegexMatcher;

        public ZipcodeValidator() {
            zipCodeRegexMatcher = new ZipCodeRegexMatcher();
        }

        @Override
        public boolean isValid(String zipCode, ConstraintValidatorContext constraintValidatorContext) {
            return zipCodeRegexMatcher.isValid(zipCode);
        }
    }

完成此设置后,使用@Validated转到控制器类和带注释的类, 以及您希望使用自定义注释进行验证的字段,即Zipcode我们刚刚创建的。在这种情况下,我们通过扩展ConstraintValidator创建一个自定义验证器 ZipcodeValidator 。

这是调用者的样子:

    @GetMapping
    public String get(@Zipcode @RequestParam("zipcode") String zipCode) {
        return zipCode;
    }

在验证失败时,它会抛出javax.validation.ConstraintViolationException: get.zipCode: Invalid Zipcode value您可以根据需要使用ControllerAdvice自定义的内容。

您还可以@Zipcode在服务级别使用注释,它的工作方式相同。关于ZipCodeRegexMatcher而不是在构造函数中创建它,您可以创建一个 bean 并注入该依赖项。它是一个简单的类,具有邮政编码的正则表达式并执行验证。

public static class ZipCodeRegexMatcher {
        public static final String ZIP_REGEX = "^[0-9]{5}(?:-[0-9]{4})?$";
        private final Pattern pattern;

        public ZipCodeRegexMatcher() {
            pattern = Pattern.compile(ZIP_REGEX);
        }

        public boolean isValid(String zipCode) {
            return pattern.matcher(zipCode).matches();
        }
    }

整个代码位于此处

于 2020-12-31T06:34:10.103 回答
1

我推荐以下内容:

  • 将通用位置中的所有异常作为ExceptionHandler类处理,有关更多详细信息,请参见:https ://www.baeldung.com/exception-handling-for-rest-with-spring
  • 您可以ValidationException从扩展RuntimeException,该方法将允许从 try-catch 结构中卸载代码
  • @Service 注解对于转换器或验证器来说不太合适,因为规则 @Service 类包含业务逻辑,对于帮助程序类将更好地使用 @Component,这两个注解之间没有区别,只了解该组件具有哪一层应用程序

请分享代码以获得更多建议和帮助。

于 2020-12-31T01:22:14.870 回答