六、 SpringBoot 配置?件
- 本節?標
- 1. 配置?件作?
- 2. 配置?件快速??
- 3. 配置?件的格式
- 4. properties 配置?件說明
- 4.1 properties 基本語法
- 4.2 讀取配置?件
- 4.3 properties 缺點分析
- 5. yml 配置?件說明
- 5.1 yml 基本語法
- 5.2 yml 使?進階
- 5.2.1 yml 配置不同數據類型及 null
- 5.2.1.1 yml 配置讀取
- 5.2.1.2 注意事項:value 值加單雙引號
- 5.2.2 配置對象 @ConfigurationProperties(prefix = "student") ★
- 5.2.3 配置集合@ConfigurationProperties("dbtypes") ★
- 5.2.4 配置Map ★
- maptypes: {map: {k1: kk1,k2: kk2, k3: kk3}}
- 5.3 yml優缺點
- 6. 綜合性練習
- 6.1 驗證碼案例
- 6.1.1 Kaptcha 插件介紹
- 配置后, 可以直接訪問 http://XXXX:port/home/captcha即可?成驗證碼,且自動存儲在session中
- 6.1.2 需求
- 驗證碼前端代碼
- 后端
- 配置文件
- 導包
- 代碼
本節?標
- 學習SpringBoot配置?件的格式以及對應的語法
- 了解兩個配置?件格式的差異
1. 配置?件作?
配置?件主要是為了解決編碼帶來的問題, 把可能會發?改變的信息, 放在?個集中的地?, 當我們啟動某個程序時, 應?程序從配置?件中讀取數據, 并加載運?.
硬編碼是將數據直接嵌?到程序或其他可執?對象的源代碼中, 也就是我們常說的"代碼寫死".
?如?機字體??
如果采?硬編碼的?式, 就直接在程序中指定字體??, 所有的??使?的都是同?個字體??
但是不同的??有不同的偏好, 我們可以把?機字體的??放在配置?件中, 當程序啟動時, 讀取配置, 以??設置的字體??來顯?.
使?配置?件, 可以使程序完成??和應?程序的交互, 或者應?程序與其他應?程序的交互
- SpringBoot配置?件
SpringBoot?持并定義了配置?件的格式, 也在另?個層?達到了規范其他框架集成到SpringBoot的?的.
很多項?或者框架的配置信息也放在配置?件中, ?如:
- 項?的啟動端?
- 數據庫的連接信息(包含??名和密碼的設置)
- 第三?系統的調?密鑰等信息
- ?于發現和定位問題的普通?志和異常?志等
項?的啟動端?
SpringBoot內置了Tomcat服務器, 默認端?號是8080, 但是??電腦上8080端?號有可能就被其他應?程序占?了, 所以SpringBoot需要?持讓???定義端?號數據庫連接信息
為了更?便簡單的訪問數據庫, 出現了?些持久層框架, 其實就是對JDBC進?了更深層次的封裝.讓??通過簡單??代碼就可完成數據庫的訪問. 但是不同的應?程序訪問的數據庫不同, 這些持久層框架就需要?持??可以?定義配置數據庫的連接信息.
2. 配置?件快速??
我們在前?講了Tocmat 默認端?號是8080, 所以我們程序訪問時的端?號也是8080
但是如果8080端?號已經被其他進程使?了呢? 我們可以通過配置?件來修改服務的端?號SpringBoot 在創建項?時, 就已經幫我們創建了配置?件
修改 application.properties ?件
server.port=9090
3. 配置?件的格式
Spring Boot 配置?件有以下三種:
? application.properties
? application.yml
? application.yaml
yml 為yaml的簡寫, 實際開發中出現頻率最?. yaml 和yml 的使??式?樣, 課堂中只講yml?件的使?
當應?程序啟動時, Spring Boot會?動從classpath路徑找到并加載application.properties 和 application.yaml 或者application.yml ?件.
也可以通過spring.config.name指定?件路徑和名稱, 參考 https://docs.spring.io/spring-boot/reference/features/external-config.html#features.external-config.files
- 理論上講 .properties 和 .yml 可以并存在于?個項?中,當 .properties 和 .yml并存時,兩個配置都會加載. 如果配置?件內容有沖突, 則以 .properties 為主, 也就是 .properties 優先級更?.
- 雖然理論上來講 .properties 可以和 .yml 共存,但實際的業務當中,我們通常會采取?種統?的配置?件格式,這樣可以更好的維護(降低故障率)
4. properties 配置?件說明
properties 配置?件是最早期的配置?件格式,也是創建 SpringBoot 項?默認的配置?件
4.1 properties 基本語法
properties 是以鍵值的形式配置的,key 和 value 之間是以"="連接的,如
#配置項目端口號
server.port=8080
#配置數據庫連接信息
spring.datasource.url=idbc:mysql://127.0.0.1:3306/testdb?characterEncoding=utf8&spring.datasource.username=root
spring.datasource.password=root
4.2 讀取配置?件
如果在項?中,想要主動的讀取配置?件中的內容,可以使? @Value 注解來實現。
@Value 注解使?" ${} "的格式讀取,如下代碼所?:
properties 配置如下:
mykey.key1 = bite
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class PropertiesController { @Value("${mykey.key1}")private String key1;@RequestMapping("/key")public string key() {return"讀取到值:"+key1;}
}
最終執?效果:
4.3 properties 缺點分析
properties 配置是以 key-value 的形式配置的,如下圖所?:
從上述配置key看出,properties 配置?件中會有很多的冗余的信息,?如這些:
想要解決這個問題,就可以使? yml 配置?件的格式化
5. yml 配置?件說明
yml 是 YAML 是縮寫,它的全稱 Yet Another Markup Language 翻譯成中?就是“另?種標記語?.我們先來學習yml的語法
5.1 yml 基本語法
yml 是樹形結構的配置?件,它的基礎語法是"key: value".
key 和 value 之間使?英?冒號加空格的?式組成,空格不可省略基礎語法如下:
第?項的配置為正確的,key 也是?亮顯?的. 第?項沒有空格是錯誤的使??式,第?項的 key 也沒有?亮顯?
使? yml 連接數據庫
yml 使??例
spring:
datasource:url: jdbc:mysql://127.0.0.0:3306/dbname?characterEncoding=utf8&usesSL=falseusername:rootpassword:root
5.2 yml 使?進階
5.2.1 yml 配置不同數據類型及 null
# 字符串
string.value: Hello
# 布爾值,true或false
boolean.value: true
boolean.value1: false
# 整數
int.value: 10
# 浮點數
float.value: 3.14159
# Null,~代表null
null.value: ~
# "" 空字符串
#, 直接后?什么都不加就可以了, 但這種?式不直觀, 更多的表?是使?引號括起來
empty.value: ''
5.2.1.1 yml 配置讀取
yml 讀取配置的?式和 properties 相同,使? @Value 注解即可,實現代碼如下:yml配置:
string:hello: bite
@RestController
public class ReadYml {@Value("${string.hello}")private String hello;@Requestapping("/ymlkey")public string key() { return"讀取到值:"+hello;}
}
5.2.1.2 注意事項:value 值加單雙引號
字符串默認不?加上單引號或者雙引號,如果加英?的單雙引號可以表?特殊的含義。
嘗試在 application.yml 中配置如下信息
string:strl: Hello \n Spring Boot.str2: 'Hello in Spring Boot.'str3: "Hello \n Spring Boot."
@RestController
public class ReadYml {@Value("${string.strl}")private String str1;@Value("${string.str2}")private String str2;@Value("${string.str3}")private String str3;@RequestMapping("/yml")public string readYml(){System.out.println(str1);System.out.println(str2); System.out.println(str3);return "yml";}
}
從上述結果可以看出:
? 字符串默認不?加上單引號或者雙引號。
? 單引號會轉義特殊字符,使其失去特殊功能, 始終是?個普通的字符串.
? 雙引號不會轉義字符串??的特殊字符, 特殊字符會表?本?的含義.
此處的轉義理解起來會有些拗?, \n 本意表?的是換?
使?單引號會轉義, 就是說, \n 不再表?換?了, ?是表??個普通的字符串使?雙引號不會轉義, 表? \n 表?的是它本?的含義, 就是換?
5.2.2 配置對象 @ConfigurationProperties(prefix = “student”) ★
我們還可以在 yml 中配置對象,如下配置:
student:id: 1name: Javaage: 18
或者是使??內寫法(與上?的寫法作??致):
student: {id: 1,name: Java,age: 18}
這個時候就不能? @Value 來讀取配置中的對象了,此時要使?另?個注解
@ConfigurationProperties 來讀取,具體實現如下:
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;@ConfigurationProperties(prefix = "student")
@Component
@Data
public class Student {private int id;private String name;private int age;
}
@RestController
public class StudentController {@Autowiredprivate Student student;@RequestMapping("/readStudent")public String readStudent(){return student.toString();}
}
5.2.3 配置集合@ConfigurationProperties(“dbtypes”) ★
配置?件也可以配置 list 集合,如下所?:
dbtypes:name:- mysql- sqlserver- db2
集合的讀取和對象?樣,也是使? @ConfigurationProperties 來讀取的,具體實現如下:
@Component
@ConfigurationProperties("dbtypes")
@Data
public class ListConfig {private List<String> name;
}
訪問集合的實現如下
@RestController
public class ReadYml2 {@Autowiredprivate ListConfig listconfig;@RequestMapping("/readList")public String readList(){return listConfig.toString();}
}
5.2.4 配置Map ★
maptypes: {map: {k1: kk1,k2: kk2, k3: kk3}}
配置?件也可以配置 map,如下所?:
maptypes:map:k1: kk1k2: kk2k3: kk3
或者是使??內寫法(與上?的寫法作??致):
maptypes: {map: {k1: kk1,k2: kk2, k3: kk3}}
Map的讀取和對象?樣,也是使? @ConfigurationProperties 來讀取的,具體實現如下
@Component
@ConfigurationProperties("maptypes")
@Data
public class MapConfig {private HashMap<String,String> map;
}
打印類的實現如下
@RestController
public class ReadYml2 {@Autowiredprivate MapConfig mapConfig;@RequestMapping("/readMap")public String readStudent(){return mapConfig.toString();}
}
5.3 yml優缺點
優點:
- 可讀性?,寫法簡單, 易于理解
- ?持更多的數據類型, 可以簡單表達對象, 數組, List,Map等數據形態.
- ?持更多的編程語?, 不?是Java中可以使?, 在Golang, Python, Ruby, JavaScript中也可以使?
缺點:
- 不適合寫復雜的配置?件
- 對格式有較強的要求(?個空格可能會引起?場?案
6. 綜合性練習
6.1 驗證碼案例
隨著安全性的要求越來越?, ?前項?中很多都使?了驗證碼, 驗證碼的形式也是多種多樣, 更復雜的圖形驗證碼和?為驗證碼已經成為了更流?的趨勢.
驗證碼的實現?式很多, ?上也有?較多的插件或者?具包可以使?, 咱們選擇使?Google的開源項?Kaptcha來實現.
6.1.1 Kaptcha 插件介紹
Kaptcha 是Google的?個?度可配置的實?驗證碼?成?具. 代碼:
http://code.google.com/p/kaptcha/
?上有很多?甚?公司基于Google的kaptcha進?了?次開發. 我們選擇?個直接適配SpringBoot的開源項?
https://github.com/oopsguy/kaptcha-spring-boot
由于作者的?檔寫的不是很全, 下?簡單介紹下插件的使?
-
原理
驗證碼可以客?端?成, 也可以服務器?成. 對于普通的字符驗證碼, 后端通常分兩部分.
?是?成驗證碼內容, 根據驗證碼內容和?擾項等, ?成圖?, 返回給客?端
?是把驗證碼內容存儲起來, 校驗時取出來進?對?.kaptcha插件選擇把驗證碼存儲在Session?. -
引?依賴
-
?成驗證碼
該插件提供了兩種?式?成驗證碼
? 通過代碼來生成(參考文檔: https://github.com/oopsguy/kaptcha-spring-
boot/blob/master/README zh-CN.md,不再介紹)
? 僅通過配置?件來?成驗證碼(推薦)
kaptcha:text-producer:character:length: 4font:color: blueitems:# admin captchaadmin:path: /admin/captchasession:key: KAPTCHA_SESSION_KEYdate: KAPTCHA_SESSION_DATE
配置后, 可以直接訪問 http://XXXX:port/home/captcha即可?成驗證碼,且自動存儲在session中
6.1.2 需求
界?如下圖所?
- ???成驗證碼
- 輸?驗證碼, 點擊提交, 驗證??輸?驗證碼是否正確, 正確則進???跳轉
驗證碼前端代碼
<!DOCTYPE html>
<html lang="en"><head><meta charset="utf-8"><title>驗證碼</title><style>#inputCaptcha {height: 30px;vertical-align: middle; }#verificationCodeImg{vertical-align: middle; }#checkCaptcha{height: 40px;width: 100px;}</style>
</head><body><h1>輸入驗證碼</h1><div id="confirm"><input type="text" name="inputCaptcha" id="inputCaptcha"><img id="verificationCodeImg" src="/admin/captcha" style="cursor: pointer;" title="看不清?換一張" /><input type="button" value="提交" id="checkCaptcha"></div><script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.4/jquery.min.js"></script><script>$("#verificationCodeImg").click(function(){$(this).hide().attr('src', '/admin/captcha?dt=' + new Date().getTime()).fadeIn();});$("#checkCaptcha").click(function () {$.ajax({type:"get",url: "/admin/check",data:{inputCaptcha: $("#inputCaptcha").val()},success:function(result){if(result){//頁面跳轉location.href = "success.html";}else{alert("驗證碼失敗");}}});});</script>
</body></html>
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>驗證成功頁</title>
</head>
<body><h1>驗證成功</h1>
</body>
</html>
后端
配置文件
kaptcha:text-producer:character:length: 4font:color: blueitems:# admin captchaadmin:path: /admin/captchasession:key: KAPTCHA_SESSION_KEYdate: KAPTCHA_SESSION_DATE
導包
<dependency><groupId>com.oopsguy.kaptcha</groupId><artifactId>kaptcha-spring-boot-starter</artifactId><version>1.0.0-beta-2</version></dependency>
代碼
package com.bite.captcha;import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import javax.servlet.http.HttpSession;
import java.util.Date;@RequestMapping("/admin")
@RestController
public class KaptchaController {private static final String KAPTCHA_SESSION_KEY = "KAPTCHA_SESSION_KEY";private static final String KAPTCHA_SESSION_DATE = "KAPTCHA_SESSION_DATE";private static final long TIME_OUT = 60*1000;//一分鐘, 毫秒數/*** 校驗驗證碼是否正確* @param inputCaptcha 用戶輸入的驗證碼* @return*/@RequestMapping("/check")public boolean check(String inputCaptcha, HttpSession session){//1. 判斷輸入的驗證碼是否為空//2. 獲取生成的驗證碼//3. 比對 生成的驗證碼和輸入的驗證碼是否一致//4. 確認驗證碼是否過期if (!StringUtils.hasLength(inputCaptcha)){return false;}//生成的驗證碼(正確的驗證碼)String saveCaptcha = (String)session.getAttribute(KAPTCHA_SESSION_KEY);Date savaCaptchaDate = (Date)session.getAttribute(KAPTCHA_SESSION_DATE);if (inputCaptcha.equalsIgnoreCase(saveCaptcha)){//不區分大小寫if (savaCaptchaDate!=null || System.currentTimeMillis()-savaCaptchaDate.getTime()<TIME_OUT){return true;}}return false;}
}