亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

springboot中application.yml的文件配置是怎樣的

發布時間:2021-09-29 17:48:17 來源:億速云 閱讀:207 作者:柒染 欄目:大數據

今天就跟大家聊聊有關springboot中application.yml的文件配置是怎樣的,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結了以下內容,希望大家根據這篇文章可以有所收獲。

springboot配置文件

springboot最簡便的地方,一是開箱即用,二是配置簡單,配置文件路徑一般在/src/main/resources 下,主要配置有兩種形式,一種是properties文件,一種是springboot官方推薦的yml后綴的文件

一、properties/yml文件配置spring
  1. 使用properties文件springboot配置

#配置內置tomcat啟動端口
server.port=8080
#給程序起個名字
spring.application.name=boot-helloworld

properties文件作為眾多配置文件中的佼佼者,使用比較方便,格式簡單,等號左邊為屬性,右邊為值,可以說是簡單方便

  1. 使用yml文件作為springboot配置

#配置內置tomcat啟動端口
server:
  port: 8080
#應用名稱
spring:
  application:
    name: boot-helloworld

yml文件中,有著嚴格的層級關系,以空格或者Tab縮進表示,英文冒號結尾,末尾層級最后空至少一個英文空格,然后填寫該屬性的值,優點在于,層級表示可以簡單的連著寫多個值,例如:

spring:
  application:
    name: boot-helloworld
#redis連接池配置, 可以換行保持縮進,連著寫
  redis:
    host: localhost
    port: 6379
    password: password
    timeOut: 5000
    maxIdle: 50
    maxWaitMillis: 5000
    maxTotal: 500
二、springboot常用配置項

以下摘自 spring-boot-autoconfiguration.jar中的spring-configuration-metadata.json,另外,springboot默認配置都在此包中的spring-autoconfigure-metadata.properties文件中有指定,有需要的同學可以去翻閱,不同springboot版本,默認的屬性有區別

  1. 指定項目啟動端口

server:
  port: 8081
  1. 給項目指定名稱

spring:
  application:
    name: boot-helloworld
  1. 日志級別

#默認情況下springboot使用Logback作為日志框架
#logging.level開頭,指定一個依賴的groupId然后,指定日志級別
logging:
  level:
    org.springframeword.web: debug
  1. 多個環境下指定啟動使用的配置環境

#只需要在application.properties中設置spring.profiles.active=prod來指定活動的profile即可
#如下表示采用application-test.yml
#默認使用default(application.yml),這樣可以區分開發、線上、測試,preview等環境
spring:
  profiles:
    active: test
  1. 指定項目路徑

#在所有接口訪問路徑之前需要加/boot
server:
  servlet:
    context-path: /boot
三、基于@Value注解讀取自定義屬性

以下代碼僅供演示

1: User.java

/**
 * 當作一個配置項,簡單處理
 * @author Calvin
 * @date 2019/07/24
 */
public class User {

    /**
     * ID
     */
    private String id;

    /**
     * 名字
     */
    private String userName;

    /**
     * 年齡
     */
    private Integer age;

    /**
     * 性別
     */
    private String gender;

    /**
     * 所使用的操作系統
     */
    private String systemName;


    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public String getSystemName() {
        return systemName;
    }

    public void setSystemName(String systemName) {
        this.systemName = systemName;
    }

    @Override
    public String toString() {
        return "User{" +
                "id='" + id + '\'' +
                ", userName='" + userName + '\'' +
                ", age=" + age +
                ", gender='" + gender + '\'' +
                ", systemName='" + systemName + '\'' +
                '}';
    }
}

2: application.yml

spring:
  application:
    name: boot-helloworld

logging:
  level:
    org.springframeword.web: debug
server:
  servlet:
    context-path: /boot

# admin年齡的值配置
admin:
  age: 20

3:ValueController.java

/**
 * 測試@Value注解的各種方式
 * @author Calvin
 * @date 2019/07/24
 */
