Spring Boot dan beberapa file konfigurasi eksternal


125

Saya memiliki beberapa file properti yang ingin saya muat dari classpath. Ada satu set default /src/main/resourcesyang merupakan bagian dari myapp.jar. Saya springcontextmengharapkan file berada di classpath. yaitu

<util:properties id="Job1Props"
    location="classpath:job1.properties"></util:properties>

<util:properties id="Job2Props"
    location="classpath:job2.properties"></util:properties>

Saya juga membutuhkan opsi untuk mengganti properti ini dengan set eksternal. Saya memiliki folder konfigurasi eksternal di cwd. Sesuai boot musim semi, folder config doc harus ada di classpath. Tetapi tidak jelas dari doc apakah itu hanya akan menimpa applicaiton.propertiesdari sana atau semua properti di config.

Saat saya mengujinya, hanya application.propertiesdiambil dan properti lainnya masih diambil /src/main/resources. Saya telah mencoba menyediakannya sebagai daftar yang dipisahkan koma spring.config.locationtetapi set default masih tidak diganti.

Bagaimana cara membuat file konfigurasi eksternal mulitiple menggantikan file konfigurasi default?

Sebagai solusi, saya saat ini menggunakan app.config.location(properti khusus aplikasi) yang saya suplai melalui baris perintah. yaitu

java -jar myapp.jar app.config.location=file:./config

dan saya mengubah saya applicationcontextmenjadi

<util:properties id="Job2Props"
    location="{app.config.location}/job2.properties"></util:properties>

Dan inilah cara saya membuat pemisahan antara file dan classpath saat memuat Aplikasi.
EDIT:

//psuedo code

if (StringUtils.isBlank(app.config.location)) {
            System.setProperty(APP_CONFIG_LOCATION, "classpath:");
}

Saya benar-benar ingin tidak menggunakan solusi di atas dan pegas akan menimpa semua file konfigurasi eksternal pada classpath seperti yang dilakukannya untuk application.propertiesfile tersebut.


4
Itu application.propertiesakan selalu dimuat, dengan spring.config.locationAnda dapat menambahkan lokasi konfigurasi tambahan yang diperiksa untuk file (yaitu ketika diakhiri dengan a /) namun jika Anda meletakkan daftar yang dipisahkan koma di sana yang menunjuk ke file yang akan dimuat. Ini juga dijelaskan dalam Panduan Referensi Sepatu Musim Semi di sini
M. Deinum

Jawaban:


156

Saat menggunakan Spring Boot, properti dimuat dalam urutan berikut (lihat Konfigurasi Eksternal di panduan referensi Spring Boot).

  1. Argumen baris perintah.
  2. Properti Sistem Java (System.getProperties ()).
  3. Variabel lingkungan OS.
  4. Atribut JNDI dari java: comp / env
  5. RandomValuePropertySource yang hanya memiliki properti secara acak. *.
  6. Properti aplikasi di luar jar paket Anda (properti.aplikasi termasuk YAML dan varian profil).
  7. Properti aplikasi yang dikemas di dalam jar Anda (properti.aplikasi termasuk YAML dan varian profil).
  8. @PropertySource anotasi pada kelas @Configuration Anda.
  9. Properti default (ditentukan menggunakan SpringApplication.setDefaultProperties).

