[Spring] Spring配置文件

## 1. 配置文件快速上手

我们在前面讲解Tomcat的时候,默认的端口号是8080,如果我们有的程序访问的端口号也是8080的时候,这时候就会发生端口号冲突,所以我们需要通过配置文件来修改程序运行时的端口号 .在项目创建的时候,就帮我们自动创建了一个配置文件.他的后缀是.properties.

我们点开配置文件修改程序的端口号:

ini 复制代码
spring.application.name=demo
server.port=9090

AI写代码
12

运行程序:我们可以发现程序的端口号变成了9090.

这时候我们通过8080端口号访问其中的html页面的时候,就无法访问了.

2. 配置文件的格式

SpringBoot的配置文件有以下三种:

• application.properties

• application.yml

• application.yaml

其中yml格式和yaml格式其实是等同的.yml是yaml的缩写.
需要注意的一点是,配置文件的文件名只能是以上三个,文件名一旦修改,配置文件就会变成无效配置文件.

  • 特殊说明:

    1. 如果properties和yml存在于同一个项目的时候,两个配置都会加载,但是如果配置文件内容有冲突的时候,.properties文件的优先级更高.
    2. 虽然他们可以共存,但是我们在实际的也业务当中,我们一般只使用一个文件来配置,这样可以更好的维护.

3. properties配置文件的说明

properties配置文件是最早期的配置文件格式,也是创建SpringBoot项目默认的配置文件

3.1 properties基本语法

properties是以键值的形式配置 的,单词和单词之间用.分割,就像导包一样.key和value之间是以=连接的.比如:

ini 复制代码
spring.application.name=demo
server.port=9090
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/mycnblog?characterEncoding=utf8&useSSL=false
spring.datasource.name=root
spring.datasource.password=qwe123524

AI写代码
12345

