在 ConstraintValidator 中访问 ServletContext

Access ServletContext in a ConstraintValidator

我希望使用约束验证器来验证输入。我的问题是我需要 ServletContext 中包含的一些信息,例如属性文件的路径,以验证请求 bean。我发现 Spring 我可以使用 @Autowired 注释,但不幸的是我不能使用这个框架。

约束条件:

@Constraint(validateBy = MyValidationClass.class)
@Target(PARAMETER)
@Retention(RUNTIME)
public @interface  MyValidation {
    ...
}

我希望在约束验证器中做的是这样的:

@Override
public boolean isValid(RequestBean value, ConstraintValidatorContext context) {
    Properties props = servletContext.getAttribute("ws.props")
    // my validation
}

我怎样才能做到这一点?

这可能不是最佳解决方案。 (编辑:最后您可以在我的编辑中找到更好的解决方案)

但我想您可以创建一个 ServletContainerInitializerServletContext 存储在静态变量中并在初始化程序中访问它。

我觉得这里不太好,因为您对静态方法有很深的依赖性。但是否则你可能会找到一种方法来挂钩实例化 ConstraintValidator.

的过程

编辑:我刚刚查阅了 Hibernator Validator 文档。如果您正在使用 Hibernator Validator 实现,我猜这里的这一章对您来说会很有趣:https://docs.jboss.org/hibernate/stable/validator/reference/en-US/html_single/#__code_constraintvalidatorfactory_code

据此,我将创建一个自己的 ConstraintValidatorFactory 和一个新接口 ServletContextAware 以及一个 setter setServletContext(ServletContext)。 然后验证器工厂可以检查应该实例化的 class 是否实现了这个接口并设置 ServletContext。 新的 ConstraintValidatorFactory 可用于创建新的 ValidatorFactory,后者将用于创建所需的验证器。

只是一些 not-checked 代码示例:

interface ServletContextArea {
    public void setServletContext(ServletContext context);
}


public class ServletContextConstraintValidatorFactory implements ConstraintValidatorFactory {
    private ServletContext servletContext;

    public ServletContextConstraintValidatorFactory(ServletContext servletContext) {
        this.servletContext = servletContext;
    }

    @Override
    public <T extends ConstraintValidator<?, ?>> T getInstance(Class<T> key) {
        // create instance from key as validator

        if(validator instanceof ServletContextAware) {
            ((ServletContextAware) validator).setServletContext(this.servletContext);
        }
        //...

        return validator;
    }

    @Override
    public void releaseInstance(ConstraintValidator<?, ?> instance) {
        //...
    }
}

// somewhere in the code where you have the servletContext available
ValidatorFactory validatorFactory = Validation.byDefaultProvider()
    .configure()
    .constraintValidatorFactory( new ServletContextConstraintValidatorFactory(servletContext) )
    .buildValidatorFactory();
Validator validator = validatorFactory.getValidator();