Saat menyelesaikan properti (yaitu, @Value("${myprop}")penyelesaian dilakukan dalam urutan terbalik (jadi dimulai dengan 9).

Untuk menambahkan file yang berbeda, Anda dapat menggunakan spring.config.locationproperti yang mengambil daftar file properti atau lokasi file (direktori) yang dipisahkan koma.

-Dspring.config.location=your/config/dir/

Yang di atas akan menambahkan direktori yang akan dikonsultasikan untuk application.propertiesfile.

-Dspring.config.location=classpath:job1.properties,classpath:job2.properties

Ini akan menambahkan 2 file properti ke file yang dimuat.

File dan lokasi konfigurasi default dimuat sebelum yang ditentukan secara tambahan, spring.config.locationyang berarti bahwa yang terakhir akan selalu menimpa properti yang disetel di yang sebelumnya. (Lihat juga bagian ini dari Panduan Referensi Spring Boot).

Jika spring.config.locationberisi direktori (sebagai lawan dari file) mereka harus diakhiri dengan / (dan akan ditambahkan dengan nama yang dihasilkan spring.config.namesebelum dimuat). Jalur pencarian default classpath:,classpath:/config,file:,file:config/selalu digunakan, terlepas dari nilainya spring.config.location. Dengan cara itu Anda dapat menyetel nilai default untuk aplikasi Anda di application.properties(atau nama dasar apa pun yang Anda pilih spring.config.name) dan menggantinya saat runtime dengan file yang berbeda, dengan mempertahankan default.

PEMBARUAN: Karena perilaku spring.config.location sekarang menimpa default daripada menambahkannya. Anda perlu menggunakan spring.config.additional-location untuk mempertahankan default. Ini adalah perubahan perilaku dari 1.x menjadi 2.x


2
Terima kasih, tetapi saya telah membaca dokumen referensi ini dan berikut ini membingungkan saya "-Dspring.config.location = / config / dir / Anda di atas akan menambahkan direktori yang akan digunakan untuk file application.properties." Apa yang dimaksud dengan file application.properties. Itu hanya satu file. Bagaimanapun jika ia dapat mengambil seluruh direktori dengan "/" di akhir maka saya tidak perlu menentukan masing-masing sebagai daftar yang dipisahkan koma. Saya pikir saya telah mencoba kedua pendekatan seperti yang saya sebutkan di posting saya tetapi saya akan mencobanya sekali lagi
nir

Seperti yang dinyatakan dalam dokumen itu akan memilih berkonsultasi seperti lokasi default lainnya untuk application.propertiesdan application-[env].properties. Itu tidak memperhitungkan file properti lainnya. Ini juga dinyatakan dalam panduan referensi (di bagian tautan mengarah ke dan kutipan dari panduan referensi).
M. Deinum

1
Ya, tapi itulah yang tidak masuk akal bagi saya .. mengapa hanya mempertimbangkan satu jenis file dari direktori di classpath daripada seluruh direktori. Ini memaksa Anda untuk menggunakan satu file properti saja yang imo tidak baik. Seperti di tomcat saya dapat mengkonfigurasi common.loader untuk meletakkan direktori tertentu (dan semua yang ada di dalamnya) di classpath mengapa tidak bisa boot classloader dapat mendukungnya.
nir

3
Mengutip dokumentasi tidak membantu. Jika dokumentasinya jelas (cukup? Dengan cara yang sangat dibutuhkan?) Maka pertanyaannya tidak diperlukan. Misalnya, dalam kasus ini, sebenarnya tidak jelas bagaimana config.locationdan config.namesberinteraksi, meskipun mungkin terlihat jelas bagi orang yang sudah tahu bagaimana mereka berinteraksi. Bisakah Anda memperbarui jawaban Anda untuk menambahkan sesuatu ke dokumentasi?
Narfanator

13
Ini harus diperbarui, karena perilaku spring.config.locationsekarang menggantikan default daripada menambahkannya. Anda perlu menggunakan spring.config.additional-locationuntuk mempertahankan default. Ini adalah perubahan perilaku dari 1.x menjadi 2.x.
Robin

32

Dengan boot Spring, spring.config.location berfungsi, cukup sediakan file properti yang dipisahkan koma.

lihat kode di bawah ini

@PropertySource(ignoreResourceNotFound=true,value="classpath:jdbc-${spring.profiles.active}.properties")
public class DBConfig{

     @Value("${jdbc.host}")
        private String jdbcHostName;
     }
}

seseorang dapat meletakkan versi default jdbc.properties di dalam aplikasi. Versi eksternal dapat diatur dengan ini.

java -jar target/myapp.jar --spring.config.location=classpath:file:///C:/Apps/springtest/jdbc.properties,classpath:file:///C:/Apps/springtest/jdbc-dev.properties

Berdasarkan nilai profil yang ditetapkan menggunakan properti spring.profiles.active, nilai jdbc.host akan diambil. Jadi saat (di windows)

set spring.profiles.active=dev

jdbc.host akan mengambil nilai dari jdbc-dev.properties.

untuk

set spring.profiles.active=default

jdbc.host akan mengambil nilai dari jdbc.properties.


Saya tidak percaya blok kode pertama akan berfungsi. Saya tahu ketika saya menghentikan diri saya sendiri untuk yang satu ini, dan mengikuti jawaban ini . Lihat jira.springsource.org/browse/SPR-8539 yang direferensikan sebagai jawaban untuk penjelasan yang layak.
Sowka

27

Spring boot 1.X dan Spring Boot 2.X tidak memberikan opsi dan perilaku yang sama tentang file Externalized Configuration.

