【问题标题】:How do I use a custom validator with dropwizard?如何使用带有 dropwizard 的自定义验证器?
【发布时间】:2016-06-15 13:52:29
【问题描述】:

我有一个由其他人编写的 REST api,其中处理对特定 url 的请求的方法接受一堆从路径参数填充的参数。

@POST
@Path("/{classid}/{studentid}/details")
@Consumes(MediaType.MULTIPART_FORM_DATA)
@SuppressWarnings("unchecked")


public Response processFile(@FormDataParam("sourceFile") InputStream aStream, @PathParam("classid") String classId, @PathParam("studentid")  String studentId, @Context HttpServletRequest httpRequest) {

// Code to do stuff and return a response
}

写这篇文章的人使用过 DropWizard,我以前没有使用过它的经验。我的任务是通过将 studentId 字段与数据库中的值进行比较来验证它。这将非常简单,但有人告诉我使用自定义验证器来完成。我对编写注释很陌生,但是经过大量挖掘后,我写了这样的注释,

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Constraint(validatedBy = StudentIdValidator.StudentIdValidation.class)

public @interface StudentIdValidator {

    String message() default "{Invalid Id}";

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

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


      class StudentIdValidation implements ConstraintValidator<StudentIdValidator, String> {

        @Override
        public void initialize(StudentIdValidator constraintAnnotation) {
            System.out.println("Annotation initialize !!!!!!!!!");
        }


        @Override
        public boolean isValid(String value, ConstraintValidatorContext context)                                                                            {
                // TODO Auto-generated method stub
                System.out.println("Annotation called");
                return false;
            }
        }
    }

在此之后,我将注释添加到我想像这样运行验证的字段中,

public Response processFile(@FormDataParam("sourceFile") InputStream     aStream, @PathParam("classid") String classId, @StudentIdValidator     @PathParam("studentid")  String studentId, @Context HttpServletRequest     httpRequest)

现在的问题是,当我运行/调试代码时......这个验证器没有被调用,我也不知道如何在 studentId 验证类中获取 studentId 的值。于是我又挖了一些,把它加到了应用文件中

class MyApplication extends Application<MyConfiguration> {
    ........

    @Override
   public void run(MyConfiguration myConfiguration, Environment                     currentEnvironment) {

     currentEnvironment.jersey().register(StudentIdValidator.class);

    }

我真的是无能为力了。非常感谢任何帮助。很抱歉格式不好。

【问题讨论】:

    标签: java validation annotations jersey dropwizard


    【解决方案1】:

    这很简单。我会把我的例子贴在这里,因为我已经把它写好了,我很懒,不想带走你的有趣体验:)

    编辑:我认为您的问题是您没有使用 @Valid 注释您的资源

    所以我们开始:

    您与验证者的合作是正确的。这些是我的:

    public class CustomValidator implements ConstraintValidator<CustomValidation, String> {
    
        @Override
        public void initialize(CustomValidation constraintAnnotation) {
    
        }
    
        @Override
        public boolean isValid(String value, ConstraintValidatorContext context) {
    
            System.out.println("Validation called");
    
            return false;
        }
    
    }
    

    这是注释:

    @Constraint(validatedBy = {CustomValidator.class})
    @Target({ElementType.FIELD, ElementType.PARAMETER})
    @Retention(value = RetentionPolicy.RUNTIME)
    public @interface CustomValidation {
    
    
          String message() default "Some message";
    
          Class<?>[] groups() default {};
          Class<? extends Payload>[] payload() default {};
    }
    

    应用程序:

    public class Application extends io.dropwizard.Application<Configuration>{
    
        @Override
        public void run(Configuration configuration, Environment environment) throws Exception {
            MetricRegistry metrics = environment.metrics();
            environment.jersey().register(new HelloResource(metrics));
    
        }
    
        public static void main(String[] args) throws Exception {
            new Application().run("server", "/home/artur/dev/repo/sandbox/src/main/resources/config/test.yaml");
        }
    }
    

    还有资源:

    @Path("/test")
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    public class HelloResource {
    
        private MetricRegistry service;
    
        public HelloResource(MetricRegistry service) {
            this.service = service;
        }
    
        @GET
        public String hello() {
    
            Timer timer = service.timer("test");
    
            try(Context t = timer.time()) {
                return "Hello World";
            }
    
        }
    
    
        @GET
        @Path("/test2")
        public void test(@Valid @CustomValidation @QueryParam("arg") String test) {
            System.out.println(test);
        }
    }
    

    不要介意指标,它们与它无关。重要的部分是你需要告诉 DW 你想要验证什么。

    在资源中,查看测试方法。我用 @Valid(告诉 DW 验证)@CustomValidation(告诉 DW 使用什么验证器)注释我需要的参数。

    这实际上不是 Dropwizard 功能,而是休眠验证器实现。

    它在底层工作的方式是当通过调用构造函数请求时,hibernate 会动态创建 Validator 类。现在,如果您进行简单的验证(例如比较字符串),这将非常有效。如果您需要依赖项,那么它会变得更加棘手。我也有一个例子,你可以在这里阅读:

    With dropwizard validation, can I access the DB to insert a record

    此示例使用 guice,但它演示了如何将自己的创建机制挂钩到验证中。这样您就可以控制您的验证器创建并使用数据源注入或初始化它们以访问您的数据库。

    我希望能回答你的问题,

    阿图尔

    【讨论】:

    • 还有更多关于验证器的信息以及如何在启用组的情况下实现验证,这里:stackoverflow.com/questions/37463570/…
    • 感谢您的回复。当我尝试它时,我收到了这个警告 org.glassfish.jersey.internal.inject.Providers:在 SERVER 运行时注册的提供程序 com.shuvro.application.validator.StudentIdValidatior$StudentIdValidation 没有实现任何适用于 SERVER 运行时的提供程序接口。由于约束配置问题,提供者 com.shuvro.application.validator.StudentIdValidator.StudentIdValidatior$StudentIdValidation 将被忽略。
    • 嗨 - 你不需要注册你的验证器。它不是球衣组件,所以球衣不知道如何处理它
    【解决方案2】:

    drop 向导中的自定义验证与休眠自定义验证器相同。

    点击链接:hibernate validator-customconstraints

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-05-13
      • 2020-01-05
      • 1970-01-01
      • 2018-07-15
      • 1970-01-01
      • 2011-03-26
      • 2015-03-28
      • 1970-01-01
      相关资源
      最近更新 更多