@RestController
@RequestMapping("/value")
public class ValueController {


    /**
     * ID 采用表達式注解
     */
    @Value("#{ T(java.util.UUID).randomUUID()}")
    private String adminId;

    /**
     * name 采用值注解獲取一個UUID
     */
    @Value("Calvin")
    private String adminName;

    /**
     * gender 給定一個默認值,如果沒有定義,就采用默認值
     */
    @Value("${admin.gender: 男}")
    private String adminGender;

    /**
     * 注入yml文件中的admin.age
     */
    @Value("${admin.age}")
    private Integer adminAge;

    /**
     * 采用表達式獲取系統變量
     */
    @Value("#{systemProperties['os.name']}")
    private String systemName;

    /**
     * 獲取用戶信息
     * @return
     */
    @GetMapping("/getUserInfo")
    public User getAdminInfo(){
        User admin = new User();
        admin.setId(adminId);
        admin.setUserName(adminName);
        admin.setAge(adminAge);
        admin.setGender(adminGender);
        admin.setSystemName(systemName);
        return admin;
    }

}

4:調用結果
springboot中application.yml的文件配置是怎樣的

springboot配置文件不僅可以使用@Value注解, 還有很多好玩的方式,另一個可以使用@ConfigurationProperties去注入到某個Bean中,具體方法此處不做調研

四、yml配置文件加載源碼解讀

源碼解讀非常不容易,筆者也是參考了網上很多資源,才撰寫出這部分,希望大家多多指教,此處就不畫圖了,畫圖功底不好

1: 調用鏈
BootApplication.main()

//main方法,程序入口
SpringApplication.run(BootApplication.class, args);

SpringApplication.run():1202

//實例化SpringApplication并且調用run方法
return new SpringApplication(primarySources).run(args);

SpringApplication.run():304

//此方法中實例化Environment
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);

SpringApplication.prepareEnvironment():338

//因為我是Web程序,用的是spring-boot-starter-web依賴,所以是StandardServletEnvironment
private ConfigurableEnvironment getOrCreateEnvironment() {
	//省略部分代碼
	return new StandardServletEnvironment();
}
//因為StandardServletEnviroment extends AbstractEnvironment
//而AbstractEnvironment構造器中中調用了customizePropertySources()方法
public AbstractEnvironment() {
	//模板方法,大家都懂得
	customizePropertySources(this.propertySources);
}

StandardServletEnvironment.customizePropertySources():54

protected void customizePropertySources(MutablePropertySources propertySources) {
	//將servletConfigInitParams添加進PropertySource中
	propertySources.addLast(new StubPropertySource(SERVLET_CONFIG_PROPERTY_SOURCE_NAME));
	//將servletContextInitParams添加進PropertySource中
	propertySources.addLast(new StubPropertySource(SERVLET_CONTEXT_PROPERTY_SOURCE_NAME));
	if (JndiLocatorDelegate.isDefaultJndiEnvironmentAvailable()) {
		propertySources.addLast(new JndiPropertySource(JNDI_PROPERTY_SOURCE_NAME));
	}
	//調用AbstractEnvironment.customizePropertySources()方法
	super.customizePropertySources(propertySources);
}

AbstractEnvironment.customizePropertySources():77

@Override
protected void customizePropertySources(MutablePropertySources propertySources) {
	//添加systemProperties, 添加的是System.getProperties(),是一個Native方法,主要屬性是
	//java.runtime.name | java.vm.version等系統配置的屬性
	propertySources.addLast(
		new PropertiesPropertySource(SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, getSystemProperties()));
	//添加systemEnvironment, 也就是系統環境變量, 其中包含JAVA_HOME等屬性
	propertySources.addLast(
		new SystemEnvironmentPropertySource(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, getSystemEnvironment()));
}

至此結束,ConfigurableEnvironment對象中添加了四個propertySource,分別為:
[servletConfigInitParams, servletContextInitParams , systemProperties, systemEnvironment]

