java - Spring - 使用值注释从本地配置文件中读取

标签 java spring spring-boot configuration nullpointerexception

我尝试使用 Spring 中的 Value 注释来读取本地 application.yaml 文件,该文件与我的主测试类和单元测试类放在同一个包中。我有一个简单的类,其中包含获取配置值的方法:

public class EmailValidator {

    String getConfigValue(configurationProvider1 configurationReader, String configName) {
        String value = null;
        ConfigurationProvider reader;
        try {
            reader = configurationReader.configurationProvider();
            value = reader.getProperty(configName, String.class);
            //the `reader` above is null when I run the test, so I get Null Pointer Exception on this line
            if (value == null) {
                LOGGER.warn("The configuration for " + configName + " cannot be found.");
            }
        } catch (Exception e){
            e.printStackTrace();
        }

        return value;
    }
} 

我有一个配置提供程序类,它设置配置读取器,以便我上面的类可以使用它来读取 application.yaml 文件:

@Configuration
@AllArgsConstructor(access = AccessLevel.PACKAGE)
@NoArgsConstructor
@ComponentScan
public class configurationProvider1 {

        @Value("${configFilesPath:./domain/application.properties}")//Not really sure if this is the right way of locating my configuration file
        @Getter
        private String filePath;

        @Bean
        public ConfigurationProvider configurationProvider() throws FileNotFoundException {
            if (!Paths.get(this.filePath).toFile().exists()) {
                throw new FileNotFoundException("Configuration file doesn't exist: " + this.filePath);
            }

            ConfigFilesProvider configFilesProvider =
                    () -> Collections.singletonList(Paths.get(filePath).toAbsolutePath());
            ConfigurationSource source = new FilesConfigurationSource(configFilesProvider);
            Environment environment = new ImmutableEnvironment(this.filePath);

            return new ConfigurationProviderBuilder()
                    .withConfigurationSource(source)
                    .withEnvironment(environment)
                    .build();
        }
    } 

如上所述,我不确定 @Value("${configFilesPath:./domain/application.properties}") 是否是定位本地 application.properties 文件的正确方法(这些类位于同一个名为 domain 的包中,但配置文件不在资源文件夹中,因为这是一个服务层。所以它就在 domain 包下)。

当我尝试在第一个类中测试 getConfigValue 方法时,我得到了 NPE(我认为这是因为我作为参数传递给 getConfigValue 方法的 ConfigurationReader 为 null):

@RunWith(SpringRunner.class)
@SpringBootTest
public class EmailValidatorTest {

    @MockBean
    private configurationProvider1 configurationReader = mock(configurationProvider1.class);

    @Autowired
    private DefaultEmailValidator validator;//maybe I should inject the dependency somewhere?

    @Test
    public void simple(){
        String a = validator.getConfigValue(configurationReader,"mail.subject.max.length");
        System.out.println(a);
    } 

我不确定我的类此时是否实际上正在从配置文件中读取配置值。任何帮助将不胜感激!

附注代码已更新

最佳答案

@Value

Spring’s @Value annotation provides a convenient way to inject property values into components, not to provide the properties file path

@PropertySource 使用@PropertySource Doc

Annotation providing a convenient and declarative mechanism for adding a PropertySource to Spring's Environment. To be used in conjunction with @Configuration classes

Given a file app.properties containing the key/value pair testbean.name=myTestBean, the following @Configuration class uses @PropertySource to contribute app.properties to the Environment's set of PropertySources.

示例

 @Configuration
 @PropertySource("classpath:/com/myco/app.properties")
 public class AppConfig {

 @Autowired
 Environment env;

 @Bean
 public TestBean testBean() {
     TestBean testBean = new TestBean();
     testBean.setName(env.getProperty("testbean.name"));
     return testBean;
   }
 }

24.7.4 YAML Shortcomings

YAML files cannot be loaded by using the @PropertySource annotation. So, in the case that you need to load values that way, you need to use a properties file.

来到测试用例,您不应该创建 DefaultEmailValidator 的新实例,您需要使用 @SpringBootTest

@SpringBootTest Example

The @SpringBootTest annotation can be used when we need to bootstrap the entire container. The annotation works by creating the ApplicationContext that will be utilized in our tests.

RunWith(SpringRunner.class)

@RunWith(SpringRunner.class) is used to provide a bridge between Spring Boot test features and JUnit. Whenever we are using any Spring Boot testing features in out JUnit tests, this annotation will be required.

@MockBean

Another interesting thing here is the use of @MockBean. It creates a Mock

EmailValidator测试

 @RunWith(SpringRunner.class)
 @SpringBootTest
 public class EmailValidatorTest {

@MockBean
private configurationProvider1 configurationReader;

@Autowire
private DefaultEmailValidator validator

@Test
public void testGetConfigValue(){
    String a = validator.getConfigValue(configurationReader,"mail.subject.max.length");
    System.out.println(a);
} 

关于java - Spring - 使用值注释从本地配置文件中读取,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55787296/

相关文章:

java - 使用 Maven 的 Java EE 开发团队中的 Eclipse/Netbeans IDE 选择

java - 在 Java 中,什么时候 {a,b,c,...} 数组简写不合适,为什么?

java - 为自定义类生成 hashCode()

java - Spring MVC 如何为 Controller 方法提供注入(inject)

java - 使用 ServletContainer 作为 Servlet 提供静态资源

java - 如果 Singleton 不是线程安全的,这到底意味着什么?

java - 如何在 Spring 后端获取可变 HTML 表单值 (POST)

java - 我可以更改 junit 测试执行顺序吗?

spring-boot - Eureka 服务给出请求执行错误?

java - jar 外部的 ResourceBundle 文件