一.配置文件的作用
计算机上有数以千计的配置文件,绝大部分软件,都离不开配置文件,那么配置文件是有什么作用呢?
配置文件主要是为了解决硬编码带来的问题,把可能会发生改变的信息,集中放在一个地方,当我们启动某个程序的时候,应用程序就从配置文件中读取数据并运行.
SpringBoot配置文件
SpringBoot支持并定义了配置文件的格式,也在另一个层面达到了规范其他框架集成到SpringBoot的目的.
很多项目或者框架的配置信息也放在了配置文件中,就比如:项目的启动端口.数据库的连接信息.第三方系统的调用秘钥信息等等.
二.配置文件快速入手
我们在前面已经提到了Tomcat的默认端口号是8080,所以我们访问程序的时候,端口号也是8080.
这时候,我们可以通过修改配置文件来达到修改Tomcat的端口号.
在我们创建SpringBoot项目的时候,就已经自动创建了配置文件.
application.properties文件就是我们的配置文件.

更改配置文件,将端口号改为9090,重新运行程序


此时我们访问程序就需要到9090端口去访问.
三.配置文件的格式
SpringBoot的配置文件有以下三种格式:
1.application.properties
2.application.yml
3.application.yaml
这其中,yml和yaml的使用方式一模一样,yml是yaml的简写.所以我们只需要学习yml和properties这两种配置文件的使用方法.
特殊说明:
1.理论上来说.yml和.properties文件可以并存在一个项目中,但是当.properties和.yml文件并存时,两个配置都会加载,如果配置文件内容有冲突,则以properties为主,也就是说.properties优先级更高.
2.虽然理论上可以共存,但是实际业务中,通常只会采取一种统一的配置文件格式,这样可以更好的维护.
四.配置文件说明
properties配置文件是最早期的配置文件格式,也是创建SpringBoot项目默认的配置文件.
4.1 properties基本语法
properties是以键值对的形式配置的.key和value之间是用"="连接.
java
spring.application.name=IoC
#配置端口号
server.port = 9090
#配置数据库连接信息
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/testdb?
characterEncoding=utf8&useSSL=false
spring.datasource.username=root
spring.datasource.password=root
4.2 读取配置文件
如果在项目中,想要主动读取配置文件中的内容,可以使用@Value注解来实现.
比如我们现在配置如下:

后端代码:
java
@RestController
public class PropertiesController {
@Value("${ID}")
private String ID;
@Value("${password}")
private Integer password;
@RequestMapping("/getStudent")
public String getStudent(){
return "ID:" + ID + "password:" + password;
}
}
运行程序,就可以直接拿到配置文件中的信息了.

4.3 properties缺点分析
properties配置是以键值对的方式进行配置的,就像我们之前配置数据库信息,会有很多冗余的信息.比如:

要写多次spring.datasource.要解决这个问题,就可以使用yml配置文件.
五.yml配置文件说明
5.1 yml基本语法
yml采用的是树形结构的配置文件,它的基础语法是key: value
key和value之间用英文冒号+空格组成,空格不能省略.

使用yml读取数据库:

5.2 yml使用进阶
5.2.1 yml配置不同数据类型及null
~代表null
""代表空字符串
yml的读取方式跟properties相同,使用@Value注解即可.


运行代码,就可以拿到配置文件中的内容

5.2.2 value值加单双引号
字符串默认不加单双引号,如果加上了单双引号,可以表示特殊含义.
在properties.yml文件中配置下面数据.

用程序读取并打印出来看看结果.
java
@RestController
public class YmlController {
@Value("${string.val1}")
private String val1;
@Value("${string.val2}")
private String val2;
@Value("${string.val3}")
private String val3;
@RequestMapping("/yml")
public void getYml() {
System.out.println(val1);
System.out.println(val2);
System.out.println(val3);
}
}
结果:

通过结果我们可以发现,字符串默认不用加上单双引号,如果加上单引号字符串还是字符串,加上双引号会使\n变成转义字符
5.2.2 配置对象
我们还可以在yml中配置对象.这两种方法是一样的.

这个时候就不能用@Value去读取配置中的对象了,这时候需要用@ConfigurationProperties这个注解来读取.
java
@RestController
public class StudentController {
@Autowired
private Student student;
@RequestMapping("/getstudent")
public Student getStudent() {
return student;
}
}
在Student类上面添加@Component注解,把这个类交给Spring管理,然后再添加@ConfigurationProperties注解,来读取配置文件,其中prefix属性就是告诉Spring从配置文件中读取以student开头的配置项并绑定到这个类上面来.
java
@Component
@ConfigurationProperties(prefix = "student")
@Data
public class Student {
private String name;
private Integer age;
private Integer id;
}
运行程序,得到配置中的信息.

5.2.3 配置集合&配置Map
读取集合跟读取对象是一样的,也是通过@ConfigurationProperties注解实现的.
在yml中添加配置信息

java
@Data
@Component
@ConfigurationProperties(prefix = "dbtypes")
public class ListConfig {
private List<String> name;
}
java
@RestController
public class DbtypeController {
@Autowired
private ListConfig listconfig;
@RequestMapping("/getList")
public void getList(){
System.out.println(listconfig);
}
}
运行代码:

配置Map也是一样的,



运行程序,得到配置中的信息.