提示\] 配置文件中可以通过在前面加`#`来注释信息. #### [](https://link.juejin.cn?target= "")[](https://link.juejin.cn?target= "")3.2 读取配置文件 如果在项目中,想要读取配置文件中的内容,可以使用`@Value`注解来实现.`@Value`注解在后面的参数中使用`${}`的格式来读取,代码如下: ```kotlin @RestController @RequestMapping("/demo") public class PropertiesController { @Value("${mykey.key}") private String key; @RequestMapping("/key") public String key(){ return key; } } AI写代码java 运行 12345678910 ``` 运行结果: ![在这里插入图片描述](https://oss.xyyzone.com/jishuzhan/article/1996111521315880961/a062e1658e38875a51df0a387be871d9.webp) #### [](https://link.juejin.cn?target= "")[](https://link.juejin.cn?target= "")3.3 properties的缺点 properties配置文件是以key-Value的形式来配置的,但是有的时候,配置文件中的信息有些赘余,比如下面的配置,`spring.datasource`这个内容就是赘余的: ```ini spring.datasource.url=jdbc:mysql://127.0.0.1:3306/mycnblog?characterEncoding=utf8&useSSL=false spring.datasource.name=root spring.datasource.password=qwe123524 AI写代码 123 ``` 要想解决这个问题,我们需要引入yml配置文件的格式了. ### [](https://link.juejin.cn?target= "")[](https://link.juejin.cn?target= "")4.yml配置文件说明 #### [](https://link.juejin.cn?target= "")[](https://link.juejin.cn?target= "")4.1 yml基本语法 yml是树形结构的配置文件,他的基础语法是:`key: value`,需要注意的一点是,*key和value之间的空格不可以省略* . 基础语法如下: ![在这里插入图片描述](https://oss.xyyzone.com/jishuzhan/article/1996111521315880961/2ce99e41fa89a62f8e77a6ca3db889a8.webp) 我们看到,要是yml的键值对中间没有空格的话,key是没有语法高亮的,语法就是错误的. 下面我们就把上面连接数据库的案例改写为yml的格式. ```yaml spring: datasource: url: jdbc:mysql://127.0.0.1:3306/mycnblog?characterEncoding=utf8&useSSL=false name: root password: qwe123524 AI写代码yml 12345 ``` 我们看到,前面我们所说的"赘余"的信息,*在yml下可以合并到一起写了* .**这里行与行之间的缩进一般是两个空格**. #### [](https://link.juejin.cn?target= "")[](https://link.juejin.cn?target= "")4.2 yml使用进阶 ##### [](https://link.juejin.cn?target= "")[](https://link.juejin.cn?target= "")4.2.1 yml配置不同的数据类型及其null ```php # 字符串 string.value: Hello # 布尔值,true或false boolean.value: true boolean.value1: false # 整数 int.value: 10 # 浮点数 float.value: 3.14159 # Null,~代表null null.value: ~ # "" 空字符串 #, 直接后⾯什么都不加就可以了, 但这种⽅式不直观, 更多的表⽰是使⽤引号括起来 empty.value: '' AI写代码yml 1234567891011121314 ``` 这里需要注意的地方只有两点,第一就是*空字符串是一个单引号,第二就是null用一个波浪号来表示*. ##### [](https://link.juejin.cn?target= "")[](https://link.juejin.cn?target= "")4.2.2 yml配置读取 yml读取配置的方法和properties相同,使用`@Value`注解即可,实现代码如下: ```yaml string: hello: bite AI写代码yml 12 ``` ```kotlin @RequestMapping("/demo") @RestController public class YmlController { @Value("${string.hello}") public String hello; @RequestMapping("/hello99") public String hello(){ return this.hello; } } AI写代码java 运行 12345678910 ``` 运行结果: ![在这里插入图片描述](https://oss.xyyzone.com/jishuzhan/article/1996111521315880961/3e6f2ac8aeda54f200bb37effe64721b.webp) ##### [](https://link.juejin.cn?target= "")[](https://link.juejin.cn?target= "")4.2.3 注意事项:value值佳单引号和双引号 字符串默认不用加上单引号或者是双引号,如果加了的话,有的情况下又会表示特殊含义. 比如在yml文件中配置如下信息: ```yaml string: str1: Hello \n Spring Boot. str2: 'Hello \n Spring Boot.' str3: "Hello \n Spring Boot." AI写代码yml 1234 ``` ```kotlin @RestController public class ReadYml { @Value("${string.str1}") private String str1; @Value("${string.str2}") private String str2; @Value("${string.str3}") private String str3; @PostConstruct public String readYml(){ System.out.println(str1); System.out.println(str2); System.out.println(str3); return "yml"; } } AI写代码java 运行 12345678910111213141516 ``` ![在这里插入图片描述](https://oss.xyyzone.com/jishuzhan/article/1996111521315880961/c1093ff4ec62663876bd4eccd59ce8c5.webp) 在这里我们可以看到: 1. 字符串默认不用加上单引号或者双引号 2. 加了单引号之后,*特殊字符会被转义,只表示的是一个普通的字符串,加了双引号之后,特殊字符不会被转义*. > 注意:这里的转义说起来可能会有些拗口,\\n本来表示的是换行,使用单引号发生了转义,也就是说,\\n不再表示换行了,表示的是一个普通的字符串,而加了双引号之后就表示的是特殊字符的本意,没有发生转义. > 我们来说明一下`@PostConstruct`这个注解,这个注解表示的是,在服务启动之后,**这个方法会变为初始化方法** ,这个方法在后端立即就会执行,如果有打印信息的话,会立即打印在后端的控制台上.相比于使用`@RequestMapping`注解,我们就不需要通过浏览器来访问最终结果了,我们只需要在后端的控制台上看最终的结果即可. ##### [](https://link.juejin.cn?target= "")[](https://link.juejin.cn?target= "")4.2.4 配置对象 我们还可以在yml中配置对象.如下配置: ```yaml student: id: 1 name: java age: 20 AI写代码yml 1234 ``` 这个时候我们就不可以用`@Value`来配置对象了,此时就要使用到另一个注解:`@ConfigurationProperties`来读取.具体实现如下: ```less @Component @ConfigurationProperties(prefix = "student") @Data public class Student { public Integer id; public String name; public Integer age; } AI写代码java 运行 12345678 ``` ```typescript @RestController public class StudentController { @Autowired private Student student; @PostConstruct public void readStudent(){ System.out.println(student); } } AI写代码java 运行 123456789 ``` 运行结果: ![在这里插入图片描述](https://oss.xyyzone.com/jishuzhan/article/1996111521315880961/6acbe70dbe2dcc88c21d7c6c907329e6.webp) \[注意事项

  1. 在一个类中给对象中的属性赋值的时候,这个类必须有Set方法 ,所以我们才要在类的头上加上@Data注解,我们下面不引入注解,手动写入Set方法,来验证这种说法的可靠性.
