java - 使用 JAX-RS 时,有没有办法将变量放入自定义 ConstraintValidator 中?

标签 java jax-rs bean-validation websphere-liberty

当反序列化 JSON 负载时,我想使用自定义 validator 验证电话号码。该 validator 需要知道客户所在的国家/地区才能正确解析电话号码。我可以在 http header Accept-Language 中找到该国家/地区。

问题是我如何为自定义 validator 提供这些额外的元数据?

我确信 @Context 会将 HttpHeaders 注入(inject)到 PhoneNumberValidator 中,但这不起作用:

    @Context
    private HttpHeaders mHttpHeaders;

该字段为空。

API端点:

@Path("customer")
public class CustomerResource {

    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    public Response postCustomer(@Valid Customer pCustomer) {
        return Response.ok(pCustomer).build();
    }
}

POJO:

@Getter
@Setter
public class Customer {
    @NotNull
    private String firstName;

    @ValidPhoneNumber
    private String mobileNumber;
}

validator 接口(interface):

@Documented
@Retention(RUNTIME)
@Target({ TYPE, FIELD })
@Constraint(validatedBy = { PhoneNumberValidator.class })
public @interface ValidPhoneNumber {
    String message() default "Phone number is not valid!";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

自定义 validator :

@Slf4j
public class PhoneNumberValidator implements ConstraintValidator<ValidPhoneNumber, String> {    
    @Override
    public boolean isValid(String vTelephone, ConstraintValidatorContext pContext) {
        final PhoneNumberUtil vPhoneNumberUtil = PhoneNumberUtil.getInstance();
        // TODO: Get the country in here somehow
        final String vCountry = "GB";      
        try {
            PhoneNumber vPhoneNumber = vPhoneNumberUtil.parse(vTelephone, vCountry);
            if (!vPhoneNumberUtil.isValidNumber(vPhoneNumber)) {
                log.error("Invalid {} phone number: {}", vCountry, vTelephone);
                return false;                
            }
        } catch (NumberParseException e) {
            log.error("Error parsing {} as a phone number in {}: {}", vTelephone, vCountry, e.getMessage());
            return false;
        }
        return true;
    }
}

最佳答案

HttpHeaders 对象(还)不是 CDI 托管 bean - 我说还不是,因为它是 Jakarta 的 JAX-RS 3.0 成为 CDI bean 计划的一部分,但对于 JAX-RS 2.1 及更早版本则不然。

但是资源类有可能是 CDI 托管 bean。因此,您可以将 HttpHeaders 注入(inject)到 CustomerResource 类中,然后提供一个可以访问 header 的 getter 方法。然后在 validator 类中使用 @Inject 来注入(inject)您的资源。然后您可以从 validator 访问 header 。

类似这样的事情:

@RequestScoped
public class PhoneNumberValidator implements ConstraintValidator<ValidPhoneNumber, String> {
    @Inject
    CustomerResource customerResource;

    @Override
    public boolean isValid(String vTelephone, ConstraintValidatorContext pContext) {
        // Get the country in here using the original resource instance
        final String vCountry = customerResource.getHeaderString("COUNTRY");
        try {
            validate(vTelephone, vCountry);
        } catch (Throwable t) {
            System.out.printf("Error parsing {0} as a phone number in {1}: {2}", vTelephone, vCountry, t.getMessage());
            return false;
        }
        return true;
    }
...

像这样更新资源类:

@RequestScoped
@Path("customer")
public class CustomerResource {

    @Context
    private HttpHeaders headers;

    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    public Response postCustomer(@Valid Customer pCustomer) {
        return Response.ok(pCustomer).build();
    }

    String getHeaderString(String headerName) {
        return headers.getHeaderString(headerName);
    }
...

我在这里写了一个可能有帮助的工作示例: https://github.com/andymc12/ContextVarInValidatorSample

希望这有帮助,安迪

关于java - 使用 JAX-RS 时,有没有办法将变量放入自定义 ConstraintValidator 中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56428847/

相关文章:

grails - 使用jaxrs插件Spring Security设置在Grails中开发Webapi

spring - 如何解决转换问题java.lang.ClassCastException : $Proxy cannot be cast to NotEmpty which is annotation

java - Java 中 "abc"+ "de"和 "abc"+ de (de = "de") 之间的区别?

java - Android- fragment 内的动画

java - 如何在同一个 Jersey JAX-RS 应用程序中使用两个版本的 Jackson(1.x 和 2.x)?

jersey - Jersey :给定无效的请求正文时,返回400错误而不是500

java - 如何自动调整java swing元素的大小?

java - ReentrantReadWriteLock 中的公平锁定

Java 验证 API : skip some rules without changing bean definition

java - 如何为同一个@Constraint 实现多个JSR-303 验证消息?