Jawaban yang sangat bagus dari M. Deinum mengacu pada spesifikasi Spring Boot 1.
Saya akan memperbarui untuk Spring Boot 2 di sini.

Sumber dan keteraturan properti lingkungan

Spring Boot 2 menggunakan PropertySourceurutan yang sangat khusus yang dirancang untuk memungkinkan pengesampingan nilai yang masuk akal. Properti dipertimbangkan dalam urutan berikut:

  • Properti pengaturan global Devtools di direktori home Anda (~ / .spring-boot-devtools.properties saat devtools aktif).

  • @TestPropertySource anotasi pada pengujian Anda.

  • @SpringBootTest#propertiesatribut annotation pada pengujian Anda. Argumen baris perintah.

  • Properti dari SPRING_APPLICATION_JSON(JSON sebaris yang disematkan dalam variabel lingkungan atau properti sistem).

  • ServletConfig parameter init.

  • ServletContext parameter init.

  • Atribut JNDI dari java:comp/env.

  • Properti Sistem Java ( System.getProperties()).

  • Variabel lingkungan OS.

  • A RandomValuePropertySourceyang memiliki properti hanya secara acak. *.

  • Properti aplikasi khusus profil di luar tabung paket Anda ( application-{profile}.propertiesdan varian YAML).

  • Properti aplikasi khusus profil yang dikemas di dalam jar Anda ( application-{profile}.propertiesdan varian YAML).

  • Properti aplikasi di luar tabung paket Anda ( application.propertiesdan varian YAML).

  • Properti aplikasi yang dikemas di dalam jar Anda ( application.propertiesdan varian YAML).

  • @PropertySourcepenjelasan tentang @Configurationkelas Anda . Properti default (ditentukan oleh pengaturan SpringApplication.setDefaultProperties).

Untuk menentukan file properti eksternal, opsi ini menarik minat Anda:

  • Properti aplikasi khusus profil di luar tabung paket Anda ( application-{profile}.propertiesdan varian YAML).

  • Properti aplikasi di luar tabung paket Anda ( application.propertiesdan varian YAML).

  • @PropertySourcepenjelasan tentang @Configurationkelas Anda . Properti default (ditentukan oleh pengaturan SpringApplication.setDefaultProperties).

Anda hanya dapat menggunakan salah satu dari 3 opsi ini atau menggabungkannya sesuai dengan kebutuhan Anda.
Misalnya untuk kasus yang sangat sederhana dengan hanya menggunakan properti khusus profil saja sudah cukup, tetapi dalam kasus lain Anda mungkin ingin menggunakan properti khusus profil, properti default dan @PropertySource.

Lokasi default untuk file application.properties

Tentang application.propertiesfile (dan varian), secara default Spring memuatnya dan menambahkan propertinya di lingkungan dari ini dalam urutan berikut:

  • A / config subdirektori dari direktori saat ini

  • Direktori saat ini

  • Paket classpath / config

  • Akar classpath

Prioritas yang lebih tinggi begitu harfiah:
classpath:/,classpath:/config/,file:./,file:./config/.

Bagaimana cara menggunakan file properti dengan nama tertentu?

Lokasi default tidak selalu cukup: lokasi default seperti nama file default ( application.properties) mungkin tidak cocok. Selain itu, seperti dalam pertanyaan OP, Anda mungkin perlu menentukan beberapa file konfigurasi selain application.properties(dan varian).
Jadi spring.config.nametidak akan cukup.

Dalam kasus ini Anda harus menyediakan lokasi eksplisit dengan menggunakan spring.config.locationproperti lingkungan (yang merupakan daftar lokasi direktori atau jalur file yang dipisahkan koma).
Untuk bebas tentang pola nama file, pilih daftar jalur file di atas daftar direktori.
Misalnya lakukan seperti itu:

java -jar myproject.jar --spring.config.location=classpath:/default.properties,classpath:/override.properties

Cara itu adalah yang paling verbose yang hanya menentukan folder tetapi juga cara untuk menentukan file konfigurasi kita dan untuk mendokumentasikan dengan jelas properti yang digunakan secara efektif.

spring.config.location sekarang menggantikan lokasi default alih-alih menambahkannya