5.2.5 yml优缺点
优点:
1.可读性高,写法简单,易于理解.
2.支持更多数据类型,可以简单表达对象,数组,List,Map等数据类型.
3.支持更多编程语言.
缺点:
1.不适合写复杂的配置文件.
2.对格式有较强的要求.
六.综合性练习
随着安全性的要求越来越高,目前有很多项目中都使用了验证码,验证码的形式也是有各种各样的.比如图形验证码,行为验证码.
实现验证码的方式有很多种,前端可以实现,后端也可以实现,网上也有很多插件或者工具包可以实现,这里我们选择用Hutool提供的小工具来实现.
6.1 需求
1.页面生成验证码.
2.输入验证码,点击提交,判断验证码输入是否正确,正确则跳转页面.
6.2 准备工作
创建项目,引入前端代码
输入验证码界面:
html
<!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 () {
alert("验证码校验");
});
</script>
</body>
</html>
验证成功跳转界面:
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>
6.3 约定前后端交互接口
需求分析:
后端需要提供两个服务:
1.生成验证码并返回给前端
2.校验验证码是否正确.
接口定义:
1.生成验证码
请求URL:/captcha/getCaptcha
响应:验证码图片内容
2.校验验证码是否正确.
请求:
URL:/chptcha/check
请求参数:captcha=验证码结果
响应: true/false
6.4 Hutool工具介绍
Hutool官网Hutool🍬一个功能丰富且易用的Java工具库,涵盖了字符串、数字、集合、编码、日期、文件、IO、加密、数据库JDBC、JSON、HTTP客户端等功能。
打开官网,可以在文档中找到有关图形验证码相关API,我们是通过使用这个工具来实现我们的验证码功能

6.5 实现服务器端代码
6.5.1 引入Hutool依赖.
和我们之前使用lombok一样,想要使用Hutool的API,就需要引入依赖.
打开Hutool的官网,可以找到引入依赖的代码.添加到pom文件中.

6.5.2 实现验证码
在Hutool的文档中,有例子,我们可以先粘贴进我们的代码看看效果.

运行这段代码,我们就可以在相对应的文件路径下拿到图片.


但是此时浏览器显示的是文件路径,我们想要的是图片

这时候就需要用流.,用HttpResponse将图片写入到流.
java
public void getCaptcha(HttpServletResponse response) throws IOException {
//定义图形验证码的长和宽
LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(200, 100);
//图形验证码写出,这里用response输出
lineCaptcha.write(response.getOutputStream());
//输出code,这里是在后台打印验证码.
Console.log(lineCaptcha.getCode());
//验证图形验证码的有效性,返回boolean值
System.out.println(lineCaptcha.verify("1234"));;
}
再次运行代码,就可以在浏览器中看到图片.

接下来,我们需要对程序进行调整,先把验证码的相关配置项挪到配置文件中,再吧生成的验证码存在session中,以便于后续验证.
java
captcha:
width: 200
height: 100
session:
#验证码的值
key: CAPTCHA_SESSTION_KEY
#生成验证码的时间
date: CAPTCHA_SESSTION_DATE
再创建一个验证码配置项对应的Java文件.
java
@Data
@Component
@ConfigurationProperties(prefix = "captcha")
public class CaptchaProperties {
private Integer width;
private Integer height;
private Session session;
@Data
public static class Session{
private String key;
private String date;
}
}
再调整Controller代码
java
@RestController
@RequestMapping("/captcha")
public class HutoolCaptchaController {
@Autowired
private CaptchaProperties captchaProperties;
@RequestMapping("/getchptcha")
public void getCaptcha(HttpServletResponse response, HttpSession session) throws IOException {
//定义图形验证码的长和宽
LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(captchaProperties.getWidth(), captchaProperties.getHeight());
//告诉浏览器输出的是图片数据
response.setContentType("image/png");
//禁止缓存,每次图片不一样
response.setHeader("Pragma", "No-cache");
//图形验证码写出,这里用response输出
lineCaptcha.write(response.getOutputStream());
//设置session,用来判断验证码是否正确
session.setAttribute(captchaProperties.getSession().getKey(), lineCaptcha.getCode());
session.setAttribute(captchaProperties.getSession().getDate(), new Date());
//输出code,这里是在后台打印验证码.
Console.log("正确验证码:" + lineCaptcha.getCode());
}
}
6.5.3 校验验证码
在上面,我们已经实现了生成验证码的功能,现在要实现校验验证码的功能.
这个逻辑很简单,定义了一个超时时间,我们先从session中拿到正确的验证码,然后用codex(用户输入的验证码)去判断是否和正确的验证码相同,相同的情况我们再判断是否超时,都满足则验证正确.
java
private final static long VALID_MILLIS_TIME = 5 * 60 * 1000;
@RequestMapping("/check")
public boolean checkCaptcha(String code, HttpSession session) {
//先判断用户输入的验证码是否为空
if (!StringUtils.hasLength(code)) {
return false;
}
//读取session中的验证码和时间
String sessionCode = (String) session.getAttribute(captchaProperties.getSession().getKey());
Date sessionDate = (Date) session.getAttribute(captchaProperties.getSession().getDate());
//拿到验证码先判断验证码是否正确
if(code.equalsIgnoreCase(sessionCode)){
//再判断时间是否超时
if(sessionDate == null || System.currentTimeMillis() - sessionDate.getTime() < VALID_MILLIS_TIME){
return true;
}
return false;
}
return false;
}
6.5.4 调整前端页面
先把图片放到前端页面中.将路径改为后端路径.补充代码,点击提交按钮之后发送请求去后端.

6.6 运行测试
运行程序,输入URL访问

输入错误验证码:

输入正确验证码:

