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

Posted

技术标签:

【中文标题】Spring-Boot 多模块项目加载属性文件【英文标题】:Spring-Boot multi module project load property-file 【发布时间】:2018-03-28 18:51:08 【问题描述】:

我在 Maven 中有一个 Spring-Boot-Application 作为多模块项目。结构如下:

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

MainApplication 项目中有main() 方法类用@SpringBootApplication 等注解。这个项目和往常一样有一个自动加载的 application.properties 文件。所以我可以使用@Value 注释访问这些值

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

在我的 Module1 中,我还想使用一个属性文件(称为 module1.properties),其中存储了模块配置。该文件只能在模块中访问和使用。但我无法加载它。我用@Configuration@PropertySource 尝试过,但没有运气。

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

如何使用 Spring-Boot 加载属性文件并轻松访问这些值?找不到有效的解决方案。

我的配置

@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();
    

调用配置

@Component
public class TMDbWarper 

@Autowired
private TMDbConfig tmdbConfig;

private TmdbApi tmdbApi;

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

当我自动装配 warper 时,构造函数中出现 NullPointerException。

【问题讨论】:

你能关注这个帖子吗?它也有代码示例。 javacodegeeks.com/2016/11/… 属性文件是否复制到 jar 中?尝试解压缩您的 jar 并检查文件是否存在 好吧,没有更多信息,这只是一个疯狂的猜测,正如 JavaDoc 中所述:为了使用属性解析 定义或 @Value 注释中的 $... 占位符从 PropertySource,必须注册一个 PropertySourcesPlaceholderConfigurer。 我更新了我的帖子。在那里您可以看到配置以及我如何尝试访问该值。我解压缩了我的战争包。在战争中是我的模块的罐子,在模块罐子中是我的属性文件。 tmdbConfig 没有实例化? 【参考方案1】:

在对象创建之后(通过反射调用构造函数之后)执行自动装配。所以 NullPointerException 应该在你的构造函数中,因为 tmdbConfig 字段在构造函数调用期间将为空

您可以通过使用@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;
    

您的其余配置对我来说似乎是正确的。

希望这会有所帮助。

【讨论】:

【参考方案2】:

对于现场注入:

在构造 bean 之后,在调用任何配置方法之前立即注入字段。这样的配置字段不必是公开的。请参阅Autowired annotation 了解完整用法。在这种情况下使用构造函数注入,如下所示:

@Component
public class TMDbWarper 

    private TMDbConfig tmdbConfig;

    private TmdbApi tmdbApi;

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

(或)

使用@PostConstruct进行如下初始化:

@Component
public class TMDbWarper 

    @Autowired
    private TMDbConfig tmdbConfig;

    private TmdbApi tmdbApi;

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

【讨论】:

【参考方案3】:

您可以自动装配并使用 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");
  


这应该保证在您调用getApiKey() 方法时从上下文中读取属性,而不管PropertySourcesPlaceholderConfigurer 何时解析@Value 表达式。

【讨论】:

【参考方案4】:

这是一个 Spring Boot 多模块示例,您可以在其中获取不同模块的属性。 假设我有主 application 模块、dataparse-moduledatasave-module。

StartApp.javaapplication 模块中:

@SpringBootApplication
public class StartApp 

    public static void main(String[] args) 

        SpringApplication.run(StartApp.class, args);
    

dataparse-module 中的配置。 ParseConfig.java

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

XmlParseService.java:

@Service
public class XmlParseService ...

datasave-module 中的配置。 SaveConfig.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:

@ConfigurationProperties("datasave")
public class ServiceProperties 

    private String message;

    public String getMessage() 
        return message;
    

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


application.propertiesresource/config 文件夹中的 datasave-module 中:

datasave.message=多模块 Maven 项目!

threads.xml.number=5

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

然后在 datasave-module 中,您可以通过@Value 使用所有属性。

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;
    
    ...

或通过 ServiceProperties:

Service.java:

@Component
public class Service 

    @Autowired
    ServiceProperties serviceProperties;

    public String message() 

        return serviceProperties.getMessage();

    

【讨论】:

【参考方案5】:

我之前也遇到过这种情况,注意到属性文件没有复制到jar中。

我做了以下工作:

    在资源文件夹中,我创建了一个独特的包,然后将我的 application.properties 文件存储在其中。例如:com/company/project

    在配置文件中,例如:TMDBConfig.java 我已经引用了我的 .properties 文件的完整路径:

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

构建并运行,它会像魔术一样工作。

【讨论】:

以上是关于Spring-Boot 多模块项目加载属性文件的主要内容,如果未能解决你的问题,请参考以下文章

Spring-Boot 多模块无法从另一个模块读取属性文件

Spring-Boot构建多模块项目

多模块 Gradle 项目 - 从 Spring-Boot 1.5 迁移到 2.1

使用gradle BOM和spring-boot(多模块应用程序)哪种方式更好

从 json 文件加载 spring-boot 属性

是否可以创建一个 spring-boot 自定义父 pom 这也是一个多模块项目?