Dengan Spring Boot 1, spring.config.locationargumen menambahkan lokasi tertentu di lingkungan Spring.
Tapi dari Spring Boot 2, spring.config.locationmenggantikan lokasi default yang digunakan oleh Spring dengan lokasi yang ditentukan di lingkungan Spring seperti yang dinyatakan dalam dokumentasi .

Saat lokasi konfigurasi kustom dikonfigurasi dengan menggunakan spring.config.location, lokasi default akan diganti. Misalnya, jika spring.config.locationdikonfigurasi dengan nilai`` classpath:/custom-config/, file:./custom-config/urutan pencarian menjadi sebagai berikut:

  1. file:./custom-config/

  2. classpath:custom-config/

spring.config.locationsekarang menjadi cara untuk memastikan bahwa application.propertiesfile apa pun harus ditentukan secara eksplisit.
Untuk uber JAR yang tidak seharusnya mengemas application.propertiesfile, itu cukup bagus.

Untuk menjaga perilaku lama spring.config.locationsaat menggunakan Spring Boot 2 Anda dapat menggunakan spring.config.additional-locationproperti baru alih-alih spring.config.locationyang masih menambahkan lokasi seperti yang dinyatakan oleh dokumentasi :

Alternatifnya, saat lokasi konfigurasi kustom dikonfigurasikan dengan menggunakan spring.config.additional-location, lokasi tersebut digunakan selain lokasi default.


Dalam praktek

Jadi misalkan seperti dalam pertanyaan OP, Anda memiliki 2 file properti eksternal untuk ditentukan dan 1 file properti disertakan dalam uber jar.

Untuk menggunakan hanya file konfigurasi yang Anda tentukan:

-Dspring.config.location=classpath:/job1.properties,classpath:/job2.properties,classpath:/applications.properties   

Untuk menambahkan file konfigurasi ke ini di lokasi default:

-Dspring.config.additional-location=classpath:/job1.properties,classpath:/job2.properties

classpath:/applications.properties pada contoh terakhir tidak diperlukan karena lokasi default memilikinya dan lokasi default di sini tidak ditimpa tetapi diperpanjang.


Jawaban Anda benar-benar lengkap kecuali pada satu hal: di mana Spring akan menemukan konfigurasi eksternal job1.properties pada disk jika Anda hanya menentukan: "classpath: /job1.properties"? Bagaimana Anda menambahkan direktori yang berisi properti eksternal ke classpath di sini?
Tristan

@Tristan, pada dasarnya, spring dapat membaca satu application.propertiesdengan semua parameter dan multipel ${file_name}.propertiesdengan kumpulan properti yang ditentukan sebagian. Jadi, jika Anda menggunakan @PropertySourceatau tautan kuat lainnya ke file, Anda dapat membuat file eksternal lain dan menimpa properti itu (Misalnya: dari classpath:file.properties).
Mister_Jesus

23

Lihatlah PropertyPlaceholderConfigurer, saya merasa lebih jelas untuk digunakan daripada anotasi.

misalnya

@Configuration
public class PropertiesConfiguration {


    @Bean
    public PropertyPlaceholderConfigurer properties() {
        final PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
//        ppc.setIgnoreUnresolvablePlaceholders(true);
        ppc.setIgnoreResourceNotFound(true);

        final List<Resource> resourceLst = new ArrayList<Resource>();

        resourceLst.add(new ClassPathResource("myapp_base.properties"));
        resourceLst.add(new FileSystemResource("/etc/myapp/overriding.propertie"));
        resourceLst.add(new ClassPathResource("myapp_test.properties"));
        resourceLst.add(new ClassPathResource("myapp_developer_overrides.properties")); // for Developer debugging.

        ppc.setLocations(resourceLst.toArray(new Resource[]{}));

        return ppc;
    }

Terima kasih banyak atas jawaban ini. Bisakah Anda memberi tahu saya bagaimana saya bisa mencapai hal yang sama dalam proyek yang memiliki konfigurasi XML seperti untuk hal-hal berbeda tanpa file XML dasar? Jawaban Anda di atas memang membantu saya dalam proyek lain yang berbasis anotasi. Terima kasih sekali lagi untuk itu.
Chetan

8

ini adalah salah satu pendekatan sederhana menggunakan sepatu bot musim semi

TestClass.java

@Configuration
@Profile("one")
@PropertySource("file:/{selected location}/app.properties")
public class TestClass {

    @Autowired
    Environment env;

