简体   繁体   English

Spring-Boot 多模块项目加载属性文件

[英]Spring-Boot multi module project load property-file

I have a Spring-Boot-Application as a multimodule-Project in maven.我有一个 Spring-Boot-Application 作为 maven 中的多模块项目。 The structure is as follows:结构如下:

Parent-Project
|--MainApplication
|--Module1
|--ModuleN

In the MainApplication project there is the main() method class annotated with @SpringBootApplication and so on.MainApplication项目中有main()方法类用@SpringBootApplication等注解。 This project has, as always, an application.properties file which is loaded automatically.该项目一如既往地具有自动加载的 application.properties 文件。 So I can access the values with the @Value annotation所以我可以使用@Value注释访问这些值

@Value("${myapp.api-key}")
private String apiKey;

Within my Module1 I want to use a properties file as well (called module1.properties), where the modules configuration is stored.在我的 Module1 中,我还想使用一个属性文件(称为 module1.properties),其中存储了模块配置。 This File will only be accessed and used in the module.该文件只能在模块中访问和使用。 But I cannot get it loaded.但我无法加载它。 I tried it with @Configuration and @PropertySource but no luck.我用@Configuration@PropertySource尝试过,但没有运气。

@Configuration
@PropertySource(value = "classpath:module1.properties")
public class ConfigClass {

How can I load a properties file with Spring-Boot and access the values easily?如何使用 Spring-Boot 加载属性文件并轻松访问这些值? Could not find a valid solution.找不到有效的解决方案。

My Configuration我的配置

@Configuration
@PropertySource(value = "classpath:tmdb.properties")
public class TMDbConfig {

    @Value("${moviedb.tmdb.api-key}")
    private String apiKey;

    public String getApiKey() {
        return apiKey;
    }

    @Bean
    public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
        return new PropertySourcesPlaceholderConfigurer();
    }
}

Calling the Config调用配置

@Component
public class TMDbWarper {

@Autowired
private TMDbConfig tmdbConfig;

private TmdbApi tmdbApi;

public TMDbWarper(){
    tmdbApi = new TmdbApi(tmdbConfig.getApiKey());
}

I'm getting an NullPointerException in the constructor when I autowire the warper.当我自动装配扭曲器时,我在构造函数中收到 NullPointerException。

For field injection:对于现场注入:

Fields are injected right after construction of a bean, before any config methods are invoked.在构建 bean 之后,在调用任何配置方法之前,立即注入字段。 Such a config field does not have to be public.这样的配置字段不必是公开的。 Refer Autowired annotation for complete usage.有关完整用法,请参阅Autowired 注释 Use constructor injection in this case like below:在这种情况下使用构造函数注入,如下所示:

@Component
public class TMDbWarper {

    private TMDbConfig tmdbConfig;

    private TmdbApi tmdbApi;

    @Autowired
    public TMDbWarper(final TMDbConfig tmdbConfig){
            this.tmdbConfig = tmdbConfig;
            tmdbApi = new TmdbApi(tmdbConfig.getApiKey());
    }

(or) (或)

Use @PostConstruct to initialise like below:使用@PostConstruct初始化如下:

@Component
public class TMDbWarper {

    @Autowired
    private TMDbConfig tmdbConfig;

    private TmdbApi tmdbApi;

    @PostConstruct
    public void init() {
        // any initialisation method
        tmdbConfig.getConfig();
    }

Autowiring is performed just after the creation of the object(after calling the constructor via reflection).自动装配是在创建对象之后(通过反射调用构造函数之后)执行的。 So NullPointerException is expected in your constructor as tmdbConfig field would be null during invocation of constructor因此,您的构造函数中tmdbConfig会出现NullPointerException ,因为在调用构造函数期间tmdbConfig字段将为空

You may fix this by using the @PostConstruct callback method as shown below:您可以使用@PostConstruct 回调方法解决此问题,如下所示:

@Component
public class TMDbWarper {

    @Autowired
    private TMDbConfig tmdbConfig;

    private TmdbApi tmdbApi;

    public TMDbWarper() {

    }

