Свойство файл загрузки проекта с несколькими модулями Spring-Boot
У меня есть Spring-Boot-Application как мультимодуль-проект в maven. Структура выглядит следующим образом:
Parent-Project
|--MainApplication
|--Module1
|--ModuleN
В проекте MainApplication
имеется класс метода main()
аннотированный с помощью @SpringBootApplication
и т.д. Этот проект имеет, как всегда, файл application.properties, который загружается автоматически. Поэтому я могу получить доступ к значениям с @Value
аннотации @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());
}
Я получаю исключение NullPointerException в конструкторе, когда я autowire warper.
Ответы
Ответ 1
Autowiring выполняется сразу после создания объекта (после вызова конструктора посредством отражения). Таким образом, NullPointerException
ожидается в вашем конструкторе, поскольку поле tmdbConfig
будет null при вызове конструктора
Вы можете исправить это, используя метод обратного вызова @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
Для полевого впрыска:
Поля вводятся сразу после построения компонента, прежде чем вызывать любые методы конфигурации. Такое поле конфигурации не должно быть общедоступным. Обратитесь к автообновленной аннотации для полного использования. Используйте инъекцию конструктора в этом случае, как показано ниже:
@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
для инициализации, как @PostConstruct
ниже:
@Component
public class TMDbWarper {
@Autowired
private TMDbConfig tmdbConfig;
private TmdbApi tmdbApi;
@PostConstruct
public void init() {
// any initialisation method
tmdbConfig.getConfig();
}
Ответ 3
Вот пример мультимодуля Spring Boot, в котором вы можете получить свойства в другом модуле. Скажем, у меня есть основной модуль приложения, dataparse-module, datasave-module.
StartApp.java в прикладном модуле:
@SpringBootApplication
public class StartApp {
public static void main(String[] args) {
SpringApplication.run(StartApp.class, args);
}
}
Конфигурация в datararse-модуле. ParseConfig.java:
@Configuration
public class ParseConfig {
@Bean
public XmlParseService xmlParseService() {
return new XmlParseService();
}
}
XmlParseService.java:
@Service
public class XmlParseService {...}
Конфигурация в datasave-модуле. 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.properties в datasave-модуле в папке resource/config:
datasave.message = Многомодульный проект Maven!
threads.xml.number = 5
file.location.on.disk = D:\Temp\реестра
Затем в модуле datasave вы можете использовать все свои свойства либо через @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();
}
}
Ответ 4
Раньше у меня была эта ситуация, я заметил, что файл свойств не был скопирован в банку.
Я сделал следующее, чтобы заставить его работать:
-
В папке ресурсов я создал уникальный пакет, а затем сохранил в нем файл application.properties. например: com/компания/проект
-
В файле конфигурации, например: TMDBConfig.java, я указал полный путь к файлу.properties:
@Configuration
@PropertySource("classpath:/com/company/project/application.properties")
public class AwsConfig
Постройте и запустите, он будет работать как магия.
Ответ 5
Вы можете использовать autwire и использовать компонент Enviornment
для чтения свойства
@Configuration
@PropertySource(value = "classpath:tmdb.properties")
public class TMDbConfig {
@Autowired
private Environment env;
public String getApiKey() {
return env.getRequiredProperty("moviedb.tmdb.api-key");
}
}
Это должно гарантировать, что свойство считывается из контекста при вызове getApiKey()
независимо от того, когда выражение @Value
разрешено PropertySourcesPlaceholderConfigurer
.