    @Bean
    public boolean test() {
        System.out.println(env.getProperty("test.one"));
        return true;
    }
}

yang app.properties konteks, dalam Anda lokasi yang dipilih

test.one = 1234

aplikasi boot musim semi Anda

@SpringBootApplication

public class TestApplication {

    public static void main(String[] args) {
        SpringApplication.run(testApplication.class, args);
    }
}

dan konteks application.properties yang telah ditentukan sebelumnya

spring.profiles.active = one

Anda dapat menulis kelas konfigurasi sebanyak yang Anda suka dan mengaktifkan / menonaktifkannya hanya dengan menyetel spring.profiles.active = nama / nama profil {dipisahkan dengan koma}

seperti yang Anda lihat, sepatu bot musim semi sangat bagus, hanya perlu beberapa saat untuk membiasakannya, perlu disebutkan bahwa Anda juga dapat menggunakan @Value di bidang Anda

@Value("${test.one}")
String str;

7

Saya memiliki masalah yang sama. Saya ingin memiliki kemampuan untuk menimpa file konfigurasi internal saat startup dengan file eksternal, mirip dengan deteksi properti.aplikasi Spring Boot. Dalam kasus saya, ini adalah file user.properties tempat pengguna aplikasi saya disimpan.

Persyaratan saya:

Muat file dari lokasi berikut (dalam urutan ini)

  1. Jalur kelas
  2. A / config subdirektori dari direktori saat ini.
  3. Direktori saat ini
  4. Dari direktori atau lokasi file yang diberikan oleh parameter baris perintah saat startup

Saya datang dengan solusi berikut:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.PathResource;
import org.springframework.core.io.Resource;

import java.io.IOException;
import java.util.Properties;

import static java.util.Arrays.stream;

@Configuration
public class PropertiesConfig {

    private static final Logger LOG = LoggerFactory.getLogger(PropertiesConfig.class);

    private final static String PROPERTIES_FILENAME = "user.properties";

    @Value("${properties.location:}")
    private String propertiesLocation;

    @Bean
    Properties userProperties() throws IOException {
        final Resource[] possiblePropertiesResources = {
                new ClassPathResource(PROPERTIES_FILENAME),
                new PathResource("config/" + PROPERTIES_FILENAME),
                new PathResource(PROPERTIES_FILENAME),
                new PathResource(getCustomPath())
        };
        // Find the last existing properties location to emulate spring boot application.properties discovery
        final Resource propertiesResource = stream(possiblePropertiesResources)
                .filter(Resource::exists)
                .reduce((previous, current) -> current)
                .get();
        final Properties userProperties = new Properties();

        userProperties.load(propertiesResource.getInputStream());

        LOG.info("Using {} as user resource", propertiesResource);

        return userProperties;
    }

    private String getCustomPath() {
        return propertiesLocation.endsWith(".properties") ? propertiesLocation : propertiesLocation + PROPERTIES_FILENAME;
    }

}

Sekarang aplikasi menggunakan sumber daya classpath, tetapi memeriksa sumber daya di lokasi lain yang diberikan juga. Sumber daya terakhir yang ada akan diambil dan digunakan. Saya dapat memulai aplikasi saya dengan java -jar myapp.jar --properties.location = / directory / myproperties.properties untuk menggunakan lokasi properti yang mengapung perahu saya.

Detail penting di sini: Gunakan String kosong sebagai nilai default untuk properti.lokasi di anotasi @Value untuk menghindari kesalahan saat properti tidak disetel.

Ketentuan untuk properti.lokasi adalah: Gunakan direktori atau jalur ke file properti sebagai properti.lokasi.

Jika Anda hanya ingin mengganti properti tertentu, PropertiesFactoryBean dengan setIgnoreResourceNotFound (true) dapat digunakan dengan set larik sumber daya sebagai lokasi.

Saya yakin bahwa solusi ini dapat diperluas untuk menangani banyak file ...

EDIT

Di sini solusi saya untuk beberapa file :) Seperti sebelumnya, ini dapat digabungkan dengan PropertiesFactoryBean.

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.PathResource;
import org.springframework.core.io.Resource;

import java.io.IOException;
import java.util.Map;
import java.util.Properties;

import static java.util.Arrays.stream;
import static java.util.stream.Collectors.toMap;

@Configuration
class PropertiesConfig {

    private final static Logger LOG = LoggerFactory.getLogger(PropertiesConfig.class);
    private final static String[] PROPERTIES_FILENAMES = {"job1.properties", "job2.properties", "job3.properties"};

