首页 > 解决方案 > 如何在配置过程中关闭 Spring 应用程序?

问题描述

在配置过程中或在应用程序上下文初始化之后关闭 Spring 应用程序的最佳实践是什么?

例如,在我的情况下,我有几个@ConfigurationProperties,并且必须指定其中至少一个,否则应用程序将关闭。我应该使用@Conditional, 一些通用@ConfigurationProperties的验证,还是别的什么?


我决定将验证与一般@ConfigurationProperties

@Constraint(validatedBy = AtLeastOneOfTheFieldsValidator.class)
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface AtLeastOneOfTheFields {

    String message() default "At least one of the fields must be specified";

    String onBooleanCondition();

    String[] fields();

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

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

    @interface List {

        AtLeastOneOfTheFields[] value();
    }
}

public class AtLeastOneOfTheFieldsValidator implements ConstraintValidator<AtLeastOneOfTheFields, Object> {

    private String[] fields;

    private String booleanConditionField;

    @Override
    public void initialize(AtLeastOneOfTheFields atLeastOneOfTheFields) {
        this.fields = atLeastOneOfTheFields.fields();
        this.booleanConditionField = atLeastOneOfTheFields.onBooleanCondition();
    }

    @Override
    public boolean isValid(Object value, ConstraintValidatorContext constraintValidatorContext) {
        Object booleanConditionValue = new BeanWrapperImpl(value).getPropertyValue(booleanConditionField);

        if (Objects.isNull(booleanConditionValue) || Objects.equals(Boolean.TRUE, booleanConditionValue)) {
                return Arrays.stream(fields)
                    .map(field -> new BeanWrapperImpl(value).getPropertyValue(field))
                    .anyMatch(Objects::nonNull);
        }
        return true;
    }
}

@Getter
@Setter
@Configuration
@ConfigurationProperties(prefix = "bot")
@Validated
@AtLeastOneOfTheFields(fields = {"facebook.page-access-token", "telegram.token", "viber.token"},
        onBooleanCondition = "enabled",
        message = "At leas one of bot token must be specified if property bot.enabled = 'true'.")
public class BotConfig {

    @NotNull
    private Boolean enabled;

    @NestedConfigurationProperty
    private FacebookBotConfig facebook;

    @NestedConfigurationProperty
    private TelegramBotConfig telegram;

    @NestedConfigurationProperty
    private ViberBotConfig viber;
}

另一个变体ApplicationContextInitializer用于验证环境属性。

我会很高兴收到您的意见或建议。=)

标签: javaspringspring-boot

解决方案


您可以像这样创建一些关闭处理程序组件:

@Component
public class ShutdownHandler {

    @Autowired
    private ApplicationContext applicationContext;

    public void shutdown(int code) {     // to shutdown you have to put 0 number
        SpringApplication.exit(applicationContext, () -> code);
    }
}

在你的属性类上,调用它;

@ConfigurationProperties
public class ConfigProperties {

    @Autowired
    private ShutdownHandler handler;

    public void someMethod() {            
        if (isValid){
           handler.shutdown(0);
        }
    }

}

推荐阅读