    @PostConstruct
    public void init() {
        tmdbApi = new TmdbApi(tmdbConfig.getApiKey());
    }

    public TmdbApi getTmdbApi() {
        return this.tmdbApi;
    }
}

Rest of your configuration seems correct to me.你的其余配置对我来说似乎是正确的。

Hope this helps.希望这会有所帮助。

Here is a Spring Boot multi-module example where you can get properties in different module.这是一个 Spring Boot 多模块示例,您可以在其中获取不同模块中的属性。 Let's say I have main application module, dataparse-module , datasave-module.假设我有主要的应用程序模块, dataparse-moduledatasave-module 。

StartApp.java in application module:应用程序模块中的StartApp.java

@SpringBootApplication
public class StartApp {

    public static void main(String[] args) {

        SpringApplication.run(StartApp.class, args);
    }
}

Configuration in dataparse-module . dataparse-module 中的配置。 ParseConfig.java :解析配置.java :

@Configuration
public class ParseConfig {
        @Bean
        public XmlParseService xmlParseService() {
            return new XmlParseService();
        }
}

XmlParseService.java: XmlParseService.java:

@Service
public class XmlParseService {...}

Configuration in datasave-module . datasave-module 中的配置。 SaveConfig.java:保存配置.java:

@Configuration
@EnableConfigurationProperties(ServiceProperties.class)
@Import(ParseConfig.class)//get beans from dataparse-module - in this case XmlParseService
public class SaveConfig {

    @Bean
    public SaveXmlService saveXmlService() {
        return new SaveXmlService();

    }

}

ServiceProperties.java:服务属性.java:

@ConfigurationProperties("datasave")
public class ServiceProperties {

    private String message;

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

}

application.properties in datasave-module in resource/config folder:资源/配置文件夹中datasave-module中的application.properties

datasave.message=Multi-module Maven project! datasave.message=多模块Maven项目!

threads.xml.number=5线程数.xml.number=5

file.location.on.disk=D:\\temp\\registry file.location.on.disk=D:\\temp\\registry

Then in datasave-module you can use all your properties either through @Value.然后在datasave-module 中,您可以通过@Value 使用所有属性。

SaveXmlService.java: SaveXmlService.java:

@Service
public class SaveXmlService {

    @Autowired
    XmlParseService xmlParseService;

    @Value("${file.location.on.disk: none}")
    private String fileLocation;

    @Value("${threads.xml.number: 3}")
    private int numberOfXmlThreads;
    
    ...
}

Or through ServiceProperties:或通过 ServiceProperties:

Service.java:服务.java:

@Component
public class Service {

    @Autowired
    ServiceProperties serviceProperties;

    public String message() {

        return serviceProperties.getMessage();

    }
}

I had this situation before, I noticed that the properties file was not copied to the jar.我之前遇到过这种情况,我注意到属性文件没有复制到 jar 中。

I made the following to get it working:我做了以下工作以使其正常工作:

  1. In the resources folder, I have created a unique package, then stored my application.properties file inside it.在资源文件夹中,我创建了一个独特的包,然后将我的 application.properties 文件存储在其中。 eg: com/company/project例如:com/公司/项目

  2. In the configuration file eg: TMDBConfig.java I have referenced the full path of my .properties file:在配置文件中,例如:TMDBConfig.java 我引用了我的 .properties 文件的完整路径:

     @Configuration @PropertySource("classpath:/com/company/project/application.properties") public class AwsConfig

Build and run, it will work like magic.构建并运行,它会像魔术一样工作。

You could autowire and use the Enviornment bean to read the property您可以自动装配并使用Enviornment bean 来读取属性

@Configuration
@PropertySource(value = "classpath:tmdb.properties")
public class TMDbConfig {

  @Autowired
  private Environment env;

  public String getApiKey() {
    return env.getRequiredProperty("moviedb.tmdb.api-key");
  }

}

This should guarantee that property is read from the context when you invoke the getApiKey() method regardless of when the @Value expression is resolved by PropertySourcesPlaceholderConfigurer .这应该保证在调用getApiKey()方法时从上下文中读取属性,而不管@Value表达式何时由PropertySourcesPlaceholderConfigurer解析。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM