文章目录
- 一、关于配置文件
-
- [1.1 配置文件有哪些](#1.1 配置文件有哪些)
- [1.2 配置文件的重要性 --- 解决硬编码](#1.2 配置文件的重要性 --- 解决硬编码)
- 二、配置文件格式
-
- [2.1 通用知识](#2.1 通用知识)
- [2.2 properties配置文件说明](#2.2 properties配置文件说明)
- [2.3 yml配置文件说明](#2.3 yml配置文件说明)
- 三、示例
-
- [3.1 关于类型的匹配](#3.1 关于类型的匹配)
- [3.2 配置对象](#3.2 配置对象)
- [3.3 修改端口号](#3.3 修改端口号)
- [3.4 使用自定义配置](#3.4 使用自定义配置)
- [3.5 配置广告条](#3.5 配置广告条)
- [3.6 验证码案例](#3.6 验证码案例)
一、关于配置文件
1.1 配置文件有哪些
- Spring的配置文件 :Spring给我们提供了一些默认配置(约定),可以让我们实现零配置。但也允许我们去修改 ---- >写在配置文件里
- pom.xml:也是一个配置文件。使我们可以通过 < dependency> ,让Maven帮我们去下载Jar包
- file --->settings:也对应着配置文件,只是给我们提供了图形化界面而已
- C盘中.开头的文件 :C盘中用户文件夹里,放的大多都是一些配置文件或缓存文件
- . 开头的很多都是配置文件
1.2 配置文件的重要性 --- 解决硬编码
- 配置文件最重要的目的就是 解决硬编码的问题
- 硬编码:直接往代码中嵌入数据,写死了,无法在不修改源代码的情况下进行更改
- 比如如果我们把数据库的账号和密码直接写在代码中,如果本地上装的mysql和在Linux上装的mysql账号密码不同,这时候就需要修改代码,再部署到Linux服务器上。但如果部署出错了,此时就需要再次修改代码,然后再上传,十分繁琐
- 编译问题:硬编码问题,是需要我们多次编译的,虽然我们目前修改配置文件的方式,也需要重启服务,编译让其生效。那是因为我们使用的技术并没有很先进,如果我们搭配了先进的框架,这些配置文件是可以做到立即生效的(热加载)。
- 热加载:写的代码立即被加载进来且生效
- 热部署:如果代码发生了变化,会重新部署
- 硬编码:直接往代码中嵌入数据,写死了,无法在不修改源代码的情况下进行更改
- 让我们自己进行配置:配置文件相当于提供了一个入口,让我们去配置,服务器会从这个入口读配置内容
- 什么样的数据适合放在配置文件中?:数据可能会改变且与程序的运行并没有什么关系
二、配置文件格式
2.1 通用知识
- 如何配置:配置就是让配置项按照格式的要求去写
- 配置是两方面的:一方面是我去设置了,另一方面是对方支持我配置的内容
- SpringBoot配置文件的常见三种格式 :可以理解为下面这三种都是语言,是通用的,Python、Go也可能在用
- properties:
- yaml:
- yml:是yaml的简写,和yaml一模一样,只是名字不同
- Spring Boot的配置文件:Spring项目在启动时,会去寻找这个文件,并加载里面的内容,然后再去进行Bean的创建(初始化操作)
- SpringBoot只支持3个文件 :更改了文件名后无法生效(因为Spring Boot默认的配置文件就是application开头的)
- application.properties:
- application.yaml:
- application.yml:
- 修改Spring Boot默认的配置文件 :Spring Boot默认的配置文件就是application开头的,我们可以去修改,但往往不去改,多此一举
- 方法:启动Spring Boot时指定配置文件
- Spring Boot如何启动:运行一个Java程序
- 在IDEA中:点击运行就行,实际上是运行了main方法
- 不在IDEA中:首先打一个Jar包,然后去运行我们这个Jar包
- Jar包 VS war包:里面都是出来的class文件,通常我们会认为war包是一个web程序,不用特别纠结用哪个
- 运行Jar包:把该包拖到 Linux服务器 上,通过java -jar XXX.jar 直接启动
- 如果存在多个配置文件怎么办? :properties的优先级更高
- 对优先级的理解:不是说其他的不生效了,配置文件都生效,只是如果两个文件中都包含同一个配置,是以properties为主的
- 开发时的使用:配置文件是可以替代的。企业开发中,我们通常只使用一个文件就可以完成配置了。而且如果用多个配置文件,一个配置项还要去多个文件中找,十分繁琐
2.2 properties配置文件说明
- 格式规范 :
- key - value的形式,以 = 分割,后面加不加空格无所谓
- key的格式建议是小写,单词之间使用.分割
java
# 配置项⽬端⼝号
server.port=8080
#配置数据库连接信息
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/testdb?characterEncoding=utf8&
//中间的空行可以随便加
spring.datasource.username=root
spring.datasource.password=root
- 缺点分析 :
- 有很多重复的部分,代码繁琐
- 可读性差,当配置项很多时,看不出来配置项之间的关系
2.3 yml配置文件说明
- 非常注意格式,格式问题会导致bug
- 格式 :
- key之间使用 【冒号 + 换行】分割
- 空格的含义:每一行的空格代表的是"层次关系"
- IDEA中 tab 与 空格 的关系:有些版本的IDEA默认把tab对标到空格上,我们在IDEA上可以用tab,但是实际上是要用空格的。
- key和Value之间使用【冒号】赋值,Value前面的冒号后面一定要加空格
- key之间使用 【冒号 + 换行】分割
- yml 中一些特殊的表示 :
- 用【~】表示 null:key: ~
- 用【】、【''】、【""】表示 空字符串:key: 、key: ''、key: ""
- 因为使用【】不太易读,所以我们会用单双引号的方式,提高可读性
- 一般情况下,一个普通的字符串不需要加引号,但如果是空字符串的情况下,为了可读性,建议加上单双引号
- yml层次问题:yml文件的层次并不是两个空格,两个空格只是企业的规范。我们可以用任意空格表示层次,只要表示了即可。
- 不能重复 :
- yml优缺点 :
- 优点
- 带有换行,可读性高,写法简单,易于理解
- 支持更多的数据类型,可以简单表达对象,数组,List,Map等数据形态
- 支持更多的编程语言, 不止是Java中可以使用,在Golang, Python, Ruby, JavaScript中也可以使用。一个大项目,往往是由多个语言写出来的。
- 缺点
- 格式复杂,内容少的时候,就适合用了
- 优点
三、示例
注意配置文件是可以替代的,不用管是properties还是yml
3.1 关于类型的匹配
- 关于自动匹配 :Spring会帮我们把配置文件中的值自动转换成接收的类型,并赋值
- 保证能转:注意,此处只是帮我们自动转,但也是需要我们保证【能转】的。比如布尔类型就无法转为int类型
- Spring MVC类似:Spring MVC中参数的接收也是如此,Spring会帮我们自动转换类型 + 赋值
- 单引号 VS 双引号 :单引号会对特殊字符进行转义,双引号不会进行转义。下面的例子是如果出现了【\n】
- 单引号:使用单引号时,内容是\n,而不是换行
- 双引号:使用双引号时,\n变成了换行,也就是\n本来的含义
java
String:
str1: This is \n str1
str2: 'This is \n str2'
str3: "This is \n str3"
java
@RestController
public class YmlController {
@Value("${String.str1}")
private String str1;
@Value("${String.str2}")
private String str2;
@Value("${String.str3}")
private String str3;
@PostConstruct
public void init(){
System.out.println(str1);
System.out.println(str2);
System.out.println(str3);
}
}
- 为什么日志要从下往上看:下面出现的问题,会引发上方的问题,层层递进
3.2 配置对象
在yml中配置对象
- 方式 :一个变量一个变量地去读
- @Value注解:使用@Value,一个变量一个变量地去读
- @ConfigurationProperties:把配置文件中的数据作为一个对象读取,并且一一对应赋值
- prefix:前缀,表示在yml文件中你配置的这个对象的前缀是什么
- 接收配置文件中设置的值
java
@Component
@ConfigurationProperties(prefix = "student")
@Data
public class Student {
private Integer id;
private String name;
private Integer age;
}
- 配置文件:
java
student:
id: 18
name: zhangsan
age: 12
- 使用:
java
@RestController
public class YmlController {
@Autowired
private Student student;
@PostConstruct
public void init(){
System.out.println(student);
}
}
在yml中配置集合/数组
- 配置文件:并列的关系,要加【-】,且后面要加空格,如果没加会直接当成一整个字符串赋值过去
java
person:
name:
- zhangsan
- lisi
- wangwu
- 接收配置文件中设置的值
- 两种接受方式:
- 列表:private List name
- 数组:private String[] name;
- 两种接受方式:
java
@Data
@Component
@ConfigurationProperties(prefix = "person")
public class Person {
private List<String> name;
// private String[] name; 还可以使用数组去接受
}
- 使用:
java
@RestController
public class YmlController {
@Autowired
private Person person;
@PostConstruct
public void init(){
System.out.println(person.getName().toString());
}
}
yml配置Map
- 配置文件:
java
person:
name:
- zhangsan
- lisi
- wangwu
map:
k1: a
k2: b
k3: c
- 接收配置文件中设置的值:
java
@Data
@Component
@ConfigurationProperties(prefix = "person")
public class Person {
private String[] name;
private HashMap<String, String> map;
}
- 使用:
java
@RestController
public class YmlController {
@Autowired
private Person person;
@PostConstruct
public void init(){
System.out.println(person.getName().toString());
System.out.println(person.getMap().toString());
}
}
3.3 修改端口号
- 关于配置项的查询:去官方文档上查阅
- server.port :修改Spring内置的Tomcat的端口号
- 关于端口号:
- 范围0~65535
- 前0 ~1024的端口大多已经被一些知名的服务器占用了,不推荐使用
- 注意数据库默认端口号是3306,也别去占用
- 关于端口号:
java
server.port=9090 //server.port是Spring给我们提供的一个配置文件的配置项
3.4 使用自定义配置
- 使用原理:配置项原本就是由程序员自定义的,像Spring Boot的配置项就是由他们的开发人员自定义然后提供给我们,然后我们都这么用。也因此,我们也可以自定义配置项,然后使用。
- 代码解析 :
- 原理:@Value注解读取到【demo.key1】中的内容后,Value数据会自动匹配成String类,然后被赋值给key1
- @Value:可以帮我们去读取配置文件中的内容
- 配置项中的value值:不需要加单双引号,被读取后是可以根据接收的类型自动匹配的,所以哪怕配置项是数字我们也可以直接写
- $符号:可以理解为【去从里面的这个变量取到值】
- 如果不加,此时就变成了把【demo.key1】变成一个字符串然后赋值给key1,即我们获取到的结果不是helloXXX,而是demo.key1
- properties格式下:
java
//配置文件代码
demo.key1 = hello, properties
java
@RestController
public class propertiesController {
@Value("${demo.key1}")
private String key1;
@RequestMapping("/readkey")
public String readKey(){
return key1;
}
}
- yml 格式下 :
- @PostConstruct注解:表示初始化
- Spring会帮我们创建完类和对象后,且他还没有对外提供服务时,执行这个初始化方法
- @PostConstruct注解:表示初始化
java
spring:
datasource:
url: jdbc:mysql://127.0.0.0:3306/dbname?characterEncoding=utf8&useSSL=false
username: root
password: 123456
banner:
location: banner.txt
//中间可以随便加空行
demo:
key1: hello, poerties
key2: hello, yml
key3: 10
java
@RestController
public class YmlController {
@Value("${demo.key2}")
private String key2;
@PostConstruct
public void init(){
System.out.println(key2);
}
}
3.5 配置广告条
3.6 验证码案例
- 实现方式 :kaptcha插件
- 我们可以自己去实现,但那比较复杂,直接用插件即可
- 验证码前后端都可以去实现,此处我们是用后端kaptcha插件实现
- 要注意Spring Boot的版本问题,如果Spring Boot版本太高,是无法使用的
- 引入依赖 :我们把Jar包引进来后,虽然它们不在我们自己写的代码中,但是已经包含在项目里了,是可以直接使用的
- 使用Edit Startern,由Spring帮我们管理依赖:这里只是提供了一些常见的框架的依赖,小众的还是需要自己添加的
- 手动添加
xml
<dependency>
<groupId>com.oopsguy.kaptcha</groupId>
<artifactId>kaptcha-spring-boot-starter</artifactId>
<version>1.0.0-beta-2</version>
</dependency>
- 进行配置项的设置 :
- 此处生成的验证码被放在了session中
- 此处生成的验证码被放在了session中
- 查看生成的验证码
此时用Get方法以【/home/captcha】和【/admin/captcha】路径可以访问Kacptcha生成的验证码,刷新会生成新的 - 前端代码 :
- img里的src:本机地址(分相对和绝对)、网络地址(打开图片 + 复制图片地址)、后端地址
java
$("#checkCaptcha").click(function () {
$.ajax({
type: "get",
url: "/admin/check",
data:{
captcha: $("#inputCaptcha").val()
},
success: function (result){
if (result){
location.href = "success.html";
}else{
alert("验证码错误")
}
}
});
});
- 后端代码 :
- 为什么要定义常量:提高代码的可读性(value太长影响阅读) + 解耦合
- 常量的定义:只是企业开发的建议
- 【key】全部大写,单词之间使用下划线分割
- 【value】通常是小写,以下划线分割(下面示例中其实并不规范)
- 定义时间:使用Long类型接收 + 用表达式去写。60表示的是60s,1000L表示的是1000毫秒
- 查看Session中的值:
java
@RestController
@RequestMapping("/admin")
public class CaptchaController {
private static final String KAPTCHA_SESSION_KEY = "ADMIN_KAPTCHA_SESSION_KEY";
//验证码时间
private static final String KAPTCHA_SESSION_DATE = "ADMIN_KAPTCHA_SESSION_DATE";
//有效时间
private static final Long SESSION_TIMEOUT = 60 * 1000L;
@RequestMapping("/check")
public Boolean check(String captcha, HttpSession session){
if (!StringUtils.hasLength(captcha)){
return false;
}
String savaCaptcha = (String)session.getAttribute(KAPTCHA_SESSION_KEY);
Date saveDate = (Date) session.getAttribute(KAPTCHA_SESSION_DATE);
if (captcha.equals(savaCaptcha)){
if (saveDate==null || System.currentTimeMillis() - saveDate.getTime()<SESSION_TIMEOUT){
return true;
}
}
return false;
}
}