目录
1.配置文件作用
- 集中管理参数:将应用程序运行所需的各种参数集中在一起,方便进行统一管理和维护,避免参数分散在代码各处。
- 灵活定制应用:可以根据不同的环境(如开发、测试、生产等)设置不同的配置,轻松实现应用在不同场景下的定制化运行。
- 提高可维护性:当需要修改参数时,只需在配置文件中进行更改,而无需修改代码,大大降低了维护成本和出错风险。
- 增强可移植性:使得应用在不同的部署环境中更容易适配,通过调整配置来适应新环境的需求。
- 实现动态调整:某些情况下,可以在应用运行过程中动态修改配置文件,从而实时影响应用的行为,无需重新启动应用。
2.配置元素快速入手
Tocmat 默认端⼝号是8080, 所以我们程序访问时的端⼝号也是8080
但是如果8080端⼝号已经被其他进程使⽤了呢? 我们可以通过配置⽂件来修改服务的端口号 SpringBoot 在创建项⽬时, 就已经帮我们创建了配置⽂件
修改application.properties文件
server.port=9090
重新运行程序,观察日志:
显⽰Tomcat启动端⼝号为9090
3.配置文件的格式
Spring Boot 配置文件有以下三种:application.properties、 application.yml、application.yaml
yml 为yaml的简写, 实际开发中出现频率最高 . yaml 和yml的使用方式一样
当应⽤程序启动时, Spring Boot会⾃动从classpath路径找到并加载application.properties和application.yaml或者application.yml文件
application.properties 和 application.yml 区别:
- 书写格式:properties 文件是基于键值对的简单格式,每行一个配置项;yml 文件则是采用层次化、缩进式的结构,更直观清晰地体现配置的层次关系。
- 可读性:一般来说,yml 的可读性相对更好一些,尤其是在配置项较多且有复杂层次结构时
Spring Boot 允许同时使用.
properties和.
yml,一般情况下,如果 .
yml和.
properties中对于相同配置项的内容有冲突,会以 .
properties 中的配置为准。不过这也不是绝对的,具体还可能受到一些特定配置和框架内部处理逻辑的影响。
虽然理论上来讲两者可以共存,但实际的业务中我们通常会采取一种统一的配置文件格式,这样便于维护和降低故障率
4.properties配置文件说明
properties 配置文件是最早期的配置⽂件格式 ,也是创建 SpringBoot 项⽬默认的配置文件
4.1properties基本语法
properties 是以键值对的形式配置的 ,key 和 value 之间是以"="连接的 ,如:
# 配置项⽬端⼝号
server.port=8080
#配置数据库连接信息
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/name?useSSL=false&characterEncoding=utf8
spring.datasource.username=root
spring.datasource.password=root
配置⽂件中使⽤ “ #”来添加注释信息。
4.2读取配置文件
如果在项目中 ,想要主动的读取配置文件中的内容 ,可以使用@Value注解来实现
@Value注解使用" ${}"的格式读取,如下代码所示:
properties配置如下:
mykey.key1 = romised
代码示例:
@RestController
@RequestMapping("/mykey")
public class PropertiesController {
@Value("${mykey.key1}")
private String key;
@RequestMapping("/key")
public String getKey(){
return key;
}
}
最终执行结果:
4.3properties 缺点分析
properties 文件的缺点主要包括以下几点:
- 代码冗余:properties 文件以键值对的形式存储配置信息,当有多个相关的配置项时,可能会导致重复的键前缀,使得文件内容显得冗余。
- 格式限制:properties 文件的格式相对简单,不支持复杂的数据结构和层次化的配置。对于一些复杂的配置需求,可能需要使用其他格式的配置文件。
- 可读性较差:对于大型的配置文件,properties 文件可能会变得难以阅读和理解,尤其是当键和值的含义不明确时。
- 缺乏类型安全:properties 文件中的值都是字符串类型,需要在程序中进行类型转换,这可能会导致类型错误和运行时异常。
- 不适合大型项目:随着项目的增长,配置信息的数量和复杂性也会增加,properties 文件可能会变得难以管理和维护。
5.yml配置文件说明
yml 是 YAML 是缩写 ,它的全称 Yet Another Markup Language 翻译成中文就是“ 另⼀种标记语言
5.1yml基本语法
yml 是树形结构的配置文件 ,它的基础语法是"key: value".
key 和 value 之间使用英文冒号加空格的方式组成 ,空格不可省略
基础语法如下:
第⼀项的配置为正确的 ,key 也是高亮显⽰的. 第⼆项没有空格是错误的使用方式 ,第⼆项的 key 也 没有高亮显示
使用yml 连接数据库:
spring:
datasource:
url: jdbc:mysql://127.0.0.0:3306/dbname?characterEncoding=utf8&useSSL=false
username: root
password: 1111
5.1.1yml配置不同数据类型及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.1.2yml 配置读取
yml 读取配置的方式和 properties 相同 ,使用 @Value 注解即可 ,实现代码如下:
yml配置:
string:
hello: romised!!!
代码示例:
@RestController
@RequestMapping("/mykey")
public class PropertiesController {
@Value("${string.hello}")
private String hello;
@RequestMapping("/hello")
public String getHello(){
return hello;
}
}
运行结果:
5.1.3注意事项:value 值加单双引号
字符串默认不用加上单引号或者双引号 ,如果加英文的单双引号可以表示特殊的含义。 尝试在 application.yml 中配置如下信息:
string:
str1: Hello \n Spring Boot.
str2: 'Hello \n Spring Boot.'
str3: "Hello \n Spring Boot."
以上程序的执行结果如下图所示:
从上述结果可以看出:
字符串默认不⽤加上单引号或者双引号。
单引号会转义特殊字符 ,使其失去特殊功能, 始终是⼀个普通的字符串.
双引号不会转义字符串里面的特殊字符, 特殊字符会表示本身的含义.
5.2配置对象
我们还可以在yml 中配置对象 ,配置如下:
student:
id: 1
name: romised
age: 18
或者使用行内写法(与上⾯的写法作用⼀致):
student: {id: 1,name: romised,age: 18}
这个时候就不能⽤ @Value 来读取配置中的对象了 ,此时要使用另⼀个注解@ConfigurationProperties来读取,具体实现如下
@RestController
public class StudentController {
@Autowired
private Student student;
@RequestMapping("/readStudent")
public String readStudent(){
return student.toString();
}
}
代码运行结果:
5.3配置集合
配置⽂件也可以配置 list 集合 ,在 YML 中,“-”表示列表项的开始。如下所示:
dbtypes:
name:
- mysql
- sqlserver
- db2
集合的读取和对象⼀样 ,也是使用@ConfigurationProperties来读取的 ,具体实现如下
@Component
@ConfigurationProperties("dbtypes")
@Data
public class ListConfig {
private List<String> name;
}
访问集合的实现如下:
@RestController
public class YmlController {
@Autowired
private ListConfig listConfig;
@RequestMapping("/readList")
public String readList(){
return listConfig.toString();
}
}
运行结果:
5.4配置Map
配置文件也可以配置 map ,如下所示:
maptypes:
map:
k1: kk1
k2: kk2
k3: 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 YmlController {
@Autowired
private MapConfig mapConfig;
@RequestMapping("/readMap")
public String readMap(){
return mapConfig.toString();
}
}
代码运行结果:
5.5yml优缺点
优点:
- 语法简洁直观:易于阅读和理解,书写格式较为自然。
- 层次结构清晰:通过缩进明确表示数据的层次关系,一目了然。
- 跨语言支持较好:可以方便地在不同编程语言的项目中使用。
- 配置灵活:能轻松表达复杂的配置结构和关系。
缺点:
- 对格式要求严格:缩进错误可能导致配置错误,不易排查。
- 缺乏一些高级特性:相比一些专门的配置格式,可能在某些特定场景下功能不够强大。
- 在某些复杂配置场景下可能显得不够简洁:当配置项非常多且复杂时,可能会显得有些混乱
6.验证码案例
随着安全性的要求越来越高 ,目前项目中很多都使用了验证码, 验证码的形式也是多种多样, 更复杂的图形验证码和行为验证码已经成为了更流行的趋势.
验证码的实现⽅式很多, ⽹上也有⽐较多的插件或者工具包可以使用, 咱们选择使⽤Google的开源项目 Kaptcha来实现.
6.1Kaptcha 插件介绍
Kaptcha 是Google的⼀个高度可配置的实用验证码生成工具:http://code.google.com/p/kaptcha/
我们选择⼀个直接适配SpringBoot的开源项目https://github.com/oopsguy/kaptcha-spring-boot
1.原理
验证码可以客户端⽣成, 也可以服务器生成. 对于普通的字符验证码, 后端通常分两部分.
⼀是生成验证码内容, 根据验证码内容和干扰项等, 生成图片 , 返回给客户端
⼆是把验证码内容存储起来, 校验时取出来进⾏对⽐ . kaptcha插件选择把验证码存储在Session⾥ .
2.引入依赖
<dependency>
<groupId>com.oopsguy.kaptcha</groupId>
<artifactId>kaptcha-spring-boot-starter</artifactId>
<version>1.0.0-beta-2</version>
</dependency>
3.生成验证码
该插件提供了两种方式来生成验证码
1.通过代码生成:
https://github.com/oopsguy/kaptcha-springboot/blob/master/README_zh-CN.md)
2.仅通过配置文件来生成验证码(推荐)
Kaptcha详细配置
也可以使用kaptcha.items配置多个验证码生成器
kaptcha.items是一个Map,key为验证码生成器名称,value为验证码生成器的配置
kaptcha:
items:
# home captcha
home:
path: /home/captcha
session:
key: HOME_KAPTCHA_SESSION_KEY
date: HOME_KAPTCHA_SESSION_DATE
# admin captcha
admin:
path: /admin/captcha
session:
key: ADMIN_KAPTCHA_SESSION_KEY
date: ADMIN_KAPTCHA_SESSION_DATE
配置说明:
配置后, 可以直接访问 http://XXXX:port/home/captcha即可⽣成验证码
6.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({
url: "/check",
type: "post",
data: {captcha: $("#inputCaptcha").val()},
success: function (result) {
if (result) {
location.href = "success.html";
} else {
alert("验证码错误");
$("#inputCaptcha").val("");
}
}
});
});
</script>
</body>
</html>