    @Value("${properties.location:}")
    private String propertiesLocation;

    @Bean
    Map<String, Properties> myProperties() {
        return stream(PROPERTIES_FILENAMES)
                .collect(toMap(filename -> filename, this::loadProperties));
    }

    private Properties loadProperties(final String filename) {
        final Resource[] possiblePropertiesResources = {
                new ClassPathResource(filename),
                new PathResource("config/" + filename),
                new PathResource(filename),
                new PathResource(getCustomPath(filename))
        };
        final Resource resource = stream(possiblePropertiesResources)
                .filter(Resource::exists)
                .reduce((previous, current) -> current)
                .get();
        final Properties properties = new Properties();

        try {
            properties.load(resource.getInputStream());
        } catch(final IOException exception) {
            throw new RuntimeException(exception);
        }

        LOG.info("Using {} as user resource", resource);

        return properties;
    }

    private String getCustomPath(final String filename) {
        return propertiesLocation.endsWith(".properties") ? propertiesLocation : propertiesLocation + filename;
    }

}

solusi yang bagus. Seperti konstruksi java8 itu! bagaimanapun saya tidak dapat menggunakannya karena saya membutuhkan beberapa biji Properti bukan hanya satu. Jika Anda melihat EDIT saya, solusi saya cukup mirip dan rapi untuk kasus penggunaan saya.
nir

Saya memposting versi untuk beberapa file, hanya untuk kelengkapan;)
mxsb

6

spring boot memungkinkan kita untuk menulis profil yang berbeda untuk menulis untuk lingkungan yang berbeda, misalnya kita dapat memiliki file properti terpisah untuk produksi, qa dan lingkungan lokal.

application-local.properties file dengan konfigurasi yang sesuai dengan mesin lokal saya

spring.profiles.active=local

spring.data.mongodb.host=localhost
spring.data.mongodb.port=27017
spring.data.mongodb.database=users
spring.data.mongodb.username=humble_freak
spring.data.mongodb.password=freakone

spring.rabbitmq.host=localhost
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
spring.rabbitmq.port=5672

rabbitmq.publish=true

Demikian pula, kita dapat menulis application-prod.properties dan application-qa.properties sebanyak file properti yang kita inginkan

kemudian tulis beberapa skrip untuk memulai aplikasi untuk lingkungan yang berbeda, misalnya

mvn spring-boot:run -Drun.profiles=local
mvn spring-boot:run -Drun.profiles=qa
mvn spring-boot:run -Drun.profiles=prod

5

Saya baru saja mengalami masalah yang mirip dengan ini dan akhirnya menemukan penyebabnya: file application.properties memiliki atribut kepemilikan dan rwx yang salah. Jadi ketika tomcat memulai, file application.properties berada di lokasi yang benar, tetapi dimiliki oleh pengguna lain:

$ chmod 766 application.properties

$ chown tomcat application.properties

Saya rasa saya memiliki masalah serupa. Saya telah menginstal tomcat di folder opt. Di mana Anda meletakkan file lamaran Anda? Haruskah saya mengubah atribut folder juga?
anakin59490

3

Versi modifikasi dari solusi @mxsb yang memungkinkan kita untuk menentukan banyak file dan dalam kasus saya ini adalah file yml.

Di application-dev.yml saya, saya menambahkan konfigurasi ini yang memungkinkan saya memasukkan semua yml yang memiliki -dev.yml di dalamnya. Ini bisa menjadi daftar file tertentu juga. "jalur kelas: /test/test.yml,classpath: /test2/test.yml"

application:
  properties:
    locations: "classpath*:/**/*-dev.yml"

Ini membantu untuk mendapatkan peta properti.

@Configuration

