002.SpringBoot入門篇:屬性配置和使用
簡介
在使用SpringBoot構建專案的過程中,簡化了第三方外掛與Spring整合步驟,省略了繁瑣的XML配置內容,只需要在pom.xml檔案中引入模組化的Starter POMs,其中各個模組都有自己的預設配置,所以如果不是特殊應用場景,就只需要在application.properties中完成一些屬性配置就能開啟各模組的應用。
如果需要修改自定義修改預設配置,spring boot 提供了很簡便的方法,只需要在application.properties 中新增修改相應的配置。(spring boot啟動的時候會讀取application.properties這份預設配置)
注意:application.properties 是springboot預設的全域性變數配置檔案,預設位置是src/main/resources(如果不存在可以手動建立),SpingBoot的全域性配置檔案的作用是對一些預設配置的配置值進行修改。
修改預設配置
在application.properties檔案中可以完成日誌資訊、資料庫連線池、自定義變數等資訊的配置。完整的配置參考官方地址:SpringBoot屬性檔案application.properties配置文件(全部)
tomcat埠
springboot開發web專案的時候,預設的埠號是8080,如果需要修改該埠號,需要在application.properties 新增以下記錄:
#tomcat 埠號設定,重啟後生效
server.port=8888
重啟之後可以看到埠號已經被修改:
2018-03-05 14:13:08.663 INFO 6672 --- [ restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8888 (http) with context path ''
自定義屬性和使用
在配置檔案中定義
在配置檔案application.properties增加如下資訊:
#自定義屬性資訊並且在rest介面中返回使用
com.sunld.applicationp.chapter=springboot自定義屬性
com.sunld.applicationp.course=《springboot系統化學習》
#在配置檔案中可以使用屬性傳遞
com.sunld.applicationp.learning=我們正在學習${com.sunld.applicationp.course}中的${com.sunld.applicationp.chapter}
測試用例
引用類-CourseLearningApplicationProperties
package com.sunld.conf;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
//可以通過@Value("${屬性值}")獲取配置檔案中的屬性
@Component
public class CourseLearningApplicationProperties {
@Value("${com.sunld.applicationp.chapter}")
private String chapter;
@Value("${com.sunld.applicationp.course}")
private String course;
@Value("${com.sunld.applicationp.learning}")
private String learning;
public String getChapter() {
return chapter;
}
public void setChapter(String chapter) {
this.chapter = chapter;
}
public String getCourse() {
return course;
}
public void setCourse(String course) {
this.course = course;
}
public String getLearning() {
return learning;
}
public void setLearning(String learning) {
this.learning = learning;
}
}
測試類與結果
@Test
public void contextLoads() {
}
@Autowired
private CourseLearningApplicationProperties courseLearningApplicationProperties;
//測試自定義屬性的獲取
@Test
public void testCourseLearningApplicationProperties() {
System.out.println("章節:" + courseLearningApplicationProperties.getChapter());
System.out.println("課程:" + courseLearningApplicationProperties.getCourse());
System.out.println("學習:" + courseLearningApplicationProperties.getLearning());
}
結果輸出-亂碼:
章節:springboot自定义属性
課程:《springboot系统化å¦ä¹ 》
學習:我们æ£åœ¨å¦ä¹ 《springboot系统化å¦ä¹ 》ä¸çš„springboot自定义属性
亂碼解決
原因分析
在配置檔案application.properties中配置中文,在讀取時會出現亂碼,但是application.yml就顯示正常。
原因:Springboot是以iso-8859的編碼方式讀取的application.properties配置檔案。
解決方案
增加properties檔案
新增配置檔案
重新配置一個檔案“myconfig.properties”,在載入的例項類中增加如下程式碼:
@PropertySource(value = "classpath:/myconfig.properties" ,encoding = "UTF-8")
引用類-CourseLearningMyConfig
測試和輸出
@Autowired
private CourseLearningMyConfig courseLearningMyConfig;
//測試自定義屬性的獲取
@Test
public void testCourseLearningMyConfig() {
System.out.println("章節:" + courseLearningMyConfig.getChapter());
System.out.println("課程:" + courseLearningMyConfig.getCourse());
System.out.println("學習:" + courseLearningMyConfig.getLearning());
}
輸出:
章節:springboot自定義屬性-myconfig
課程:《springboot系統化學習》-myconfig
學習:我們正在學習《springboot系統化學習》-myconfig中的springboot自定義屬性-myconfig
使用yml配置檔案替換預設的properties配置檔案
配置檔案
使用application.yml替換application.properties檔案
com: #自定義屬性資訊並且在rest介面中返回使用
sunld:
applicationp:
chapter: springboot自定義屬性-yml
course: 《springboot系統化學習》-yml
#在配置檔案中可以使用屬性傳遞
learning: 我們正在學習${com.sunld.applicationp.course}中的${com.sunld.applicationp.chapter}
引用類-CourseLearningApplicationYml
測試與結果
@Autowired
private CourseLearningApplicationYml courseLearningApplicationYml;
//測試自定義屬性的獲取
@Test
public void testCourseLearningApplicationYml() {
System.out.println("章節:" + courseLearningApplicationYml.getChapter());
System.out.println("課程:" + courseLearningApplicationYml.getCourse());
System.out.println("學習:" + courseLearningApplicationYml.getLearning());
}
輸出結果:
章節:springboot自定義屬性-yml
課程:《springboot系統化學習》-yml
學習:我們正在學習《springboot系統化學習》-yml中的springboot自定義屬性-yml
@ConfigurationProperties讀取自定義屬性
在pom檔案增加依賴資訊
<!-- 增加使用@ConfigurationProperties讀取自定義屬性的依賴 -->
<!--spring boot 配置處理器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
增加解析配置檔案的bean
參考程式碼如下
package com.sunld.conf;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
//可以通過@Value("${屬性值}")獲取配置檔案中的屬性
@Component
@PropertySource(value = "classpath:/myconfig.properties" ,encoding = "UTF-8")
//@ConfigurationProperties註解主要用來把properties配置檔案轉化為bean來使用的,
//而@EnableConfigurationProperties註解的作用是@ConfigurationProperties註解生效。
@ConfigurationProperties(prefix="com.sunld.application")
public class CourseLearningMyConfigAuto {
private String chapter;
private String course;
private String learning;
public String getChapter() {
return chapter;
}
public void setChapter(String chapter) {
this.chapter = chapter;
}
public String getCourse() {
return course;
}
public void setCourse(String course) {
this.course = course;
}
public String getLearning() {
return learning;
}
public void setLearning(String learning) {
this.learning = learning;
}
}
測試與結果
@Autowired
private CourseLearningMyConfigAuto courseLearningMyConfigAuto;
//測試自定義屬性的獲取
@Test
public void testCourseLearningMyConfigAuto() {
System.out.println("章節:" + courseLearningMyConfigAuto.getChapter());
System.out.println("課程:" + courseLearningMyConfigAuto.getCourse());
System.out.println("學習:" + courseLearningMyConfigAuto.getLearning());
}
結果:
章節:springboot自定義屬性-myconfig
課程:《springboot系統化學習》-myconfig
學習:我們正在學習《springboot系統化學習》-myconfig中的springboot自定義屬性-myconfig
注意:需要在應用類或者application類,加@EnableConfigurationProperties({BlogProperties.class})註解或者在bean中增加@Component。不能同時新增,會導致單例模式的失敗。
釋出到rest
controller
package com.sunld.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.sunld.conf.CourseLearningMyConfigAuto;
//@RestController的意思就是controller裡面的方法都以json格式輸出,不用再寫什麼jackjson配置的了!
@RestController
public class PublishController {
@Autowired
private CourseLearningMyConfigAuto courseLearningMyConfigAuto;
@RequestMapping("/publishmyconfig")
public String publishMyConfig() {
System.out.println("章節:" + courseLearningMyConfigAuto.getChapter());
System.out.println("課程:" + courseLearningMyConfigAuto.getCourse());
System.out.println("學習:" + courseLearningMyConfigAuto.getLearning());
return courseLearningMyConfigAuto.toString();
}
}
測試
package com.sunld;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import com.sunld.controller.PublishController;
@RunWith(SpringRunner.class)
@SpringBootTest
/**
*
* @author sunliaodong
* 使用mockmvc進行,利用MockMvcResultHandlers.print()打印出執行結果。
* 使用MockServletContext來構建一個空的WebApplicationContext,
* 這樣我們建立的HelloController就可以在@Before函式中建立並傳遞到MockMvcBuilders.standaloneSetup()函式中。
*/
public class PublishControllerTest {
@Autowired
private PublishController publishController;
@Before
public void setUp() throws Exception {
//使用new的方式會導致引數獲取不到
//mvc = MockMvcBuilders.standaloneSetup(new PublishController()).build();
mvc = MockMvcBuilders.standaloneSetup(publishController).build();
}
@Test
public void getHello() throws Exception {
mvc.perform(MockMvcRequestBuilders.get("/publishmyconfig").accept(MediaType.APPLICATION_JSON))
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.content().string("HelloWorld ...."))
.andDo(MockMvcResultHandlers.print())
.andReturn();
}
}
隨機數
在一些情況下,有些引數我們需要希望它不是一個固定的值,比如金鑰、服務埠等。Spring Boot的屬性配置檔案中可以通過${random}來產生int值、long值或者string字串,來支援屬性的隨機值。
增加配置檔案random.properties
#隨機數配置檔案
#獲取隨機字串:${random.value}
com.sunld.randomValue=${random.value}
#獲取隨機int:${random.int}
com.sunld.randomInt=${random.int}
#獲取10以內的隨機數:${random.int(10)}
com.sunld.ranomdInt10=${random.int(10)}
#獲取10-20的隨機數:${random.int[10,20]}
com.sunld.randomInt10_20=${random.int[10,20]}
#獲取隨機long:${random.long}
com.sunld.randomLong=${random.long}
#獲取隨機uuid:${random.uuid}
com.sunld.randomUuid=${random.uuid}
增加bean
package com.sunld.conf;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
@PropertySource(value = {"classpath:/random.properties"}, encoding="UTF-8")
@Component
@ConfigurationProperties(prefix = "com.sunld")
public class RandomConfig {
//獲取隨機字串:${random.value}
private String randomValue;
//獲取隨機int:${random.int}
private String randomInt;
//獲取10以內的隨機數:${random.int(10)}
private String ranomdInt10;
//獲取10-20的隨機數:${random.int[10,20]}
private String randomInt10_20;
//獲取隨機long:${random.long}
private String randomLong;
//獲取隨機uuid:${random.uuid}
private String randomUuid;
//get\set
public String getRandomValue() {
return randomValue;
}
public void setRandomValue(String randomValue) {
this.randomValue = randomValue;
}
public String getRandomInt() {
return randomInt;
}
public void setRandomInt(String randomInt) {
this.randomInt = randomInt;
}
public String getRanomdInt10() {
return ranomdInt10;
}
public void setRanomdInt10(String ranomdInt10) {
this.ranomdInt10 = ranomdInt10;
}
public String getRandomInt10_20() {
return randomInt10_20;
}
public void setRandomInt10_20(String randomInt10_20) {
this.randomInt10_20 = randomInt10_20;
}
public String getRandomLong() {
return randomLong;
}
public void setRandomLong(String randomLong) {
this.randomLong = randomLong;
}
public String getRandomUuid() {
return randomUuid;
}
public void setRandomUuid(String randomUuid) {
this.randomUuid = randomUuid;
}
@Override
public String toString() {
return "RandomConfig [randomValue=" + randomValue + ", randomInt=" + randomInt + ", ranomdInt10=" + ranomdInt10
+ ", randomInt10_20=" + randomInt10_20 + ", randomLong=" + randomLong + ", randomUuid=" + randomUuid
+ "]";
}
}
增加測試類
package com.sunld;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import com.sunld.conf.RandomConfig;
@RunWith(SpringRunner.class)
@SpringBootTest
public class RandomConfigTest {
@Autowired
private RandomConfig randomConfig;
@Test
public void testGetRandomConfig() {
System.out.println(randomConfig);
}
}
多環境配置
說明
實際開發中可能會存在不能的環境:開發環境、測試環境、生產環境,而且每個環境的配置檔案(資料庫配置、日誌配置、埠配置等)可能不同,如果每次切換springboot的配置檔案相對比較麻煩,還容易出現錯誤。在spring boot中提供了多環境配置,使得我們切換環境變得簡便。
實現
建立檔案
在application.properties同目錄下根據實際情況建立相關檔案:
application-dev.properties//開發環境
application-test.properties//測試環境
application-prod.properties//生產環境
生效
在application.properties新增如下資訊:
#多環境配置
spring.profiles.active=dev
#引用測試的配置檔案
#spring.profiles.active=test
#引用生產的配置檔案
#spring.profiles.active=prod
測試與總結
分別在application-dev.properties、application-test.properties、application-prod.properties中配置server.port為8888、8889、8890,然後使用如下命令測試埠使用情況。
命令 | 埠結果 | 執行檔案 |
java -jar ***.jar | 8888 | application-dev.properties |
java -jar ***.jar –spring.profiles.active=test | 8889 | application-test.properties |
java -jar ***.jar –spring.profiles.active=prod | 8890 | application-prod.properties |
通過測試總結如下:
- application.properties中配置通用內容
- 在application.properties中設定spring.profiles.active={profile},比如(spring.profiles.active=dev)開啟開發環境為預設檔案
- application-{profile}.properties中配置各個環境不同的內容
- 通過命令啟用不同的配置
- 檔案格式要滿足application-{profile}.properties
通過命令列方式修改引數
比如修改埠號,則可以執行以下命令:
java -jar ****.jar --server.port=9090
在命令號中連續輸入兩個減號+屬性名=*,等同於在配置檔案中直接配置。雖然通過命令列的方式配置引數比較便利,但是也帶來了安全性問題,如果想禁用命令列輸入,可以在啟動類中增加如下程式碼:
springApplication.setAddCommandLineProperties(false);
完整程式碼參考如下:
package com.sunld;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ApplicationdemoApplication {
public static void main(String[] args) {
// SpringApplication.run(ApplicationdemoApplication.class, args);
/**
* 禁用命令列輸入引數
*/
SpringApplication springApplication = new SpringApplication(ApplicationdemoApplication.class);
springApplication.setAddCommandLineProperties(false);
springApplication.run(args);
}
}
總結
配置方式和優先順序
這些方式優先順序如下:
a. 命令列引數
b. 來自java:comp/env的JNDI屬性
c. Java系統屬性(System.getProperties())
d. 作業系統環境變數
e. RandomValuePropertySource配置的random.*屬性值
f. jar外部的application-{profile}.properties或application.yml(帶spring.profile)配置檔案
g. jar內部的application-{profile}.properties或application.yml(帶spring.profile)配置檔案
h. jar外部的application.properties或application.yml(不帶spring.profile)配置檔案
i. jar內部的application.properties或application.yml(不帶spring.profile)配置檔案
j. @Configuration註解類上的@PropertySource
k. 通過SpringApplication.setDefaultProperties指定的預設屬性