6.3实现服务端代码
@RequestMapping("/admin")
@RestController
public class CaptchaController {
//企业标准(建议):
//常量定义: key: 全部大写, 单词之间使用下划线分割 value: 通常是小写, 以下划线分割
private static final String KAPTCHA_SESSION_KEY = "HOME_KAPTCHA_SESSION_KEY";
private static final String KAPTCHA_SESSION_DATE = "HOME_KAPTCHA_SESSION_DATE";
//验证码的有效时间:ms
private static final Long SESSION_TIMEOUT = 60 * 1000L;
//验证成功: true
//验证失败: false
/**
* 1. 从Session中获取到生成的验证码
* 2. 比对前端传递的验证码和Session中存储的是否一样
*/
@RequestMapping("/check")
public Boolean check(String captcha, HttpSession session){
if (!StringUtils.hasLength(captcha)){
return false;
}
//从Session中获取验证码
String saveCaptcha = (String)session.getAttribute(KAPTCHA_SESSION_KEY);
Date saveDate = (Date)session.getAttribute(KAPTCHA_SESSION_DATE);
//比对验证码
if (captcha.equals(saveCaptcha)){
//比对日期
if (saveDate==null || System.currentTimeMillis() - saveDate.getTime()<SESSION_TIMEOUT){
return true;
}
}
return false;
}
}
输入验证码,验证成功