看完 SpringApplication.prepareEnvironment():338所作的事情, 接著看listeners.environmentPrepared(environment):340,這也是yml文件配置的入口

SpringApplicationRunListeners.environmentPremared

public void environmentPrepared(ConfigurableEnvironment environment) {
	for (SpringApplicationRunListener listener : this.listeners) {
		listener.environmentPrepared(environment);
	}
}

這個方法中加載了很多個Listener,每個的調用鏈也非常深,這里簡短點,


SpringApplicationRunListeners.java
environmentPrepared-->


SimpleApplcationEventMulticaster.java
multicastEvent():126&131-->
invokeListener():159-->
doInvokeListener(listener, event) -->


CofigFileApplicationListener.java
onApplicationEvent():-->
addPostProcessors();-->
new Loader(environment, resourceLoader).load():202-->
load(String location, String name, Profile profile, DocumentFilterFactory filterFactory,DocumentConsumer consumer):429-->


前方高能,筆者跟代碼跟的非常之辛苦,廢話少說,ConfigFileApplicationListener.java中核心代碼

ConfigFileApplicationListener.onApplicationEvent()

@Override
public void onApplicationEvent(ApplicationEvent event) {
	if (event instanceof ApplicationEnvironmentPreparedEvent) {
		onApplicationEnvironmentPreparedEvent((ApplicationEnvironmentPreparedEvent) event);
	}
	if (event instanceof ApplicationPreparedEvent) {
		onApplicationPreparedEvent(event);
	}
}

ConfigFileApplicationListener.load()

private void load(String location, String name, Profile profile, DocumentFilterFactory filterFactory,
		DocumentConsumer consumer) {
	if (!StringUtils.hasText(name)) {
		for (PropertySourceLoader loader : this.propertySourceLoaders) {
			if (canLoadFileExtension(loader, location)) {
				load(loader, location, profile, filterFactory.getDocumentFilter(profile), consumer);
				return;
			}
		}
	}
	Set<String> processed = new HashSet<>();
	//遍歷propertySourceLoaders
	for (PropertySourceLoader loader : this.propertySourceLoaders) {
		for (String fileExtension : loader.getFileExtensions()) {
			if (processed.add(fileExtension)) {
				//尋找配置文件
				loadForFileExtension(loader, location + name, "." + fileExtension, profile, filterFactory,
						consumer);
			}
		}
	}
}

this.propertySourceLoaders中有兩個類,都是PropertySourceLoader的實現類,分別是

[
	org.springframework.boot.env.PropertiesPropertySourceLoader, 
	org.springframework.boot.env.YamlPropertySourceLoader
]

PropertiesPropertySourceLoader.java

/**
 *<p>
 *  <li>此類負責加載["properties", "xml"]后綴的配置文件
 *  <li>loadProerties負責讀取配置文件中的內容
 *</p>
 */
public class PropertiesPropertySourceLoader implements PropertySourceLoader {

	private static final String XML_FILE_EXTENSION = ".xml";

	@Override
	public String[] getFileExtensions() {
		return new String[] { "properties", "xml" };
	}

	@Override
	public List<PropertySource<?>> load(String name, Resource resource) throws IOException {
		Map<String, ?> properties = loadProperties(resource);
		if (properties.isEmpty()) {
			return Collections.emptyList();
		}
		return Collections.singletonList(new OriginTrackedMapPropertySource(name, properties));
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	private Map<String, ?> loadProperties(Resource resource) throws IOException {
		String filename = resource.getFilename();
		if (filename != null && filename.endsWith(XML_FILE_EXTENSION)) {
			return (Map) PropertiesLoaderUtils.loadProperties(resource);
		}
		return new OriginTrackedPropertiesLoader(resource).load();
	}

}

YamlPropertySourceLoader.java

/**
 *<p>
 *  <li>此類負責加載["yml", "yaml"]后綴的配置文件
 *  <li>load負責讀取配置文件中的內容
 *</p>
 */
public class YamlPropertySourceLoader implements PropertySourceLoader {