public class PropertiesConfig {

private final static Logger LOG = LoggerFactory.getLogger(PropertiesConfig.class);

@Value("${application.properties.locations}")
private String[] locations;

@Autowired
private ResourceLoader rl;

@Bean
Map<String, Properties> myProperties() {
    return stream(locations)
            .collect(toMap(filename -> filename, this::loadProperties));
}

private Properties loadProperties(final String filename) {

    YamlPropertySourceLoader loader = new YamlPropertySourceLoader();
    try {
        final Resource[] possiblePropertiesResources = ResourcePatternUtils.getResourcePatternResolver(rl).getResources(filename);
        final Properties properties = new Properties();
        stream(possiblePropertiesResources)
                .filter(Resource::exists)
                .map(resource1 -> {
                    try {
                        return loader.load(resource1.getFilename(), resource1);
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                }).flatMap(l -> l.stream())
                .forEach(propertySource -> {
                    Map source = ((MapPropertySource) propertySource).getSource();
                    properties.putAll(source);
                });

        return properties;
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}
}

Namun, jika seperti dalam kasus saya, saya ingin membagi file yml untuk setiap profil dan memuatnya dan menyuntikkannya langsung ke konfigurasi pegas sebelum inisialisasi kacang.

config
    - application.yml
    - application-dev.yml
    - application-prod.yml
management
    - management-dev.yml
    - management-prod.yml

... Anda mengerti

Komponennya sedikit berbeda

@Component
public class PropertiesConfigurer extends     PropertySourcesPlaceholderConfigurer
    implements EnvironmentAware, InitializingBean {

private final static Logger LOG = LoggerFactory.getLogger(PropertiesConfigurer.class);

private String[] locations;

@Autowired
private ResourceLoader rl;
private Environment environment;

@Override
public void setEnvironment(Environment environment) {
    // save off Environment for later use
    this.environment = environment;
    super.setEnvironment(environment);
}

@Override
public void afterPropertiesSet() throws Exception {
    // Copy property sources to Environment
    MutablePropertySources envPropSources = ((ConfigurableEnvironment) environment).getPropertySources();
    envPropSources.forEach(propertySource -> {
        if (propertySource.containsProperty("application.properties.locations")) {
            locations = ((String) propertySource.getProperty("application.properties.locations")).split(",");
            stream(locations).forEach(filename -> loadProperties(filename).forEach(source ->{
                envPropSources.addFirst(source);
            }));
        }
    });
}


private List<PropertySource> loadProperties(final String filename) {
    YamlPropertySourceLoader loader = new YamlPropertySourceLoader();
    try {
        final Resource[] possiblePropertiesResources = ResourcePatternUtils.getResourcePatternResolver(rl).getResources(filename);
        final Properties properties = new Properties();
        return stream(possiblePropertiesResources)
                .filter(Resource::exists)
                .map(resource1 -> {
                    try {
                        return loader.load(resource1.getFilename(), resource1);
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                }).flatMap(l -> l.stream())
                .collect(Collectors.toList());
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}

}


3

Jika Anda ingin mengganti nilai yang ditentukan dalam file application.properties, Anda dapat mengubah profil aktif saat menjalankan aplikasi dan membuat file properti aplikasi untuk profil tersebut. Jadi, sebagai contoh, mari tentukan profil aktif "override" dan kemudian, dengan asumsi Anda telah membuat file properti aplikasi baru bernama "application-override.properties" di bawah / tmp, maka Anda dapat menjalankan

java -jar yourApp.jar --spring.profiles.active="override" --spring.config.location="file:/tmp/,classpath:/" 

Nilai-nilai yang ditentukan dalam spring.config.location dievaluasi dalam urutan terbalik. Jadi, dalam contoh saya, classpat dievaluasi terlebih dahulu, lalu nilai file.

Jika file jar dan file "application-override.properties" ada di direktori saat ini, Anda sebenarnya dapat menggunakan

java -jar yourApp.jar --spring.profiles.active="override"

karena Spring Boot akan menemukan file properti untuk Anda


1
Ini akan memberitahu spring untuk menggunakan profil "override" sebagai profil aktif Anda; itu memang akan melampaui nilai yang ditentukan dalam file application.yml atau application.properties
acaruci

itu akan melihat ke dalam folder untuk setiap file konfigurasi .ymal atau .properties dalam kasus saya, saya hanya meletakkan application-profile.yml maka dibutuhkan dengan benar, Terima kasih @acaruci itu perjalanan yang menyenangkan
Ahmed Salem

0

Saya telah menemukan ini menjadi pola yang berguna untuk diikuti:

@RunWith(SpringRunner)
@SpringBootTest(classes = [ TestConfiguration, MyApplication ],
        properties = [
                "spring.config.name=application-MyTest_LowerImportance,application-MyTest_MostImportant"
                ,"debug=true", "trace=true"
        ]
)

Di sini kami mengganti penggunaan "application.yml" untuk menggunakan "application-MyTest_LowerImportance.yml" dan juga "application-MyTest_MostImportant.yml"
(Spring juga akan mencari file .properties)

Juga termasuk sebagai bonus tambahan adalah pengaturan debug dan jejak, pada baris terpisah sehingga Anda dapat mengomentarinya jika diperlukan;]

Debug / trace sangat berguna karena Spring akan membuang nama semua file yang dimuatnya dan yang dicoba dimuat.
Anda akan melihat baris seperti ini di konsol saat runtime:

TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'file:./config/application-MyTest_MostImportant.properties' (file:./config/application-MyTest_MostImportant.properties) resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'file:./config/application-MyTest_MostImportant.xml' (file:./config/application-MyTest_MostImportant.xml) resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'file:./config/application-MyTest_MostImportant.yml' (file:./config/application-MyTest_MostImportant.yml) resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'file:./config/application-MyTest_MostImportant.yaml' (file:./config/application-MyTest_MostImportant.yaml) resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'file:./config/application-MyTest_LowerImportance.properties' (file:./config/application-MyTest_LowerImportance.properties) resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'file:./config/application-MyTest_LowerImportance.xml' (file:./config/application-MyTest_LowerImportance.xml) resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'file:./config/application-MyTest_LowerImportance.yml' (file:./config/application-MyTest_LowerImportance.yml) resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'file:./config/application-MyTest_LowerImportance.yaml' (file:./config/application-MyTest_LowerImportance.yaml) resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'file:./application-MyTest_MostImportant.properties' (file:./application-MyTest_MostImportant.properties) resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'file:./application-MyTest_MostImportant.xml' (file:./application-MyTest_MostImportant.xml) resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'file:./application-MyTest_MostImportant.yml' (file:./application-MyTest_MostImportant.yml) resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'file:./application-MyTest_MostImportant.yaml' (file:./application-MyTest_MostImportant.yaml) resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'file:./application-MyTest_LowerImportance.properties' (file:./application-MyTest_LowerImportance.properties) resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'file:./application-MyTest_LowerImportance.xml' (file:./application-MyTest_LowerImportance.xml) resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'file:./application-MyTest_LowerImportance.yml' (file:./application-MyTest_LowerImportance.yml) resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'file:./application-MyTest_LowerImportance.yaml' (file:./application-MyTest_LowerImportance.yaml) resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'classpath:/config/application-MyTest_MostImportant.properties' resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'classpath:/config/application-MyTest_MostImportant.xml' resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'classpath:/config/application-MyTest_MostImportant.yml' resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'classpath:/config/application-MyTest_MostImportant.yaml' resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'classpath:/config/application-MyTest_LowerImportance.properties' resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'classpath:/config/application-MyTest_LowerImportance.xml' resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'classpath:/config/application-MyTest_LowerImportance.yml' resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'classpath:/config/application-MyTest_LowerImportance.yaml' resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'classpath:/application-MyTest_MostImportant.properties' resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'classpath:/application-MyTest_MostImportant.xml' resource not found
DEBUG 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Loaded config file 'file:/Users/xxx/dev/myproject/target/test-classes/application-MyTest_MostImportant.yml' (classpath:/application-MyTest_MostImportant.yml)
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'classpath:/application-MyTest_MostImportant.yaml' resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'classpath:/application-MyTest_LowerImportance.properties' resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'classpath:/application-MyTest_LowerImportance.xml' resource not found
DEBUG 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Loaded config file 'file:/Users/xxx/dev/myproject/target/test-classes/application-MyTest_LowerImportance.yml' (classpath:/application-MyTest_LowerImportance.yml)
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'classpath:/application-MyTest_LowerImportance.yaml' resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'file:./config/application-MyTest_MostImportant-test.properties' (file:./config/application-MyTest_MostImportant-test.properties) resource not found

-1

Saya mengalami banyak masalah saat mencoba mencari tahu. Ini pengaturan saya,

Dev Env: Windows 10, Java: 1.8.0_25, Spring Boot: 2.0.3. RELEASE, Spring: 5.0.7. RELEASE

Apa yang saya temukan adalah musim semi menempel dengan konsep "Default yang masuk akal untuk konfigurasi". Ini diterjemahkan menjadi, Anda harus memiliki semua file properti Anda sebagai bagian dari file perang Anda. Setelah berada di sana, Anda dapat menimpanya menggunakan properti baris perintah "--spring.config.additional-location" untuk menunjuk ke file properti eksternal. Tetapi ini TIDAK AKAN BEKERJA jika file properti bukan bagian dari file perang asli.

Kode demo: https://github.com/gselvara/spring-boot-property-demo/tree/master

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.