首页 > 解决方案 > Spring boot 在控制器和服务方法之间使用中间件服务方法时跳过自定义验证

问题描述

当我直接从控制器调用服务方法时,我的 @CustomValidation 工作并引发异常。

这是控制器方法

@PostMapping("doSomething")
public CustomInfo doSomething(@RequestBody(required = true) MyParam param) {
    CustomInfo info;
    try {
        info = myService.doSomething(param);
    } catch (Exception e) {
        info = new CustomInfo();
        info.setMessage(e.getMessage());
    }

    return info;
}

这是一个服务方法

public CustomInfo doSomething(@CustomValidation MyParam param) {
    //do something
}

但是,如果我在控制器和验证方法的中间使用另一种服务方法,它会跳过验证。

这是中间件方法示例。假设我们从控制器调用 doSomething1 方法。

public CustomInfo doSomething1(MyParam param) {
    return this.doSomething(param);
}

为什么它会跳过验证?或者我该如何解决?

编辑

这是服务等级

@Service
@Validated
public class MyService {
    //doSomething1 method
    //doSomething method
}

这是控制器类

@RestController
@RequestMapping("rest/myRest")
public class MyRestController {
    //doSomething caller method
}

这是我的自定义验证注释,它检查基于 xsd 模式的类中的必填字段。

@Documented
@Constraint(validatedBy = ParseRequiredFieldValidator.class)
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface ParseRequiredField {
    String message() default "Please fill all required fields";

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

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

    String[] ignoreFields() default {};
}

这是验证器

public class ParseRequiredFieldValidator implements ConstraintValidator<ParseRequiredField, Object> {

    private ParseRequiredField constraint;

    @Override
    public void initialize(ParseRequiredField constraint) {
        this.constraint = constraint;
    }

    @Override
    public boolean isValid(Object value, ConstraintValidatorContext context) {
        Class<?> targetClass = value.getClass();
        List<String> ignoreFields = Arrays.asList(constraint.ignoreFields());

        StringBuilder errors = new StringBuilder();
        Field[] fields = targetClass.getDeclaredFields();
        for (Field field : fields) {
            if(!ignoreFields.contains(field.getName())) {
                XmlElement annotation = field.getAnnotation(XmlElement.class);
                if (annotation != null && (annotation.required() && !annotation.nillable())) {
                    try {
                        field.setAccessible(true);
                        if (field.get(value) == null) {
                            if (errors.length() != 0) {
                                errors.append(" ");
                            }
                            String message = String.format("%s: required field '%s' is null.",
                                    targetClass.getSimpleName(),
                                    field.getName());

                            errors.append(message);
                        }
                    } catch (Exception e) {
                        //e.printStackTrace();
                    }
                }
            }
        }

        if (errors.length() != 0) {
            context.disableDefaultConstraintViolation();
            context.buildConstraintViolationWithTemplate(errors.toString())
                    .addConstraintViolation();
            return false;
        }

        return true;
    }
}

标签: spring-bootvalidation

解决方案


推荐阅读