仅当其他字段为false时才验证字段 [英] Validate fields only if other field is false

查看:171
本文介绍了仅当其他字段为false时才验证字段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有一个@ConfigurationProperties类,该类需要根据另一个字段的值来验证一组字段.例如,SdkProperties具有一个enabled字段.仅当enabledtrue时,其他字段才有效.

Suppose I have an @ConfigurationProperties class which needs to validate a set of fields based on the value of another field. For example, SdkProperties has an enabled field. Only when enabled is true should the other fields be validated.

SdkProperties

@Configuration
@ConfigurationProperties(...)
@Data
@Validated
public class SdkProperties
{
    private boolean enabled;

    @NotEmpty
    private String apiKey

    // ... etc.
}

仅当enabledtrue时,才应验证@NotEmpty批注.

The @NotEmpty annotation should only be validated if enabled is true.

执行此操作的正确方法是什么?

What's the proper way to do this?

我已经看到了使用@AssertTrueisValid函数手动处理验证的示例.但是我不想那样做.

I have seen examples of using @AssertTrue and an isValid function to handle the validation by hand. But I don't want to do that.

我想知道使用验证组是否可行?

I wonder if this is doable using validation groups?

推荐答案

您可以编写自定义ConstraintValidator.


@Configuration
@ConfigurationProperties(prefix = "sdk")
@Validated
@NotEmptyWhenEnabled // <----- custom validation -----
@Data
class SdkProperties {

    private boolean enabled;
    private String apiKey;
}

@Constraint(validatedBy = {NotEmptyWhenEnabledValidator.class})
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@interface NotEmptyWhenEnabled {
    String message() default "SDK apiKey needed when SDK is enabled";

    Class[] groups() default {};

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

class NotEmptyWhenEnabledValidator implements ConstraintValidator<NotEmptyWhenEnabled,SdkProperties> {

    @Override
    public boolean isValid(SdkProperties sdkProperties, 
                           ConstraintValidatorContext constraintValidatorContext) {
        boolean enabled = sdkProperties.isEnabled();
        boolean empty = null == sdkProperties.getApiKey() || sdkProperties.getApiKey().isEmpty();
        return !enabled || (enabled && !empty);
    }
}

然后,当启用 SDK 但未提供 API密钥时,您会在启动时收到一条很好的消息.

Then you get a nice message on startup when SDK is enabled but the API-key is not provided.

***************************
APPLICATION FAILED TO START
***************************

Description:

Binding to target org.springframework.boot.context.properties.bind.BindException: Failed to bind properties under 'sdk' to so.demo.SdkProperties$$EnhancerBySpringCGLIB$$1ecd6003 failed:

    Reason: SDK apiKey needed when SDK is enabled


Action:

Update your application's configuration


Process finished with exit code 0

EDIT

EDIT

spring-boot-2.2.0.RELEASE(2019年10月16日)起,您还有另一种选择. 您可以在构造函数中验证属性.

Since spring-boot-2.2.0.RELEASE (16 Oct 2019) you have another option. You could validate the properties in the constructor.

使用以下方式:不可变的@ConfigurationProperties 绑定

配置属性现在支持基于构造函数的绑定,该绑定允许带@ConfigurationProperties注释的类是不可变的.可以通过用@ConstructorBinding注释@ConfigurationProperties类或其构造函数之一来启用基于构造函数的绑定.可以在配置属性绑定提供的构造函数参数上使用@DefaultValue@DateTimeFormat之类的注释.

Configuration properties now support constructor-based binding, which allows a @ConfigurationProperties-annotated class to be immutable. Constructor-based binding can be enabled by annotating a @ConfigurationProperties class or one of its constructors with @ConstructorBinding. Annotations such as @DefaultValue and @DateTimeFormat can be used on constructor parameters that are provided by configuration property binding.

ref:所以就您而言...

@ConfigurationProperties(prefix = "sdk")
class SdkProperties {

    private boolean enabled;
    private String apiKey;

    @ConstructorBinding
    public SdkProperties(boolean enabled, String apiKey) {
        this.enabled = enabled;
        this.apiKey = apiKey;
        // direct validation in the constructor
        boolean apiKeyNullOrEmpty = null == apiKey || apiKey.isEmpty();
        Assert.isTrue(!enabled || !apiKeyNullOrEmpty, "When SDK is enabled, a SDK-api key is mandatory!");
    }

    public boolean isEnabled() {  return enabled; }
    public void setEnabled(boolean enabled) { this.enabled = enabled; }
    public String getApiKey() {return apiKey; }
    public void setApiKey(String apiKey) { this.apiKey = apiKey; }
}

这篇关于仅当其他字段为false时才验证字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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