1. 程式人生 > >002.SpringBoot入門篇:屬性配置和使用

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指定的預設屬性

參考地址

程式碼地址