Nous travaillons sur une application Web Spring Boot et la base de données que nous utilisons est MySql ;
la configuration que nous avons est que nous la testons d'abord localement (cela signifie que nous devons installer MySql sur notre PC);
puis nous poussons vers Bitbucket ;
Jenkins détecte automatiquement le nouveau push vers Bitbucket et fait une compilation dessus (pour que Jenkins mvn build passe, nous devons également installer MySql sur les machines virtuelles qui exécutent Jenkins).
si la construction de Jenkins réussit, nous transmettons le code à notre application sur OpenShift (en utilisant le plugin de déploiement OpenShift sur Jenkins).
Le problème que nous avons, comme vous l'avez peut-être déjà compris, est que:
dans
application.properties
nous ne pouvons pas coder en dur les informations MySql. Étant donné que notre projet sera exécuté à 3 endroits différents ( local , Jenkins et OpenShift ), nous devons rendre le champ de source de données dynamiqueapplication.properties
(nous savons qu'il existe différentes façons de le faire, mais nous travaillons sur cette solution pour le moment).spring.datasource.url = spring.datasource.username = spring.datasource.password =
La solution que nous avons trouvée est de créer des variables d'environnement système localement et dans la VM Jenkins (en les nommant de la même manière qu'OpenShift les nomme) et en leur attribuant les bonnes valeurs respectivement:
export OPENSHIFT_MYSQL_DB_HOST="jdbc:mysql://localhost"
export OPENSHIFT_MYSQL_DB_PORT="3306"
export OPENSHIFT_MYSQL_DB_USERNAME="root"
export OPENSHIFT_MYSQL_DB_PASSWORD="123asd"
Nous avons fait cela et cela fonctionne. Nous avons également vérifié Map<String, String> env = System.getenv();
que les variables d'environnement peuvent être transformées en variables java en tant que telles:
String password = env.get("OPENSHIFT_MYSQL_DB_PASSWORD");
String userName = env.get("OPENSHIFT_MYSQL_DB_USERNAME");
String sqlURL = env.get("OPENSHIFT_MYSQL_DB_HOST");
String sqlPort = env.get("OPENSHIFT_MYSQL_DB_PORT");
Maintenant, la seule chose qui reste est que nous devons utiliser ces variables java dans notre application.properties
et c'est ce avec quoi nous avons des problèmes.
Dans ce dossier, et comment, avons-nous besoin d'assigner les password
, userName
, sqlURL
et sqlPort
variables pour application.properties
être en mesure de les voir et comment pouvons-nous les inclure dans application.properties
?
Nous avons essayé de nombreuses choses, dont:
spring.datasource.url = ${sqlURL}:${sqlPort}/"nameofDB"
spring.datasource.username = ${userName}
spring.datasource.password = ${password}
Pas de chance pour l'instant. Nous ne mettons probablement pas ces variables d'environnement dans la bonne classe / dossier ou les utilisons de manière incorrecte dans application.properties
.
Votre aide est très appréciée!!
Merci!
Réponses:
Vous n'avez pas besoin d'utiliser des variables java. Pour inclure des variables d'environnement système, ajoutez les éléments suivants à votre
application.properties
fichier:spring.datasource.url = ${OPENSHIFT_MYSQL_DB_HOST}:${OPENSHIFT_MYSQL_DB_PORT}/"nameofDB" spring.datasource.username = ${OPENSHIFT_MYSQL_DB_USERNAME} spring.datasource.password = ${OPENSHIFT_MYSQL_DB_PASSWORD}
Mais la manière suggérée par @Stefan Isele est plus préférable, parce que dans ce cas , vous devez déclarer une seule variable d'env:
spring.profiles.active
. Spring lira automatiquement le fichier de propriétés approprié parapplication-{profile-name}.properties
modèle.la source
docker run --name my-tomcat -p 127.0.0.1:8080:8080 -e APP_DB_DB=mydb -e APP_DB_USER=dbuser -e APP_DB_PASS=dbpass --link mongo-myapp:mongo -v /path-to/tomcat/webapps:/usr/local/tomcat/webapps -d tomcat:8-jre8-alpine
spring.activemq.broker-url
alors la variable d'environnement correspondant serait:SPRING_ACTIVEMQ_BROKER_URL
. les points et les tirets sont automatiquement convertis en traits de soulignement. Ceci est extrêmement pratique lorsque vous travaillez avec des conteneurs / bottes à ressort.Le moyen le plus simple d'avoir différentes configurations pour différents environnements est d'utiliser des profils de ressort. Voir configuration externalisée .
Cela vous donne beaucoup de flexibilité. Je l'utilise dans mes projets et c'est extrêmement utile. Dans votre cas, vous auriez 3 profils: 'local', 'jenkins' et 'openshift'
Vous avez alors 3 profil des fichiers de propriétés spécifiques:
application-local.properties
,application-jenkins.properties
etapplication-openshift.properties
Vous pouvez y définir les propriétés de l'environnement concerné. Lorsque vous exécutez l'application, vous devez spécifier le profil à activer comme ceci:
-Dspring.profiles.active=jenkins
Éditer
Selon la documentation de printemps, vous pouvez définir la variable d'environnement système
SPRING_PROFILES_ACTIVE
pour activer les profils sans avoir besoin de la passer en paramètre.existe-t-il un moyen de transmettre l'option de profil actif pour l'application Web au moment de l'exécution?
Non. Spring détermine les profils actifs comme l'une des premières étapes, lors de la création du contexte d'application. Les profils actifs sont ensuite utilisés pour décider quels fichiers de propriétés sont lus et quels beans sont instanciés. Une fois l'application démarrée, cela ne peut pas être modifié.
la source
application-production.properties
serait déployé sur la machine de production de manière sécurisée et ne se trouverait généralement pas dans le référentiel de code source de l'application.Flayway ne reconnaît pas les variables d'environnement directes dans l' application.properties (Spring-Boot V2.1). par exemple
spring.datasource.url=jdbc:mysql://${DB_HOSTNAME}:${DB_PORT}/${DB_DATABASE} spring.datasource.username=${DB_USER} spring.datasource.password=${DB_PASS}
Pour résoudre ce problème, j'ai fait ces variables d'environnement, généralement je crée le fichier .env:
SPRING_DATASOURCE_URL=jdbc:mysql://127.0.0.1:3306/place SPRING_DATASOURCE_USERNAME=root SPRING_DATASOURCE_PASSWORD=root
Et exportez les variables vers mon environnement:
export $(cat .env | xargs)
Et enfin, lancez simplement la commande
mvn spring-boot:run
Ou exécutez votre fichier jar
java -jar target/your-file.jar
Il existe une autre approche ici: https://docs.spring.io/spring-boot/docs/2.1.0.BUILD-SNAPSHOT/maven-plugin/examples/run-env-variables.html
la source
C'est en réponse à un certain nombre de commentaires car ma réputation n'est pas assez élevée pour commenter directement.
Vous pouvez spécifier le profil au moment de l'exécution tant que le contexte d'application n'a pas encore été chargé.
// Previous answers incorrectly used "spring.active.profiles" instead of // "spring.profiles.active" (as noted in the comments). // Use AbstractEnvironment.ACTIVE_PROFILES_PROPERTY_NAME to avoid this mistake. System.setProperty(AbstractEnvironment.ACTIVE_PROFILES_PROPERTY_NAME, environment); ApplicationContext applicationContext = new ClassPathXmlApplicationContext("/META-INF/spring/applicationContext.xml");
la source
Voici un extrait de code à travers une chaîne de fichiers de propriétés d'environnements en cours de chargement pour différents environnements.
Fichier de propriétés sous les ressources de votre application ( src / main / resources ): -
1. application.properties 2. application-dev.properties 3. application-uat.properties 4. application-prod.properties
Idéalement, application.properties contient toutes les propriétés courantes qui sont accessibles pour tous les environnements et les propriétés liées à l'environnement ne fonctionnent que sur l'environnement spécifié. donc l'ordre de chargement de ces fichiers de propriétés sera de telle manière -
application.properties -> application.{spring.profiles.active}.properties.
Extrait de code ici: -
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; public class PropertiesUtils { public static final String SPRING_PROFILES_ACTIVE = "spring.profiles.active"; public static void initProperties() { String activeProfile = System.getProperty(SPRING_PROFILES_ACTIVE); if (activeProfile == null) { activeProfile = "dev"; } PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer = new PropertySourcesPlaceholderConfigurer(); Resource[] resources = new ClassPathResource[] {new ClassPathResource("application.properties"), new ClassPathResource("application-" + activeProfile + ".properties")}; propertySourcesPlaceholderConfigurer.setLocations(resources); } }
la source
Peut-être que j'écris cela trop tard, mais j'ai eu le même problème lorsque j'ai essayé de remplacer les méthodes de lecture des propriétés.
Mon problème a été: 1) Lire la propriété de env si cette propriété a été définie dans env 2) Lire la propriété de la propriété système si cette propriété a été définie dans la propriété système 3) Et enfin, lire à partir des propriétés de l'application.
Donc, pour résoudre ce problème, je vais à ma classe de configuration de bean
@Validated @Configuration @ConfigurationProperties(prefix = ApplicationConfiguration.PREFIX) @PropertySource(value = "${application.properties.path}", factory = PropertySourceFactoryCustom.class) @Data // lombok public class ApplicationConfiguration { static final String PREFIX = "application"; @NotBlank private String keysPath; @NotBlank private String publicKeyName; @NotNull private Long tokenTimeout; private Boolean devMode; public void setKeysPath(String keysPath) { this.keysPath = StringUtils.cleanPath(keysPath); } }
Et écrasez l'usine dans @PropertySource. Et puis j'ai créé ma propre implémentation pour lire les propriétés.
public class PropertySourceFactoryCustom implements PropertySourceFactory { @Override public PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException { return name != null ? new PropertySourceCustom(name, resource) : new PropertySourceCustom(resource); } }
Et créé PropertySourceCustom
public class PropertySourceCustom extends ResourcePropertySource { public LifeSourcePropertySource(String name, EncodedResource resource) throws IOException { super(name, resource); } public LifeSourcePropertySource(EncodedResource resource) throws IOException { super(resource); } public LifeSourcePropertySource(String name, Resource resource) throws IOException { super(name, resource); } public LifeSourcePropertySource(Resource resource) throws IOException { super(resource); } public LifeSourcePropertySource(String name, String location, ClassLoader classLoader) throws IOException { super(name, location, classLoader); } public LifeSourcePropertySource(String location, ClassLoader classLoader) throws IOException { super(location, classLoader); } public LifeSourcePropertySource(String name, String location) throws IOException { super(name, location); } public LifeSourcePropertySource(String location) throws IOException { super(location); } @Override public Object getProperty(String name) { if (StringUtils.isNotBlank(System.getenv(name))) return System.getenv(name); if (StringUtils.isNotBlank(System.getProperty(name))) return System.getProperty(name); return super.getProperty(name); } }
Donc, cela m'a aidé.
la source
En utilisant Spring Context 5.0, j'ai réussi à charger le fichier de propriétés correct en fonction de l'environnement système via l'annotation suivante
@PropertySources({ @PropertySource("classpath:application.properties"), @PropertySource("classpath:application-${MYENV:test}.properties")})
Ici, la valeur MYENV est lue à partir de l'environnement système et si l'environnement système n'est pas présent, le fichier de propriétés de l'environnement de test par défaut sera chargé, si je donne une valeur MYENV erronée - il ne parviendra pas à démarrer l'application.
Remarque: pour chaque profil, vous voulez maintenir - vous devrez créer un fichier application- [profile] .property et bien que j'aie utilisé Spring context 5.0 et non Spring boot - je pense que cela fonctionnera également sur Spring 4.1
la source
J'ai été confronté au même problème que l'auteur de la question. Pour notre cas, les réponses à cette question n'étaient pas suffisantes car chacun des membres de mon équipe avait un environnement local différent et nous devions absolument
.gitignore
du fichier qui avait la chaîne de connexion et les informations d'identification différentes, afin que les gens ne commettent pas le fichier commun par erreur et rompre les connexions db des autres.De plus, lorsque nous avons suivi la procédure ci-dessous, il était facile de déployer sur différents environnements et, en prime, nous n'avions pas du tout besoin d'informations sensibles dans le contrôle de version .
Obtenir l'idée du framework PHP Symfony 3 qui a un
parameters.yml
(.gitignored) et unparameters.yml.dist
(qui est un exemple qui crée le premier à traverscomposer install
),J'ai fait ce qui suit en combinant les connaissances des réponses ci-dessous: https://stackoverflow.com/a/35534970/986160 et https://stackoverflow.com/a/35535138/986160 .
Essentiellement, cela donne la liberté d'utiliser l' héritage des configurations de ressort et de choisir les profils actifs via la configuration en haut, ainsi que les informations d'identification supplémentaires sensibles comme suit:
application.yml.dist (exemple)
spring: profiles: active: local/dev/prod datasource: username: password: url: jdbc:mysql://localhost:3306/db?useSSL=false&useLegacyDatetimeCode=false&serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
application.yml (.gitignore-d sur le serveur de développement)
spring: profiles: active: dev datasource: username: root password: verysecretpassword url: jdbc:mysql://localhost:3306/real_db?useSSL=false&useLegacyDatetimeCode=false&serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
application.yml (.gitignore-d sur la machine locale)
spring: profiles: active: dev datasource: username: root password: rootroot url: jdbc:mysql://localhost:3306/xampp_db?useSSL=false&useLegacyDatetimeCode=false&serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
application-dev.yml (propriétés supplémentaires spécifiques à l'environnement non sensibles)
spring: datasource: testWhileIdle: true validationQuery: SELECT 1 jpa: show-sql: true format-sql: true hibernate: ddl-auto: create-droop naming-strategy: org.hibernate.cfg.ImprovedNamingStrategy properties: hibernate: dialect: org.hibernate.dialect.MySQL57InnoDBDialect
La même chose peut être faite avec .properties
la source
Si les fichiers de propriétés sont externalisés en tant que variables d'environnement, la configuration de l'exécution peut être ajoutée dans l'EDI:
--spring.config.additional-location={PATH_OF_EXTERNAL_PROP}
la source