	@Override
	public String[] getFileExtensions() {
		return new String[] { "yml", "yaml" };
	}

	@Override
	public List<PropertySource<?>> load(String name, Resource resource) throws IOException {
		if (!ClassUtils.isPresent("org.yaml.snakeyaml.Yaml", null)) {
			throw new IllegalStateException(
					"Attempted to load " + name + " but snakeyaml was not found on the classpath");
		}
		List<Map<String, Object>> loaded = new OriginTrackedYamlLoader(resource).load();
		if (loaded.isEmpty()) {
			return Collections.emptyList();
		}
		List<PropertySource<?>> propertySources = new ArrayList<>(loaded.size());
		for (int i = 0; i < loaded.size(); i++) {
			String documentNumber = (loaded.size() != 1) ? " (document #" + i + ")" : "";
			propertySources.add(new OriginTrackedMapPropertySource(name + documentNumber, loaded.get(i)));
		}
		return propertySources;
	}

}

至此結束,找到了加載application.yml文件的位置,接著往下跟 會在此方法中加載,具體調用了Yaml類構造器,StreamReader去讀取文件

public List<Map<String, Object>> load() {
	final List<Map<String, Object>> result = new ArrayList<>();
	process((properties, map) -> result.add(getFlattenedMap(map)));
	return result;
}

YamlProcessor.java

private void buildFlattenedMap(Map<String, Object> result, Map<String, Object> source, @Nullable String path) {
	source.forEach((key, value) -> {
		if (StringUtils.hasText(path)) {
			if (key.startsWith("[")) {
				key = path + key;
			}
			else {
				key = path + '.' + key;
			}
		}
		if (value instanceof String) {
			result.put(key, value);
		}
		else if (value instanceof Map) {
			// Need a compound key
			@SuppressWarnings("unchecked")
			Map<String, Object> map = (Map<String, Object>) value;
			buildFlattenedMap(result, map, key);
		}
		else if (value instanceof Collection) {
			// Need a compound key
			@SuppressWarnings("unchecked")
			Collection<Object> collection = (Collection<Object>) value;
			if (collection.isEmpty()) {
				result.put(key, "");
			}
			else {
				int count = 0;
				for (Object object : collection) {
					buildFlattenedMap(result, Collections.singletonMap(
							"[" + (count++) + "]", object), key);
				}
			}
		}
		else {
			result.put(key, (value != null ? value : ""));
		}
	});
}

來點廢話,這個加載的調用鏈非常深,六七個類,不少于十幾個方法,有興趣的同學可以研究研究,學習使用的同學請不要過于關注這個,不過讀源碼有助于更好的理解框架,如有不同理解或者文中有誤,歡迎多多指正。

五、小結

1:簡單解釋springboot常用兩種配置文件
2:基于兩種配置文件,分別做實現
3:@Value注解常用方式
4:yml文件加載源碼解讀

看完上述內容,你們對springboot中application.yml的文件配置是怎樣的有進一步的了解嗎?如果還想了解更多知識或者相關內容,請關注億速云行業資訊頻道,感謝大家的支持。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

东莞市| 什邡市| 乐东| 阿巴嘎旗| 瑞安市| 马鞍山市| 泗水县| 桐庐县| 永丰县| 原平市| 大港区| 澳门| 科尔| 驻马店市| 漳州市| 海城市| 太白县| 青川县| 泽州县| 清丰县| 台北市| 白山市| 秦安县| 报价| 樟树市| 禹州市| 会同县| 黄大仙区| 五寨县| 浦东新区| 竹溪县| 安岳县| 龙州县| 安福县| 平湖市| 专栏| 陆良县| 苏尼特左旗| 泽州县| 互助| 本溪市|