typescript 复制代码
@Component
@ConfigurationProperties(prefix = "student")
public class Student {
    public Integer id;
    public String name;
    public Integer age;

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

    public void setName(String name) {
        this.name = name;
    }

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

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + ''' +
                ", age=" + age +
                '}';
    }
}

AI写代码java
运行
12345678910111213141516171819202122232425262728

运行结果:

  1. 在类的属性中,属性名必须和yml中的字段名是一致的.否则无法对应的上.
4.2.5 配置集合

配置文件还可以配置List集合,(包括数组,Set在内都是如下的方法)如下所示:

markdown 复制代码
dbtypes:
  name:
    - mysql
    - sqlserver
    - db2

AI写代码yml
12345

就是在每一个字符串的前面加上一个横杠,就表示的是列表,和md的语法非常相似.

java 复制代码
import java.util.List;
@Component
@Data
@ConfigurationProperties(prefix = "dbtypes")
public class ListConfig {
    public List<String> name;//对应name字段
}

AI写代码java
运行
1234567
typescript 复制代码
@RestController
public class ReadYml2 {
    @Autowired
    public ListConfig listConfig;
    @PostConstruct
    public void readList(){
        System.out.println(listConfig);
    }
}

AI写代码java
运行
123456789

运行结果:

在配置集合的时候,上述代码实际上也是在配置一个对象,所以仍然使用@ConfigurationProperties注解.

4.2.6 配置map

配置文件也可以配置map,如下所示:

yaml 复制代码
maptypes:
  map:
    k1: v1
    k2: v2
    k3: v3

AI写代码yml
12345
less 复制代码
@Component
@Data
@ConfigurationProperties(prefix = "maptypes")
public class MapConfig {
    //注意字段名的一致性
    public Map<String,String> map;
}

AI写代码java
运行
1234567
kotlin 复制代码
@RestController
public class ReadYml3 {
    @Autowired
    public MapConfig mapConfig;
    @PostConstruct
    public void mapReader(){
        System.out.println(this.mapConfig);
    }
}

AI写代码java
运行
123456789

运行结果:

5. 综合性练习:验证码案例

5.1 接口文档

  • 需求分析

    1. 生成验证码,并返回验证码
    2. 校验验证码是否正确:校验验证码是否正确.
  • 生成验证码:

    • 请求
    javascript 复制代码
    请求url: /captcha/getCaptcha
    请求参数: 无
    
    AI写代码
    12
    • 响应
      验证码内容的图片.浏览器给服务器发送⼀个/captcha/getCaptcha 这样的请求,服务器返回⼀个图片,浏览器显显示在页面上.
  • 校验验证码是否正确

    • 请求
    ini 复制代码
    请求url: /captcha/check
    请求参数: captcha=用户输入的验证码
    
    AI写代码
    12
    • 响应
      true or false,验证成功,返回true,验证失败,返回false.

5.2 Hutool工具介绍

5.3 后端代码

  1. 引入Hutool依赖
xml 复制代码
<dependency>
	<groupId>cn.hutool</groupId>
	<artifactId>hutool-captcha</artifactId>
	<version>5.8.22</version>
</dependency>

AI写代码xml
12345
  1. 写出验证码的配置项与验证码配置项所对应的类.并注入IoC容器.
yaml 复制代码
captcha:
  width: 100
  height: 40
  session:
    key: CAPTCHA_SESSION_KEY
    date: KAPTCHA_SESSION_DATE

AI写代码yml
123456

配置项中对应的分别是验证码的长和宽,还有用于存储验证码和过期时间.

less 复制代码
@Component
@ConfigurationProperties(prefix = "captcha")
@Data
public class CaptchaProperties {
    public Integer width;
    public Integer height;
    public Session session;
    public static class Session{
        public String key;
        public String date;
    }
}

AI写代码java
运行
123456789101112
  1. 调整生成验证码的Controller代码
less 复制代码
@RestController
@RequestMapping("/captcha")
public class CaptchaController {
    @Autowired
    public CaptchaProperties captchaProperties;
    @RequestMapping("/getCaptcha")
    public void getCaptcha(HttpServletResponse response, HttpSession session) throws IOException {//可以通过这个参数拿到响应中的所有信息
        LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(captchaProperties.getWidth(),captchaProperties.getHeight());//创建线条干扰验证码
        //图形验证码写出,可以写出到文件,也可以写出到流
        response.setContentType("image/jpeg");//从响应中获取到类型信息,设置为图片格式
        response.setHeader("Pragma","No-cache");//从响应中获取到Header,把Pragma键值对设置为没有缓存.
        try {
            lineCaptcha.write(response.getOutputStream());
            //把验证码放入session中
            session.setAttribute(captchaProperties.getSession().getKey(),lineCaptcha.getCode());
            //把过期时间放入session中
            session.setAttribute(captchaProperties.getSession().getDate(),System.currentTimeMillis());
            response.getOutputStream().close();//关闭输出流
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

AI写代码java
运行
1234567891011121314151617181920212223

接下来我们来访问网页来观察验证码是否生成成功.

验证码生成成功.

  1. 校验验证码
java 复制代码
    public static final Integer MAX_WAIT_MILLS = 60*1000;
    @RequestMapping("/check")
    public boolean checkCaptcha(HttpSession session,String captcha){
       if (!StringUtils.hasLength(captcha)){//判断验证码是否有长度
           return false;
       }
       String sessionCode = (String) session.getAttribute(captchaProperties.getSession().getKey());
       Long sessionDate = (Long) session.getAttribute(captchaProperties.getSession().getDate());
       if (captcha.equalsIgnoreCase(sessionCode) &&
       System.currentTimeMillis()-sessionDate < MAX_WAIT_MILLS){
           return true;//验证码和用户输入的等同且
       }
       return false;
    }

AI写代码java
运行
1234567891011121314

5.4 前端代码

xml 复制代码
<!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="/captcha/getCaptcha" 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', '/captcha/getCaptcha?dt=' + new Date().getTime()).fadeIn();
    });

    $("#checkCaptcha").click(function () {
      $.ajax({
        url: "/captcha/check",
        type: "post",
        data: { captcha: $("#inputCaptcha").val() },
        success: function (result) {
          if (result) {
            location.href = "success.html";
          } else {
            alert("验证码错误");
            $("#inputCaptcha").val("");
          }
        }
      });
    });

  </script>
</body>

</html>

AI写代码html
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
xml 复制代码
<!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>

AI写代码html
1234567891011

测试运行:

相关推荐
稳住别浪40 分钟前
DRF框架认证底层源码解析——简单易理解!
后端
马卡巴卡42 分钟前
SpringBoot项目使用Redis对用户IP进行接口限流
后端
VX:Fegn08951 小时前
计算机毕业设计|基于springboot + vue酒店预约系统(源码+数据库+文档)
数据库·vue.js·spring boot·后端·课程设计
汤姆yu1 小时前
基于springboot的校园家教信息系统
java·spring boot·后端·校园家教
q***06291 小时前
Spring Boot--@PathVariable、@RequestParam、@RequestBody
java·spring boot·后端
血小溅1 小时前
Springboot项目Docker 多平台构建指南
后端·docker
D***44141 小时前
Spring Boot 多数据源解决方案:dynamic-datasource-spring-boot-starter 的奥秘(上)
java·spring boot·后端
武子康1 小时前
大数据-172 Elasticsearch 索引操作与 IK 分词器落地实战:7.3/8.15 全流程速查
大数据·后端·elasticsearch
疯狂的程序猴1 小时前
iOS 性能检测工具深度解析 多工具协同下的全维度性能检测体系建设
后端