Spring 中如何根據(jù)環(huán)境切換配置 @Profile
Spring 根據(jù)環(huán)境切換配置 @Profile
我們實際開發(fā)中往往有多個環(huán)境,比如測試環(huán)境、開發(fā)環(huán)境、生產環(huán)境等;不同的環(huán)境往往配置也有區(qū)別,一直切換環(huán)境的配置很麻煩,Spring 為我們提供了一個注解,可以快速切換環(huán)境配置。
@Profile
我們新建一個配置,作用是注冊三個數(shù)據(jù)源,因為不同的環(huán)境使用的數(shù)據(jù)庫一般不一樣:
@Configuration @PropertySource("classpath:/person.properties") public class MainConfigOfProfile implements EmbeddedValueResolverAware { @Value("${db.user}") private String user; @Value("${db.url}") private String url; private String driver; // 指定組件在那個環(huán)境下才能注冊到組件中: 不指定則都能注冊 @Profile("test") @Bean("testDataSource") public DataSource dataSourceTest(@Value("${db.password}") String pwd) throws PropertyVetoException { ComboPooledDataSource dataSource = new ComboPooledDataSource(); dataSource.setUser(user); dataSource.setPassword(pwd); dataSource.setJdbcUrl(url); dataSource.setDriverClass(driver); return dataSource; } @Profile("dev") @Bean("devDataSource") public DataSource dataSourceDev(@Value("${db.password}") String pwd) throws PropertyVetoException { ComboPooledDataSource dataSource = new ComboPooledDataSource(); dataSource.setUser(user); dataSource.setPassword(pwd); dataSource.setJdbcUrl(url); dataSource.setDriverClass(driver); return dataSource; } @Profile("prod") @Bean("prodDataSource") public DataSource dataSourceProd(@Value("${db.password}") String pwd) throws PropertyVetoException { ComboPooledDataSource dataSource = new ComboPooledDataSource(); dataSource.setUser(user); dataSource.setPassword(pwd); dataSource.setJdbcUrl(url); dataSource.setDriverClass(driver); return dataSource; } @Override public void setEmbeddedValueResolver(StringValueResolver resolver) { this.driver = resolver.resolveStringValue("${db.driver}"); } }
這里在方法上使用了 @Profile 注解來表示對應的環(huán)境,也就是說當指定環(huán)境之后,只有標注對應環(huán)境名的 Bean 才能被注冊到容器中去,沒有標注任何 @Profile 的方法默認直接注冊進去。
環(huán)境區(qū)分好了如何啟動對應的環(huán)境?
有兩種方式:
- 使用命令行參數(shù);
- 使用無參構造創(chuàng)建容器;
在 IDEA 中可以設置啟動參數(shù),加上如下參數(shù):
-Dspring.profiles.active=test
其中 test 可以換成在 @Profile 中配置的名稱。
這樣就能指定環(huán)境啟動了,還可以使用無參構造創(chuàng)建容器。
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); context.getEnvironment().setActiveProfiles("prod", "dev"); context.register(MainConfigOfProfile.class); context.refresh();
都是可以的,這里同時指定了兩個環(huán)境:prod 和 dev。
@Profile 也可以放在類上,這樣整個類就對應指定的環(huán)境名。
在 IDEA 中,還可以使用圖形化界面快速切換所在的環(huán)境。
Spring配置profile,切換開發(fā)環(huán)境和測試生產環(huán)境
項目的開發(fā)環(huán)境和測試生產環(huán)境要配置的數(shù)據(jù)庫,redis等等,連接地址都不一樣。這樣在項目部署到測試,生產時總要挨個修改這些配置。通過Spring的profile可以控制在不同的環(huán)境在Spring容器中注冊不同的配置Bean,然后用一個總開關控制在什么環(huán)境用什么配置。
public interface CompactDisc { void play(); }
有兩個類實現(xiàn)了它
public class MusicDisc implements CompactDisc { private String music = "菊花臺"; /** * @see com.xu.CompactDisc#play() */ @Override public void play() { System.out.println(music); } } public class MovieDisc implements CompactDisc { private String MovieConfig = "泰坦尼克號"; /** * @see com.xu.CompactDisc#play() */ @Override public void play() { musicDisc.play(); } }
基于java配置
@Configuration public class MusicConfig { @Bean @Profile("dev") public CompactDisc musicDisc(){ return new MusicDisc(); } } @Configuration public class MovieConfig { @Bean @Profile("pro") public CompactDisc movieDisc(){ return new MovieDisc(); } }
@Controller public class DiscController { @Autowired(required=false) private CompactDisc disc; @RequestMapping("/disc") public String disc(){ System.out.println("------進入controller--------"); musicDisc.play(); return "ewr"; } }
web.xml配置
<context-param> <param-name>spring.profiles.default</param-name> <param-value>dev</param-value> </context-param> <context-param> <param-name>spring.profiles.active</param-name> <param-value>pro</param-value> </context-param> <servlet> <servlet-name>DispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:/applicationContext.xml</param-value> </init-param> <init-param> <param-name>spring.profiles.default</param-name> <param-value>dev</param-value> </init-param> <load-on-startup> 1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>DispatcherServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
Controller類里有一個CompactDisc 的注入,由于上面MovieDisc 和MusicDisc 都實現(xiàn)了CompactDisc ,那么在Spring容器啟動是就要選擇一個注冊,這個選擇是通過@Profile(“pro”)注解標識的。然后通過在webxml里面添加spring.profiles.default控制
具體的控制規(guī)則如下:
xml里面配置了spring.profiles.default和spring.profiles.active,當沒有active時默認defalult中配置的dev,對應配置類中@Profile(“dev”)標識的MusicDisc會被創(chuàng)建;當配置了active時,@Profile(“dev”)會被創(chuàng)建。未被@Profile標識的bean始終會被創(chuàng)建。所以根據(jù)上面的配置,當訪問http://localhost:8080/Spring/disc 時輸出是
------進入controller--------
泰坦尼克號
這樣在部署不同的環(huán)境時通過控制spring.profiles.active和就ok了,而不必去一個一個的修改那些配置了。
xml配置方式
<beans profile="pro"> <bean id="compactDisc" class="com.xu.MusicDisc"></bean> </beans>
以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
解決@RequestMapping和@FeignClient放在同一個接口上遇到的坑
這篇文章主要介紹了解決@RequestMapping和@FeignClient放在同一個接口上遇到的坑,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-07-07SpringBoot工程Docker多環(huán)境中使用同一個Jar包解決方案
在Docker多環(huán)境部署中,SpringBoot工程可以通過環(huán)境變量來動態(tài)改變配置,無需重新打包,利用volume掛載或docker?cp命令,可以將配置文件直接傳入容器,提高部署效率,并保證安全性2024-09-09