✅作者简介:2022年博客新星 第八。热爱国学的Java后端开发者,修心和技术同步精进。
🍎个人主页:Java Fans的博客
🍊个人信条:不迁怒,不贰过。小知识,大智慧。
💞当前专栏:SpringBoot 框架从入门到精通
✨特色专栏:国学周更-心性养成之路
🥭本文内容:一文吃透 SpringBoot (从入门到精通)
文章目录
- Spring Boot是什么
- Spring Boot 的特点
- 1. 独立运行的 Spring 项目
- 2. 内嵌 Servlet 容器
- 3. 提供 starter 简化 Maven 配置
- 4. 提供了大量的自动配置
- 5. 自带应用监控
- 6. 无代码生成和 xml 配置
- 配置开发环境
- 创建 Spring Boot 项目
- Maven 创建Spring Boot 项目
- Spring Initializr 创建SpringBoot项目
- 启动 Spring Boot
- Spring Boot starter入门
- SpringBoot基本设置
- 6.1SpringBoot设置端口号
- 6.2SpringBoot设置项目名
- 6.3SpringBoot配置文件的拆分
- 6.4SpringBoot开启日志
- 6.5SpringBoot实现热部署
- 6.6SpringBoot开启分页查询
- springBoot对象管理
- springBoot整合JSP
- SpringBoot整合MyBatis
- springBoot整合Redis
- Redis 的优势
- Redis安装
- Redis数据类型
- 1.String(字符串)
- 2.Hash(哈希)
- 3.List(列表)
- 4.Set(集合)
- 5.zset(sorted set:有序集合)
- springboot操作Redis
- springboot 配置redis
- RedisTemplate及其相关方法
- 1.RedisTemplate
- 2.Redis5种数据结构操作
- springboot使用Redis实现分布式缓存
- Redis实现主从复制
- Redis集群的构建
- springBoot CORS(跨域资源共享)
- springBoot聚合工程
Spring Boot是什么
众所周知 Spring 应用需要进行大量的配置,各种 XML 配置和注解配置让人眼花缭乱,且极容易出错,因此 Spring 一度被称为“配置地狱”。
为了简化 Spring 应用的搭建和开发过程,Pivotal 团队在 Spring 基础上提供了一套全新的开源的框架,它就是 Spring Boot。
Spring Boot 具有 Spring 一切优秀特性,Spring 能做的事,Spring Boot 都可以做,而且使用更加简单,功能更加丰富,性能更加稳定而健壮。随着近些年来微服务技术的流行,Spring Boot 也成为了时下炙手可热的技术。
Spring Boot 的特点
Spring Boot 具有以下特点:
1. 独立运行的 Spring 项目
Spring Boot 可以以 jar 包的形式独立运行,Spring Boot 项目只需通过命令“ java–jar xx.jar” 即可运行。
2. 内嵌 Servlet 容器
Spring Boot 使用嵌入式的 Servlet 容器(例如 Tomcat、Jetty 或者 Undertow 等),应用无需打成 WAR 包
3. 提供 starter 简化 Maven 配置
Spring Boot 提供了一系列的“starter”项目对象模型(POMS)来简化 Maven 配置。
4. 提供了大量的自动配置
Spring Boot 提供了大量的默认自动配置,来简化项目的开发,开发人员也通过配置文件修改默认配置。
5. 自带应用监控
Spring Boot 可以对正在运行的项目提供监控。
6. 无代码生成和 xml 配置
Spring Boot 不需要任何 xml 配置即可实现 Spring 的所有配置。
配置开发环境
在使用 Spring Boot 进行开发之前,第一件事就是配置好开发环境。工欲善其事,必先利其器,IDE(集成开发环境)的选择相当重要,目前市面上有很多优秀的 IDE 开发工具,例如 IntelliJ IDEA、Spring Tools、Visual Studio Code 和 Eclipse 等等,那么我们该如何选择呢?
这里我们极力推荐大家使用 IntelliJ IDEA,因为相比于与其他 IDE,IntelliJ IDEA 对 Spring Boot 提供了更好的支持。Spring Boot 版本及其环境配置要求如下表
创建 Spring Boot 项目
开发环境配置完成后,接下来,我们就可以通过 Intellij IDEA 创建一个 Spring Boot 项目了。 Intellij IDEA 一般可以通过两种方式创建 Spring Boot 项目:
- 使用 Maven 创建
- 使用 Spring Initializr 创建
Maven 创建Spring Boot 项目
-
在 IntelliJ IDEA 欢迎页面左侧选择 Project ,然后在右侧选择 New Project,如下图
或者在 IntelliJ IDEA 工作区上方的菜单栏中选择 File ,在下拉菜单中中选中 New,然后选择 Project,如下图
- 在左侧的选项中选择 Maven,勾选 Create from archetype 选项,然后在下面选择合适的 Maven Archetype(模型),最后点击下方的 Next 按钮,如下图
注意
:此处我们也可以不勾选 Create from archetype 选项,直接点击下方的 Next 按钮,直接创建一个简单的 Maven 项目
- 如图 7 所示,展开 Artifact Coordinates ,分别输入项目名称(name)、存储位置(Location)、GroupId、ArtifactId 以及 Version 等信息,信息输入完成后,点击 Next 按钮
4.在该页面可以设置 Maven 的主目录和本地仓库信息,除此之外,我们还可以在下面的属性(Properties)列表中,检查和修改项目的信息。配置完成后,点击 Finish 按钮,完成项目的创建
5.返回 IntelliJ IDEA 工作区,会发现 Maven 项目创建完成,其目录结构如图 9 所示。
6.在该 Maven 项目的 pom.xml 中添加以下配置,导入 Spring Boot 相关的依赖
<!--继承springboot的父工程-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.5</version>
</parent>
<!--引入web依赖 spring+springmvc-->
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<!-- 项目打jar包必要插件-->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
- 在 cn.kgc.springboot包下,创建一个名为 HelloWorldApplication 主程序,用来启动 Spring Boot 应用,代码如下
<!--
注解说明: 该注解是组合注解
@SpringBootConfiguration 用来自动配置spring相关环境 spring+springmvc
@EnableAutoConfiguration 开启自动配置 核心注解
@ComponentScan 组件扫描 只能扫描当前包和子包
-->
@SpringBootApplication
public class HelloWorldApplication {
public static void main(String[] args) {
SpringApplication.run(HelloWorldApplication.class, args);
}
}
Spring Initializr 创建SpringBoot项目
IntelliJ IDEA 支持用户使用 Spring 项目创建向导(Spring Initializr )快速地创建一个 Spring Boot 项目,步骤如下
1.在 IntelliJ IDEA 欢迎页面左侧选择 Project ,然后在右侧选择 New Project,如下图
或者在 IntelliJ IDEA 工作区上方的菜单栏中选择 File ,在下拉菜单中选则 New,然后选择 Project,如下图
2.在新建工程界面左侧,选择 Spring Initializr,选择项目的 SDK 为 1.8,选择 starter service URL 为 http://start.spring.io(默认),最后点击下方的 Next 按钮进行下一步
3.IDEA 会连接网络,并根据 starter service URL 查询 Spring Boot 的当前可用版本和组件列表,如下图
在 Spring Initializr Project Settings 中,输入项目的 GroupId、ArtifactId 等内容,注意 Type 为 Maven,packaging 为 jar,Java version 切换为 8(默认为 11),最后点击下方的 Next 按钮,进行下一步
4.在 dependencise 界面中,选择 Spring Boot 的版本及所依赖的 Spring Boot 组件(例如 Spring Boot 的版本为 2.4.5, Spring Boot 组件为 Web),然后点击下方的 Next 按钮
5.根据需要修改项目名称及项目存储位置等信息,最后点击 Finish 按钮,完成 Spring Boot 项目的创建,如下图
6.返回 IDEA 工作区,可以看到 Spring Boot 项目 helloworld 已经创建完成。该项目不但具有完整的目录结构,还有完整的 Maven 配置,并默认生成了一个名为 HelloworldApplication 的主启动程序
此时,几乎所有的准备工作都已经准备就绪,我们可以在没有编写任何代码的情况下,直接将该 Spring Boot 项目运行起来。
启动 Spring Boot
默认情况下,Spring Boot 项目会创建一个名为 ***Application 的主程序启动类 ,该类中使用了一个组合注解 @SpringBootApplication,用来开启 Spring Boot 的自动配置,另外该启动类中包含一个 main() 方法,用来启动该项目。直接运行启动类 HelloworldApplication 中的 main() 方法,便可以启动该项目,结果如下图
注意:Spring Boot 内部集成了 Tomcat,不需要人为手动配置 Tomcat,开发者只需要关注具体的业务逻辑即可。
为了能比较的清楚的看到效果,我们在 cn.kgc.springboot 包下又创建一个 controller 包,并在该包内创建一个名为 HelloController 的 Controller,代码如下
@Controller
public class HelloController {
@ResponseBody
@RequestMapping("/hello")
public String hello() {
return "Hello World!";
}
}
重启 Spring Boot 项目,然后在地址栏访问 “http://localhost:8080/hello”,结果如下图
Spring Boot starter入门
传统的 Spring 项目想要运行,不仅需要导入各种依赖,还要对各种 XML 配置文件进行配置,十分繁琐,但 Spring Boot 项目在创建完成后,即使不编写任何代码,不进行任何配置也能够直接运行,这都要归功于 Spring Boot 的 starter 机制
Spring Boot 将日常企业应用研发中的各种场景都抽取出来,做成一个个的 starter(启动器),starter 中整合了该场景下各种可能用到的依赖,用户只需要在 Maven 中引入 starter 依赖,SpringBoot 就能自动扫描到要加载的信息并启动相应的默认配置。starter 提供了大量的自动配置,让用户摆脱了处理各种依赖和配置的困扰。所有这些 starter 都遵循着约定成俗的默认配置,并允许用户调整这些配置,即遵循“约定大于配置”的原则
并不是所有的 starter 都是由 Spring Boot 官方提供的,也有部分 starter 是第三方技术厂商提供的,例如 druid-spring-boot-starter 和 mybatis-spring-boot-starter 等等。当然也存在个别第三方技术,Spring Boot 官方没提供 starter,第三方技术厂商也没有提供 starter
以 spring-boot-starter-web 为例,它能够为提供 Web 开发场景所需要的几乎所有依赖,因此在使用 Spring Boot 开发 Web 项目时,只需要引入该 Starter 即可,而不需要额外导入 Web 服务器和其他的 Web 依赖
<!--SpringBoot父项目依赖管理-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.13</version>
<relativePath/>
</parent>
<dependencies>
<!--导入 spring-boot-starter-web-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
...
</dependencies>
</project>
您可能会发现一个问题,即在以上 pom.xml 的配置中,引入依赖 spring-boot-starter-web 时,并没有指明其版本(version),但在依赖树中,我们却看到所有的依赖都具有版本信息,那么这些版本信息是在哪里控制的呢?
其实,这些版本信息是由 spring-boot-starter-parent(版本仲裁中心) 统一控制的。
spring-boot-starter-parent
spring-boot-starter-parent 是所有 Spring Boot 项目的父级依赖,它被称为 Spring Boot 的版本仲裁中心,可以对项目内的部分常用依赖进行统一管理。
<!--SpringBoot父项目依赖管理-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.5</version>
</parent>
Spring Boot 项目可以通过继承 spring-boot-starter-parent 来获得一些合理的默认配置,它主要提供了以下特性:
- 默认 JDK 版本(Java 8)
- 默认字符集(UTF-8)
- 依赖管理功能
- 资源过滤
- 默认插件配置
- 识别 application.properties 和 application.yml 类型的配置文件
SpringBoot基本设置
6.1SpringBoot设置端口号
server:
port: 8989 #配置端口
6.2SpringBoot设置项目名
server:
servlet:
context-path: /springboot #配置项目的虚拟路径(根路径) 项目名使用/开头
6.3SpringBoot配置文件的拆分
spring:
profiles:
active: dev #开发环境
6.4SpringBoot开启日志
# 显示sql
logging:
level:
cn.kgc.springboot.mapper: debug #开启日志
6.5SpringBoot实现热部署
在web项目的开放过程中,通常我们每次修改完代码都需要重新启动项目,实现重新部署。但是随着项目越来越庞大,每次启动都是一个费时的事情。所以,热部署是一个非常构建的技术,有了热部署,可以极大提高我们的开发效率
spring-boot-devtools实现热部署
1.引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
2.配置maven插件
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<fork>true</fork> <!-- 如果devtools不生效 请设置该属性 -->
</configuration>
</plugin>
</plugins>
</build>
3.配置application.yml文件
devtools:
restart:
enabled: true #开启热部署
4.修改idea设置
File-Settings-Compiler 勾选 Build Project automatically
5.设置Registry
ctrl + shift + alt + / ,选择Registry,勾选Compiler autoMake allow when app running
6.6SpringBoot开启分页查询
1.引入依赖:
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.2.12</version>
</dependency>
----------------------------------------------
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.2.10</version>
</dependency>
2.配置application.yml文件(可以不配置使用默认)
# pageHelper分页配置
pagehelper:
helper-dialect: mysql #数据库类型
reasonable: true #分页合理化 page<1 查询第一页 page >pageNumber 查询最后一页
support-methods-arguments: true # 支持mapper接口传递参数开启分页
params: count=countSql #用于从对象中根据属性名取值
3.编写控制器,业务层,持久化层进行测试
@Override
public PageInfo<User> getPage(int pageNum, int pageSize) {
PageHelper.startPage(pageNum, pageSize);
List<User> userList = userMapper.selectList();
PageInfo<User> pageInfo = new PageInfo<>(userList);
return pageInfo;
}
springBoot对象管理
-
管理对象
spring中管理对象的方式:
1.使用xml配置文件,在文件中使用bean标签设置对象的管理
<bean id="" class="xxx.xxx.xxx"></bean>
2.使用注解 @Component @Controller @Service @Repository
springboot管理对象的方式:
1.使用配置方式创建对象
springboot支持使用@Configuration注解添加在配置类上,该类作为一个配置类,相当于spring的配置文件,该注解只能使用在类上。在配置类中方法上使用@Bean注解,相当于spring配置文件中的bean标签
@Configuration public class MyConfiguration{ @Bean public User getUser(){ return new User(); } @Bean public Student getStudent(){ return new Student(); } }
2.使用原始的spring注解 @Component @Controller @Service @Repository
-
属性注入
spring 原始的注入方式
1.set方式
2.constructor
3.自动注入
name: tom age: 30 price: 23.5 sex: true birth: 2021/11/28 12:12:12 array: 12,13,15,17 list: 李四,lisi,tom map: "{'aa':30,'bb':'lisi'}" # 注入map使用json格式 取值的个数#{${map}}
对象的注入
object: name: lisi age: 20 birth: 2021/11/24
@Controller @RequestMapping("/inject2") @ConfigurationProperties("object") public class InjectController2 { private String name; private Integer age; private Date birth; public void setName(String name) { this.name = name; } public void setAge(Integer age) { this.age = age; } public void setBirth(Date birth) { this.birth = birth; } @RequestMapping("/inject") @ResponseBody public String inject(){ System.out.println(name); System.out.println(age); System.out.println(birth); return "ok"; } }
注意:添加一下依赖,可以再写yaml文件时提示,消除红色的警告提示。
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency>
springBoot整合JSP
引入依赖
<!-- 标准标签库-->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- 让springboot内置的tomcat具有解析jsp的能力-->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>
配置视图解析器
spring:
mvc:
view:
prefix: /
suffix: .jsp
设置不重启项目 刷新jsp页面
server:
servlet:
jsp:
init-parameters:
development: true # 修改jsp页面无需重新启动项目
集成后无法访问jsp页面解决方案
1.添加插件
<build>
<resources>
<!--注册webapp目录为资源目录-->
<resource>
<directory>src/main/webapp</directory>
<targetPath>META-INF/resources</targetPath>
<includes>
<include>**/*.*</include>
</includes>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
2.设置工作目录
3.插件启动
SpringBoot整合MyBatis
引入依赖
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.3</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.12</version>
</dependency>
编写配置文件
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver
username: root
password: root
url: jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC&characterEncoding=utf-8
mybatis配置
mybatis:
mapper-locations: classpath:mapper/*.xml #设置mapper文件的位置
type-aliases-package: cn.kgc.springboot.entity # 起别名
configuration:
map-underscore-to-camel-case: true #开启驼峰命名
设置dao接口的扫描
1.在入口类上使用注解,完成扫描
@SpringBootApplication
@MapperScan("cn.kgc.springboot.dao") //扫描dao接口所在的包 同时生成代理对象 注入spring容器
public class Springday02Application {
public static void main(String[] args) {
SpringApplication.run(Springday02Application.class, args);
}
}
springBoot整合Redis
Redis 是完全开源的,遵守 BSD 协议,是一个高性能的 key-value 数据库.
Redis 与其他 key - value 缓存产品有以下三个特点:
- Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。
- Redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储。
- Redis支持数据的备份,即master-slave模式的数据备份。
Redis 的优势
- 性能极高 – Redis能读的速度是110000次/s,写的速度是81000次/s
- 丰富的数据类型 – Redis支持二进制案例的 String, List, Hash, Set 及 zset数据类型操作。
- 原子 – Redis的所有操作都是原子性的,意思就是要么成功执行要么失败完全不执行。单个操作是原子性的。多个操作也支持事务,即原子性,通过MULTI和EXEC指令包起来。
- 丰富的特性 – Redis还支持 publish/subscribe, 通知, key 过期等等特性
- Redis 是单线程的,6.0版本开始支持开启多线程。
Redis安装
下载地址: https://github.com/tporadowski/redis/releases。
解压下载后的压缩文件,解压后文件列表如下:
使用cmd窗口打开Redis
redis-server.exe redis.windows.conf #加载配置文件启动
注:启动之后,不要关闭窗口,关闭窗口服务停止!
Centos7环境安装redis
由于 redis 是用 C 语言开发,安装之前必先确认是否安装 gcc 环境(gcc -v),如果没有安装,执行以下命令进行安装
yum install -y gcc
下载并解压安装包
1.wget http://download.redis.io/releases/redis-6.2.5.tar.gz
2.tar -zxvf redis-6.2.5.tar.gz
cd切换到redis解压目录下,执行编译
1.cd redis-6.2.5
2.make
安装并指定安装目录
make install PREFIX=/usr/redis
启动服务
1.前台启动
cd /usr/redis/bin/
./redis-server
2.后台启动
从 redis 的源码目录中复制 redis.conf 到 redis 的安装目录
cp /usr/redis-6.2.5/redis.conf /usr/redis/bin/
修改 redis.conf 文件,把 daemonize no 改为 daemonize yes
后台启动
./redis-server redis.conf
设置开机启动
vi /etc/systemd/system/redis.service
[Unit]
Description=redis-server
After=network.target
[Service]
Type=forking
ExecStart=/usr/redis/bin/redis-server /usr/redis/bin/redis.conf
PrivateTmp=true
[Install]
WantedBy=multi-user.target
注意:ExecStart配置成自己的路径
设置开机启动
[root@localhost bin]# systemctl daemon-reload
[root@localhost bin]# systemctl start redis.service
[root@localhost bin]# systemctl enable redis.service
创建 redis 命令软链接
[root@localhost ~]# ln -s /usr/local/redis/bin/redis-cli /usr/bin/redis
测试 redis
开放外部访问
配置 vi /etc/redis.conf
开启6379端口
firewall-cmd --zone=public --add-port=6379/tcp --permanent
重启防火墙
firewall-cmd --reload
安装Redis数据库客户端
Redis数据库中常见操作指令
库相关指令:
flushdb 清空当前库
flushall 清空所有库
select 1 切换库
key的相关指令
指令 | 作用 | 语法 |
---|---|---|
del | 删除一个或多个key | del keyname |
exists | 判断一个或多个key是否存在,多个key时有一个存在则就会返回1 | exists keyname |
expire | 设置key的生存时间 单位 :秒 | expire keyname seconds |
keys | 查询所有匹配模式的key ?匹配一个字符 *匹配0-n个字符 [] 满足其中的一个 | key * key h?llo |
move | 将key移动到指定的库中 | move keyname db |
pexpire | 设置key的生存时间 单位 :毫秒 设置成功返回1 否则返回0 | pexpire keyname milliseconds |
ttl | 以秒为单位返回key的剩余生存时间,返回-1表示永久存储,-2表示key不存在 | ttl keyname |
randomkey | 从当前数据库中随机的返回一个key | randomkey |
rename | 重命名key,成功返回ok,否则返回错误信息。 | rename key newkey |
type | 返回key所存储的值的类型 | type keyname |
Redis数据类型
1.String(字符串)
- string 是 redis 最基本的类型,你可以理解成与 Memcached 一模一样的类型,一个 key 对应一个 value。
- string 类型是二进制安全的。意思是 redis 的 string 可以包含任何数据。比如jpg图片或者序列化的对象。
- string 类型是 Redis 最基本的数据类型,string 类型的值最大能存储 512MB。
操作指令:
命令 | 描述 |
---|---|
SET | 设置指定 key 的值 |
GET | 获取指定 key 的值。 |
GETRANGE | 返回 key 中字符串值的子字符 |
GETSET | 将给定 key 的值设为 value ,并返回 key 的旧值(old value)。 |
SETEX | 将值 value 关联到 key ,并将 key 的过期时间设为 seconds (以秒为单位)。 |
SETNX | 只有在 key 不存在时设置 key 的值 |
STRLEN | 返回 key 所储存的字符串值的长度。 |
MSET | 同时设置一个或多个 key-value 对。 |
MSETNX | 同时设置一个或多个 key-value 对,当且仅当所有给定 key 都不存在 |
INCR | 将 key 中储存的数字值增一 |
INCRBY | 将 key 所储存的值加上给定的增量值(increment) |
INCRBYFLOAT | 将 key 所储存的值加上给定的浮点增量值(increment) |
DECR | 将 key 中储存的数字值减一。 |
DECRBY | key 所储存的值减去给定的减量值(decrement) |
APPEND | 如果 key 已经存在并且是一个字符串, APPEND 命令将指定的 value 追加到该 key 原来值(value)的末尾 |
2.Hash(哈希)
- Redis hash 是一个键值(key=>value)对集合。
- Redis hash 是一个 string 类型的 field 和 value 的映射表,hash 特别适合用于存储对象。
操作指令:
命令 | 描述 |
---|---|
hset | 设置一个key/value对 |
hget | 获取key对应的value |
hgetall | 获取所有的key/value对 |
hdel | 删除某个key/value对 |
hexists | 判断一个key是否存在 |
hkeys | 获取所有的key |
hvals | 获取所有的value |
hmset | 设置多个key/value |
hmget | 获取多个key的value |
hsetnx | 设置一个不存在的key的值 |
hincrby | 为value的值进行加法运算 |
hincrbyfloat | 为value的值进行加浮点类型值运算 |
3.List(列表)
- Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)。
操作指令
命令 | 描述 |
---|---|
LINDEX | 通过索引获取列表中的元素 lindex lists 0 |
LINSERT key BEFORE|AFTER | 在列表的元素前或者后插入元素 |
LLEN | 获取列表长度 |
LPOP | 移出并获取列表的第一个元素 |
LPUSH | 将一个或多个值插入到列表头部 |
LPUSHX | 将一个值插入到已存在的列表头部 |
LRANGE | 获取列表指定范围内的元素 (0 -1) |
LREM | 移除列表重复元素 |
LSET | 通过索引设置列表元素的值 ,但是索引必须存在,实质是根据索引修改值 |
LTRIM | 对一个列表进行修剪(trim),就是说,让列表只保留指定区间内的元素,不在指定区间之内的元素都将被删除 |
RPOP | 移除列表的最后一个元素,返回值为移除的元素 |
RPOPLPUSH | 移除列表的最后一个元素,并将该元素添加到另一个列表并返回 |
RPUSH | 在列表中添加一个或多个值 |
RPUSHX | 为已存在的列表添加值 |
4.Set(集合)
- Redis 的 Set 是 string 类型的无序集合。
- 集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。
操作指令:
命令 | 描述 |
---|---|
sadd | 为集合添加元素 |
smembers | 显示集合中所有元素 (无序) |
scard | 返回集合中元素的个数 |
spop | 随机返回一个元素,并将这个元素删除 |
smove | 从一个集合向令一个集合中转移元素 |
srem | 从集合中删除一个元素 |
sismember | 判断集合中是否包含这个元素 |
srandmember | 随机返回一个元素 |
sinter | 求交集 |
sunion | 求和集 |
5.zset(sorted set:有序集合)
- Redis zset 和 set 一样也是string类型元素的集合,且不允许重复的成员。
- 不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。
- zset的成员是唯一的,但分数(score)却可以重复。
操作指令:
命令 | 描述 |
---|---|
zadd | 添加一个有序集合元素 |
zcard | 返回集合中元素的个数 |
zrange升序 zrevrange降序 | 返回一个范围内的元素 |
zrangebyscore | 按照分数查找一个范围内的元素 |
zrank | 返回排名 |
zrevrank | 倒叙排名 |
zscore | 显示某个元素的分数 |
zrem | 移除某个元素 |
zincrby | 给某个特定元素加分 |
springboot操作Redis
spring boot data redis中提供了RedisTemplate和StringRedisTemplate,其中StringRedisTemplate是Redistemplate的子类,两个方法基本一致,不同之处主要体现在操作的数据类型不同,RedisTemplate中的两个泛型都是Object,意味着存储的key和value都可以是一个对象,而StringRedisTemplate的两个泛型都是String,意味着StringRedisTemplate的key和value都只能是字符串。
引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
springboot 配置redis
spring:
redis:
# Redis数据库索引(默认为0)
database: 0
# Redis服务器地址
host: 127.0.0.1
# Redis服务器连接端口
port: 6379
# Redis服务器连接密码(默认为空)
password:
# 连接池最大连接数(使用负值表示没有限制)
jedis.pool.max-active: 20
# 连接池最大阻塞等待时间(使用负值表示没有限制)
jedis.pool.max-wait: -1
# 连接池中的最大空闲连接
jedis.pool.max-idle: 10
# 连接池中的最小空闲连接
jedis.pool.min-idle: 0
# 连接超时时间(毫秒)
timeout: 1000
RedisTemplate及其相关方法
1.RedisTemplate
Spring封装了RedisTemplate对象来进行对Redis的各种操作,它支持所有的Redis原生的api。RedisTemplate位于spring-data-redis包下。RedisTemplate提供了redis各种操作、异常处理及序列化,支持发布订阅。
2.Redis5种数据结构操作
- redisTemplate.opsForValue(); //操作字符串
- redisTemplate.opsForHash(); //操作hash
- redisTemplate.opsForList(); //操作list
- redisTemplate.opsForSet(); //操作set
- redisTemplate.opsForZSet(); //操作有序set
或者:
- redistempalate.boundValueOps
- redistempalate.boundSetOps
- redistempalate.boundListOps
- redistempalate.boundHashOps
- redistempalate.boundZSetOps
opsForXXX和boundXXXOps的区别:XXX为value的类型,前者获取一个operator,但是没有指定操作的对象(key),可以在一个连接(事务)内操作多个key以及对应的value;后者获取了一个指定操作对象(key)的operator,在一个连接(事务)内只能操作这个key对应的value。
SpringBootTest 实现Redis数据库增删改查
/**
* 使用RedisTemplate 操作Redis数据的不同数据类型
*/
@SpringBootTest
public class Springbootday03ApplicationTests {
@Autowired
private RedisTemplate<String, String> redisTemplate;
/**
* String 类型数据操作
*/
@Test
public void operateString() {
//添加值
redisTemplate.opsForValue().set("str", "strValue1");
//添加值 判定是否存在 存在则不添加
Boolean aBoolean = redisTemplate.opsForValue().setIfAbsent("str", "strAbsent");
System.out.println("str设置成功:" + aBoolean);
//获取值
String str = redisTemplate.opsForValue().get("str");
System.out.println("str = " + str);
//更新值
redisTemplate.opsForValue().set("str", "strValue2");
str = redisTemplate.opsForValue().get("str");
System.out.println("newStr = " + str);
//删除值
Boolean b = redisTemplate.delete("str");
System.out.println("str删除成功:" + b);
}
/**
* 操作string类型数据 设置过期时间
*/
@Test
public void operateString2() {
redisTemplate.opsForValue().set("str", "strTimeout", 10, TimeUnit.SECONDS);
//判定值是否存在 不存在则设置值 同时设置过期时间
Boolean aBoolean = redisTemplate.opsForValue().setIfAbsent("str2", "strTimeoutAbsent", 20, TimeUnit.SECONDS);
System.out.println("setIfAbsent:" + aBoolean);
}
/**
* 操作hash类型数据
*/
@Test
public void operateHash() {
//添加hash类型数据 key - value
redisTemplate.opsForHash().put("hash", "username", "admin");
//修改hash类型数据
redisTemplate.opsForHash().put("hash", "username", "tom");
redisTemplate.opsForHash().put("hash", "password", "123456");
//添加hash类型数据 key - map
HashMap<String, String> map = new HashMap<>();
map.put("driverName", "com.mysql.jdbc.Driver");
map.put("url", "jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC");
redisTemplate.opsForHash().putAll("hash", map);
//获取hash类型数据 entries
Map<Object, Object> hash = redisTemplate.opsForHash().entries("hash");
hash.forEach((key, value) -> {
System.out.println(key + "::" + value);
});
//获取所有的key
Set<Object> keys = redisTemplate.opsForHash().keys("hash");
for (Object key : keys) {
System.out.println("key:" + key);
}
//获取所有value
List<Object> values = redisTemplate.opsForHash().values("hash");
values.forEach(value -> System.out.println("value:" + value));
//删除hash类型数据 删除一个 返回删除的个数
Long delete = redisTemplate.opsForHash().delete("hash", "username");
System.out.println("delete = " + delete);
//删除hash类型数据 删除多个 返回删除的个数
delete = redisTemplate.opsForHash().delete("hash", "username", "password", "driverName");
System.out.println("delete = " + delete);
//删除hash类型数据 删除所有
Boolean delHash = redisTemplate.delete("hash");
System.out.println("delHah:" + delHash);
}
/**
* 操作List类型 有序 可重复
*/
@Test
public void operateList() {
//左压栈
// redisTemplate.opsForList().leftPush("list", "listValue1");
// redisTemplate.opsForList().leftPush("list", "listValue1");
// redisTemplate.opsForList().leftPush("list", "listValue2");
// redisTemplate.opsForList().leftPush("list", "listValue3");
//右压栈
redisTemplate.opsForList().rightPush("list", "listValue0");
redisTemplate.opsForList().rightPush("list", "listValue2");
redisTemplate.opsForList().rightPush("list", "listValue0");
//左出栈
String list1 = redisTemplate.opsForList().leftPop("list");
System.out.println("leftPop list1 = " + list1);
//右出栈
String list2 = redisTemplate.opsForList().rightPop("list");
System.out.println("rightPop list2 = " + list2);
//获取所有数据
List<String> lists = redisTemplate.opsForList().range("list", 0, redisTemplate.opsForList().size("list") - 1);
lists.forEach(list -> System.out.println(list));
//设置指定位置的数据
redisTemplate.opsForList().set("list", 0, "listValue0");
/**
* 从存储在键中的列表中删除等于值的元素的第一个计数事件。
* count> 0:删除等于从左到右移动的值的第一个元素;
* count< 0:删除等于从右到左移动的值的第一个元素;
* count = 0:删除等于value的所有元素。
*/
Long remove = redisTemplate.opsForList().remove("list", -1, "listValue0");
System.out.println("remove:" + remove);
//删除指定key的list数据
Boolean list = redisTemplate.delete("list");
System.out.println("list集合删除成功:" + list);
}
/**
* 操作Set类型 无序 不可重复
*/
@Test
public void operateSet() {
//设置set值
redisTemplate.opsForSet().add("set", "setValue0");
redisTemplate.opsForSet().add("set", "setValue0");
redisTemplate.opsForSet().add("set", "setValue1");
//判定是否包含
Boolean member = redisTemplate.opsForSet().isMember("set", "setValue0");
System.out.println("isMember:" + member);
//删除set中的值
Long remove = redisTemplate.opsForSet().remove("set", "setValue0");
System.out.println("remove = " + remove);
//获取set类型值
Set<String> set = redisTemplate.opsForSet().members("set");
set.forEach(str -> {
System.out.println("str = " + str);
});
}
/**
* 操作 ZSet 有序 不可重复
*/
@Test
public void operateZSet() {
//存储值
Boolean add = redisTemplate.opsForZSet().add("zset", "zsetValue0", 10);
System.out.println("add = " + add);
System.out.println("add = " + add);
add = redisTemplate.opsForZSet().add("zset", "zsetValue2", 2);
System.out.println("add = " + add);
//获取值
// Boolean zset = redisTemplate.delete("zset");
// System.out.println("delete zset = " + zset);
}
}
Redis工具类的封装
/**
* Redis 工具类
* @author mosin
* date 2021/11/30
* @version 1.0
*/
@Component
public final class RedisUtil {
private RedisUtil(){};
@Autowired
private RedisTemplate<String,String> redisTemplate;
//设置值
public void setValue(String key,String value){
redisTemplate.opsForValue().set(key, value);
}
// 设置值 同时设置有效时间
public void setValue(String key, String value, Long timeOut, TimeUnit timeUnit){
redisTemplate.opsForValue().setIfAbsent(key, value, timeOut, timeUnit);
}
//设置值 没有则设置 有则不设置
public void setNx(String key,String value){
redisTemplate.opsForValue().setIfAbsent(key, value);
}
//设置值 没有则设置 同时设置有效时间 有则不设置
public void setNx(String key,String value,long timeOut,TimeUnit timeUnit){
redisTemplate.opsForValue().setIfAbsent(key, value,timeOut,timeUnit);
}
//删除值
public boolean del(String key){
return redisTemplate.delete(key);
}
//获取值
public String getValue(String key){
return redisTemplate.opsForValue().get(key);
}
}
业务实践(redis存储token,实现非法请求拦截)
1.编写拦截器
@Component
public class AdminInterceptor implements HandlerInterceptor {
@Autowired
private RedisUtil redisUtil;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("拦截器以拦截请求");
//从请求头中获取token 验证用户是否登录
String token = request.getHeader("token");
System.out.println(token);
String tokenValue = redisUtil.getValue(token);
System.out.println("tokenValue = " + tokenValue);
if(tokenValue!=null){ //用户已登录 放行请求
return true;
}else{//重定向到登录页面
response.sendRedirect(request.getContextPath()+"/login.jsp");
return false;
}
}
}
2.配置拦截器
@Configuration
public class LoginConfig implements WebMvcConfigurer {
@Autowired
private AdminInterceptor adminInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
InterceptorRegistration registration = registry.addInterceptor(adminInterceptor);
registration.addPathPatterns("/**");
registration.excludePathPatterns("/user/login","/user/register","/login.jsp");
}
}
3.编写统一返回数据格式类
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class JsonResult<T> {
private Integer code;
private String msg;
private Long count;
private T data;
}
4.编写控制器
@Controller
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@Autowired
private RedisUtil redisUtil;
@ResponseBody
@RequestMapping("/login")
public Object login(User user) throws JsonProcessingException {
User usr = User.builder().id(1).name("admin").password("123456").build();
//获取token 放入redis
String token = UUID.randomUUID().toString().replace("-", "");
//将user 转为json格式放入 redis
ObjectMapper objectMapper = new ObjectMapper();
String s1 = objectMapper.writeValueAsString(usr);
//将 token 和用户信息存入 redis
redisUtil.setValue(token, s1, 2L, TimeUnit.MINUTES);
//将token 存入map集合返回
HashMap<String, String> map = new HashMap<>();
map.put("token", token);
return map;
}
@ResponseBody
@RequestMapping("/register")
public Object register(User user){
HashMap<String, String> map = new HashMap<>();
map.put("msg", "ok");
return map;
}
@ResponseBody
@RequestMapping("/add")
public Object add(User user){
HashMap<String, String> map = new HashMap<>();
map.put("msg", "ok");
return map;
}
}
5.编写业务类和Mapper接口
6.使用postman接口测试工具测试接口
springboot使用Redis实现分布式缓存
1.环境构建
1.1 通过MybatisX工具逆向功能快速初始化一个工程(springboot+mybatis-plus)
1.2 构建controller层测试各模块的功能
1.3 相同的请求没有实现共享数据,需要开启mybatis的二级缓存
1.4 springboot环境下开启mybatis-plus的二级缓存
1.5编写获取spring工厂的工具类
@Component
public class ApplicationContextUtils implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
public static Object getBean(String beanName){
return applicationContext.getBean(beanName);
}
}
1.6编写Redis缓存类
@Slf4j
public class RedisCache implements Cache {
private final String id;
public RedisCache(String id){
this.id = id;
}
// 操作模块的mapper文件的命名空间 唯一标识符
@Override
public String getId() {
log.info("id= {}",id);
return this.id;
}
// 将数据写入redis
@Override
public void putObject(Object key, Object value) {
log.info("===============将查询的数据开始写入缓存===============");
RedisTemplate redisTemplate = getRedisTemplate();
redisTemplate.opsForHash().put(id, key.toString(), value);
log.info("===============将查询的数据写入缓存完毕===============");
}
// 获取缓存中的数据
@Override
public Object getObject(Object key) {
log.info("============开始从缓存中获取数据=============");
RedisTemplate redisTemplate = getRedisTemplate();
log.info("============从缓存中获取数据完毕=============");
return redisTemplate.opsForHash().get(id, key.toString());
}
// 移除缓存中的数据
@Override
public Object removeObject(Object key) {
return null;
}
// 清空缓存
@Override
public void clear() {
log.info("==========清空缓存=============");
RedisTemplate redisTemplate = getRedisTemplate();
redisTemplate.delete(id);
}
// 获取缓存的数量
@Override
public int getSize() {
RedisTemplate redisTemplate = (RedisTemplate) ApplicationContextUtils.getBean("redisTemplate");
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
int size = redisTemplate.opsForHash().size(id).intValue();
return size;
}
private RedisTemplate getRedisTemplate(){
RedisTemplate redisTemplate = (RedisTemplate) ApplicationContextUtils.getBean("redisTemplate");
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
return redisTemplate;
}
}
1.7Redis中有关联关系缓存数据的处理
@CacheNamespaceRef(DeptMapper.class) // 引用有关联关系的命名空间
public interface EmpMapper extends BaseMapper<Emp> {
}
注:以上设置完成后,两个模块会使用相同的key(命名空间)存储数据到缓存中
1.8 Redis中key进行摘要算法
DigestUtils.md5DigestAsHex(key.toString().getBytes()) // 通过该操作可以减少key的长度
Redis实现主从复制
1.准备三台已经安装Redis的虚拟机
2.查看三台虚拟机的ip地址
3.通过远程连接工具FinalShell连接
4.修改从节点配置文件
启动三台服务器上的redis后,输入一下命令查看redis主从配置状态
info replication
修改从节点服务器的配置文件redis.conf
replicaof 主机ip 主机redis接口
masterauth 密码
修改后重启两个从机,在主机和从机分别输入一下命令查看如下:
info replication
验证主从架构
至此主从架构设置完成
Redis集群的构建
以上结构的集群构建可以在一台虚拟机环境中进行模拟,首先创建一台已经安装好Redis数据库的虚拟机
开启虚拟机并在虚拟机的根路径下创建好7000,7001,7002,7003,7004,7005六个文件夹,之后将redis解压目录下的redis.conf配置文件拷贝到以上几个文件夹中,同时按照以下参数完成配置文件的修改
修改配置文件中的参数
-port 7000 .... 每个文件修改成不同的端口号 因为是在一台虚拟机中进行的模拟
-bind 0.0.0.0 或者改成本机的ip地址
-cluster-enable yes 开启集群模式
-cluster-config-file nodes-port.conf 集群节点配置文件,可加端口 nodes-7000.conf
-cluster-node-timeout 5000 集群节点的超时时间
-appendonly yes 开启AOF持久化机制
-appendonly-aof 持久化文件的名字 修改为不一样的名字 可加端口号 appendonly-7000.aof
以上6个文件夹中文件全部修改完毕之后,可以按照以下指令启动全部的redis节点
[root@localhost bin]# ./redis-server /7000/redis.conf
[root@localhost bin]# ./redis-server /7001/redis.conf
[root@localhost bin]# ./redis-server /7002/redis.conf
[root@localhost bin]# ./redis-server /7003/redis.conf
[root@localhost bin]# ./redis-server /7004/redis.conf
[root@localhost bin]# ./redis-server /7005/redis.conf
查看redis服务是否已经全部启动成功
ps aux|grep redis
全部启动成功之后,执行以下指令,将多个节点组合成集群,同时实现主从备份
./redis-cli --cluster create 如果有密码可以添加参数 -a
192.168.253.132:7000
192.168.253.132:7001
192.168.253.132:7002
192.168.253.132:7003
192.168.253.132:7004
192.168.253.132:7005
--cluster-replicas 1 主从节点的配比 1:1
确认集群的主从从节点信息
输入yes,确认主从节点信息后,输出以下信息,表示集群构建成功
使用一下指令登录集群中的任意节点实现数据的操作,查看集群是否可正常工作
./redis-cli -a cyclone -c -h 192.168.220.11 -p 7001 连接
-a 表示连接密码 没有可省略
-c 表示集群方式进行启动
-h ip 地址
-p 表示端口号
如果在springboot项目中连接Redis集群可按照一下方式进行配置
redis:
cluster:
nodes: 192.168.1.1:6379 ,.....
springBoot CORS(跨域资源共享)
CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。它允许浏览器向跨源服务器,发出XMLHttpRequest
请求,从而克服了AJAX只能同源使用的限制。
什么是同源策略?
同源策略是浏览器的一个安全功能,不同源的客户端脚本在没有明确授权的情况下,不能读写对方资源。所以a.com下的js脚本采用ajax读取b.com里面的文件数据是会报错的。
先来说说什么是源
• 源(origin)就是协议、域名和端口号。
若地址里面的协议、域名和端口号均相同则属于同源。
以下是相对于 http:// www.a.com/test/index.html
的同源检测
http://www.a.com/dir/page.html
----成功
http://www.child.a.com/test/index.html
----失败,域名不同
https://www.a.com/test/index.html
----失败,协议不同
http://www.a.com:8080/test/index.html
----失败,端口号不同
哪些操作不受同源限制
1.script
2.link
3.img
4.form
5.a
哪些操作受同源的限制
1.ajax
解决方案:
1.局部解决跨域
- 使用注解@CrossOrigin(局部跨域)
2.全局解决跨域
- 配置类解决跨域(全局跨域)
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import java.util.ArrayList;
import java.util.List;
@Configuration
public class CorsConfig {
private CorsConfiguration buildConfig() {
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.setAllowCredentials(true); //sessionid 多次访问一致
// 允许访问的客户端域名
List<String> allowedOriginPatterns = new ArrayList<>();
allowedOriginPatterns.add("*");
corsConfiguration.setAllowedOriginPatterns(allowedOriginPatterns);
corsConfiguration.addAllowedHeader("*"); // 允许任何头
corsConfiguration.addAllowedMethod("*"); // 允许任何方法(post、get等)
return corsConfiguration;
}
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", buildConfig()); // 对接口配置跨域设置
return new CorsFilter(source);
}
}
方式2:
@Configuration
public class MyWebMvcConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("*")
.allowedHeaders("*");
}
}
springBoot聚合工程
多模块聚合工程:按照MVC的思想,将应用分成三层web、service、mapper/dao这三个主要模块,在实际的开发过程中可能会根据实际的业务将聚合工程分成如下的形式:
- common:通用工具类模块,专门用于项目中使用的一些工具类。
- entity:实体类模块,专门存放实体类对象,例如:DTO、BO、AO、VO等等对象。
- mapper:dao接口模块,专门存放操作数据库的dao接口。
- service:业务逻辑模块,专门进行业务逻辑的处理。
- web:控制器模块,用于页面请求控制模块。
搭建聚合工程步骤如下:
(1)IDEA创建maven工程
通过IDEA创建一个maven的quickstart类型项目,然后删除里面的src目录,保留pom.xml文件即可,如下图所示:
(2)修改pom依赖,修改父工程项目中的pom.xml文件,添加【springboot】依赖。
(3)创建common子模块
在弹出界面中,选择【quickstart】类型的项目,然后下一步,填入子工程信息即可
在子工程中,删除多余的【test】目录和【App】启动类,修改pom文件,删除多余内容,添加父工程依赖
按照以上步骤完成后续子模块的创建,web模块可创建一个webapp工程,形成如下的目录结构
统一依赖管理
通过前面的步骤,我们已经将父工程和子工程都搭建完成了,并且引入了【springboot】父工程依赖。这里,我们为了方便管理每个子工程的依赖,以及其他第三方依赖,我们可以选择在父工程中的【pom】文件中,统一的定义依赖版本。
在子工程【-web】的pom文件中,添加【web】依赖,并且创建【Application】启动类。
创建【Application】启动类。
创建【src/main/resources】目录,新增【application.yml】配置文件
创建【HelloController】测试类
启动项目,打开浏览器,访问测试路径
到这里,SpringBoot聚合项目已经创建好了,并且能够启动访问了。上面几个子工程虽然创建好了,但是每个子工程之间并没有依赖关系,现在我们就将这几个子工程进行依赖关联。
web----->service(---->表示依赖)
service----->mapper,app-common
mapper----->entity
依次给每个子工程添加上面的依赖即可
码文不易,本篇文章就介绍到这里,如果想要学习更多Java系列知识,点击关注博主,博主带你零基础学习Java知识。与此同时,对于日常生活有困扰的朋友,欢迎阅读我的第四栏目:《国学周更—心性养成之路》,学习技术的同时,我们也注重了心性的养成。