使用JAX-RS时,是否可以将变量输入到自定义ConstraintValidator中? [英] Is there a way to get a variable in to a custom ConstraintValidator when using JAX-RS?

查看:92
本文介绍了使用JAX-RS时,是否可以将变量输入到自定义ConstraintValidator中?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在反序列化JSON有效负载时,我想使用自定义验证器来验证电话号码.该验证器需要知道客户所在的国家/地区才能正确解析电话号码.我可以在http标头中接受的国家/地区找到语言.

When de-serializing a JSON payload i want to validate a phone number using a custom validator. This validator needs to know what country the customer is in to correctly parse the phone number. The country i can find in the http header Accept-Language.

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

The problem is how can i provide the custom validator with this extra meta data?

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

I was sure that @Context would inject the HttpHeaders into the PhoneNumberValidator but this does not work:

    @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界面:

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 {};
}

自定义验证器:

@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和更早版本,不是.

The HttpHeaders object is not (yet) a CDI managed bean - I say yet because it is part of the plan for Jakarta's JAX-RS 3.0 to be a CDI bean, but for JAX-RS 2.1 and earlier, it is not.

但是资源类可能是CDI管理的bean.因此,您可以将HttpHeaders注入到CustomerResource类中,然后提供将访问标头的getter方法.然后在验证器类中使用@Inject注入资源.然后,您可以从验证器访问标头.

But it is possible for the resource class to be a CDI managed bean. So you could inject the HttpHeaders into the CustomerResource class, and then provide a getter method that would access the headers. Then use @Inject in your validator class to inject your resource. Then you can access the headers from the validator.

类似这样的东西:

@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

I wrote up a working sample here that may help: https://github.com/andymc12/ContextVarInValidatorSample

希望这会有所帮助,安迪

Hope this helps, Andy

这篇关于使用JAX-RS时,是否可以将变量输入到自定义ConstraintValidator中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