【问题标题】:Spring boot and arguments validationSpring Boot 和参数验证
【发布时间】:2017-09-11 02:07:42
【问题描述】:

我正在编写一个 Spring 启动应用程序,我想验证在我的应用程序运行之前是否设置了所有预期的参数或外部化属性。我什么时候可以做到? 我找到了 commons-cli 或 args4j 库,但我不知道如何将它与 Spring 引导应用程序一起使用,以及它是否是一个好的解决方案。谢谢

【问题讨论】:

  • 你的意思是设置为不是null

标签: spring-boot command-line-arguments


【解决方案1】:

有几个是这样做的。这个链接解释了所有可用的https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html

如果您只是检查非空值,那么您可以像这样使用@Value

@Configuration
public class ApplicationConfiguration
{
   @Value("${name}")
   private String name;
 }

如果值为null,应用程序将在启动时停止

如果您需要确保设置了特定值的其他属性,您可以使用@ConfigurationProperties

@ConfigurationProperties(prefix = "test")
public class ConfigProps
{
     private String name;

     public String getName()
     {
          return name;
     }
}

@Configuration
@EnableConfigurationProperties
public class AppConfig
{
     @Autowired
     public AppConfig(ConfigProps configProps)
     {
          if (!"test".equals(configProps.getName())
          {
               throw new IllegalArugmentException("name not correct value");
          }
     }
}

【讨论】:

  • 这真的很有帮助。仅供参考,不过,您可能还需要属性的设置器。
  • 另外,您可能还需要将@Configuration 添加到 ConfigProps 类中。
  • 注释本身的 ConfigProps 类部分不需要 @Configuration 将其定义为配置。除非 Spring 自发布以来已更新其注解。
  • 你也不应该在 ConfigProps 类中放置一个 setter。该类的全部意义在于它可以读取属性。在 Java 代码中,您不应该覆盖应用程序之外的属性集。
  • 由于某种原因,如果我不将@Configuration 添加到我的 ConfigProps 版本中,则不会发生验证。我见过的大多数例子都不包含它,所以对我来说,为什么我似乎需要它是个谜。
【解决方案2】:

将你的验证逻辑放在 Spring boot 的 main 方法中。在 Spring Boot 应用程序中没有单独使用这些库的方法。您可以在 main 方法中添加验证代码,以解析 args 并进行验证。你可以为此使用任何 args 解析器库。

@SpringBootApplication
public class MyApplication{
    public static void main(String[] args){
        validateArguments(args);
        SpringApplication.run(MyApplication.class);
    }
    private static validateArguments(args){
        // validation logic - If validation fails throw IllegalStateException(); 
    }
}

【讨论】:

  • 谢谢我会使用你的解决方案
【解决方案3】:

首先, 使用 @Validated 注解启用属性验证。 然后为您想要检查它们的方式配置适当的字段, 例如,使用正则表达式(@Pattern 注释)。

设置了两个字段的示例配置 bean:

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.validation.annotation.Validated;

import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Pattern;

@Data
@Validated
@Configuration
@ConfigurationProperties(prefix = "mail-service")
public class MailServiceConfiguration {

    @Min(1)
    @Max(20)
    private int numberOfThreads;

    @NotBlank
    @Pattern(regexp = "/^[A-Za-z0-9]{3,10}$/"
            , message = "No special characters"
    )
    private String clientType;

}

我在 application.properties 中的配置无效:

mail-service.numberOfThreads=21
mail-service.clientType=***

...以及尝试运行后生成的消息:

Binding to target org.springframework.boot.context.properties.bind.BindException: Failed to bind properties under 'mail-service' to com.MailServiceConfiguration failed:

    Property: mail-service.numberOfThreads
    Value: 21
    Origin: class path resource [application.properties]:1:30
    Reason: must be less than or equal to 20

    Property: mail-service.clientType
    Value: ***
    Origin: class path resource [application.properties]:2:25
    Reason: No special characters

【讨论】:

    【解决方案4】:

    另一种方法是创建一个实现Validator@ConfigurationProperties 类:

    @Data
    @Validated
    @ConfigurationProperties(prefix="my")
    public class AppProperties implements Validator {
    
        private String name;
        private List<String> validNames;
    
        @Override
        public boolean supports(Class<?> clazz) {
            return AppProperties.class.isAssignableFrom(clazz);
        }
    
        @Override
        public void validate(Object target, Errors errors) {
            AppProperties config = (AppProperties) target;
    
            ValidationUtils.rejectIfEmpty(
                errors, "name", "required-field", "name is required");
    
            if (!config.validApiNames.contains(config.apiName)) {
                errors.rejectValue("apiName " + apiName, "invalid");
            }
        }
    }
    

    并确保通过 @EnableConfigurationProperties 启用您的 ConfigurationProperties 类:

    @SpringBootApplication
    @EnableConfigurationProperties(AppProperties.class)
    public class Application {
      // ...
    }
    

    如果你在 application.properties 中有这样的东西,上面应该可以工作:

    validNames=name1,name2
    name=name1
    

    我添加了对有效值的检查,主要是作为一个使用示例。但它确实可以防止无效的命令行参数(提供时,override application.properties 中的那些)。

    请注意,在 Spring Boot 2.6.3 前后,ConfigurationProperties 上的 prefix 参数是可选的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-06-04
      • 2021-01-30
      • 2021-02-07
      • 1970-01-01
      • 2016-07-24
      • 2020-04-12
      • 1970-01-01
      相关资源
      最近更新 更多