一文吃透 SpringBoot (从入门到精通)

news2024/11/25 20:22:47

在这里插入图片描述

✅作者简介: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 项目

  1. 在 IntelliJ IDEA 欢迎页面左侧选择 Project ,然后在右侧选择 New Project,如下图

    在这里插入图片描述

或者在 IntelliJ IDEA 工作区上方的菜单栏中选择 File ,在下拉菜单中中选中 New,然后选择 Project,如下图

在这里插入图片描述

  1. 在左侧的选项中选择 Maven,勾选 Create from archetype 选项,然后在下面选择合适的 Maven Archetype(模型),最后点击下方的 Next 按钮,如下图

在这里插入图片描述

注意:此处我们也可以不勾选 Create from archetype 选项,直接点击下方的 Next 按钮,直接创建一个简单的 Maven 项目

  1. 如图 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>
  1. 在 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。

img

解压下载后的压缩文件,解压后文件列表如下:

在这里插入图片描述

使用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删除一个或多个keydel keyname
exists判断一个或多个key是否存在,多个key时有一个存在则就会返回1exists keyname
expire设置key的生存时间 单位 :秒expire keyname seconds
keys查询所有匹配模式的key ?匹配一个字符 *匹配0-n个字符 [] 满足其中的一个key * key h?llo
move将key移动到指定的库中move keyname db
pexpire设置key的生存时间 单位 :毫秒 设置成功返回1 否则返回0pexpire keyname milliseconds
ttl以秒为单位返回key的剩余生存时间,返回-1表示永久存储,-2表示key不存在ttl keyname
randomkey从当前数据库中随机的返回一个keyrandomkey
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 中储存的数字值减一。
DECRBYkey 所储存的值减去给定的减量值(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这三个主要模块,在实际的开发过程中可能会根据实际的业务将聚合工程分成如下的形式:

  1. common:通用工具类模块,专门用于项目中使用的一些工具类。
  2. entity:实体类模块,专门存放实体类对象,例如:DTO、BO、AO、VO等等对象。
  3. mapper:dao接口模块,专门存放操作数据库的dao接口。
  4. service:业务逻辑模块,专门进行业务逻辑的处理。
  5. web:控制器模块,用于页面请求控制模块。

搭建聚合工程步骤如下:

(1)IDEA创建maven工程

通过IDEA创建一个maven的quickstart类型项目,然后删除里面的src目录,保留pom.xml文件即可,如下图所示:

在这里插入图片描述

(2)修改pom依赖,修改父工程项目中的pom.xml文件,添加【springboot】依赖。

image-20220523115017174

(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知识。与此同时,对于日常生活有困扰的朋友,欢迎阅读我的第四栏目:《国学周更—心性养成之路》,学习技术的同时,我们也注重了心性的养成。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2187748.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

15分钟学 Python 第35天 :Python 爬虫入门(一)

Day 35 : Python 爬虫简介 1.1 什么是爬虫&#xff1f; 网页爬虫&#xff08;Web Crawler&#xff09;是自动访问互联网并提取所需信息的程序。爬虫的主要功能是模拟用户通过浏览器访问网页的操作&#xff0c;从而实现对网页内容的批量访问与信息提取。它们广泛应用于数据收集…

【IPv6】IPv6地址格式及地址分类(组播、单播、任播)整理

IPv6地址格式 IPv6 地址从 IPv4 地址的 32 bits 扩展到 128 bits&#xff0c;IPv6 地址的表示、书写方式也从 IPv4 的点分十进制&#xff0c;修改16进制的冒号分割 IPv4 点分格式(.) 192.168.11.11 IPv6 冒号分割(:) 2408:8459:3032:0000:0000:0000:0001:a9fd IPv6 的规范…

平面电磁波的电场能量磁场能量密度相等,注意电场能量公式也没有复数形式(和坡印廷类似)

1、电场能量密度和磁场能量密度相等(实数场算的) 下面是电场能量密度和磁场能量密度的公式&#xff0c;注意这可不是坡印廷定理。且电场能量密度没有复数表达式&#xff0c;即不是把E和D换成复数形式就行的。注意&#xff0c;一个矢量可以转化为复数形式&#xff0c;两个矢量做…

6.4 数据处理架构模式和实践

6.4 数据处理架构模式和实践 目录概述需求&#xff1a; 设计思路实现思路分析1.批处理架构2.实时处理架构3.流处理架构4.微服务架构&#xff08;重点&#xff09;5.数据湖架构6.数据仓库架构 参考资料和推荐阅读 Survive by day and develop by night. talk for import biz , s…

Java | Leetcode Java题解之第452题用最少数量的箭引爆气球

题目&#xff1a; 题解&#xff1a; class Solution {public int findMinArrowShots(int[][] points) {if (points.length 0) {return 0;}Arrays.sort(points, new Comparator<int[]>() {public int compare(int[] point1, int[] point2) {if (point1[1] > point2[1…

微软官网列出了 Windows 11 LTSC 2024 中的全部新功能

今天早些时候&#xff0c;微软发布了有关受托管PC的Windows 11 24H2 升级和兼容性的详细信息。 该帖子针对的是负责在各自办公室和组织中处理系统的 IT 系统管理员。与此同时&#xff0c;微软也发布了有关 Windows 11 LTSC 或长期服务渠道的信息。 该公司已于四月早些时候证实…

yolov10+strongsort的目标跟踪实现

此次yolov10deepsort不论是准确率还是稳定性&#xff0c;再次超越了之前的yolodeepsort系列。 yolov10介绍——实时端到端物体检测 YOLOv10 是清华大学研究人员在 UltralyticsPython 清华大学的研究人员在 YOLOv10软件包的基础上&#xff0c;引入了一种新的实时目标检测…

Java 异常一口气讲完!(_ _)。゜zzZ

Java 异常处理 Java面向对象设计 - Java异常处理 异常是在没有定义正常执行路径时在Java程序的执行期间可能出现的条件。 Java通过将执行操作的代码与处理错误的代码分离来处理错误。 当发生异常时&#xff0c;Java会创建一个包含有关异常的所有信息的对象&#xff0c;并将其…

HTML增加文本复制模块(使用户快速复制内容到剪贴板)

增加复制模块主要是为了方便用户快速复制内容到剪贴板&#xff0c;通常在需要提供文本信息可以便捷复制的网页设计或应用程序中常见。以下是为文本内容添加复制按钮的一个简单实现步骤&#xff1a; HTML结构&#xff1a; 在文本旁边添加一个复制按钮&#xff0c;例如 <butto…

蘑菇分类检测数据集 21类蘑菇 8800张 带标注 voc yolo

蘑菇分类检测数据集 21类蘑菇 8800张 带标注 v 蘑菇分类检测数据集 21类蘑菇 8800张 带标注 voc yolo 蘑菇分类检测数据集介绍 数据集名称 蘑菇分类检测数据集 (Mushroom Classification and Detection Dataset) 数据集概述 该数据集专为训练和评估基于YOLO系列目标检测模型…

管理方法(12)-- 采购管理

采购人员不是在为公司讨价还价,而是在为顾客讨价还价,我们应该为顾客争取最低的价钱。-----山姆 沃尔顿 沃尔玛的创始人。 1. 采购的定义和原则 5R原则:适时(Right Time)、适质(Right Quality)、适量(Right Quantity)、适价(Right Price)、适地(Right Place)。…

Linux -- 文件系统(文件在磁盘中的存储)

目录 前言&#xff1a; 了解机械磁盘 初始盘片与磁头 盘片是怎么存数据的呢&#xff1f; 详解盘片 如何访问磁盘中的一个扇区呢&#xff1f; -- CHS 定位法 磁盘的逻辑存储 LBA&#xff08;Logical Block Addressing --- 逻辑块寻址&#xff09; 如何将 LBA 地址转换为…

C++ | Leetcode C++题解之第455题分发饼干

题目&#xff1a; 题解&#xff1a; class Solution { public:int findContentChildren(vector<int>& g, vector<int>& s) {sort(g.begin(), g.end());sort(s.begin(), s.end());int m g.size(), n s.size();int count 0;for (int i 0, j 0; i < …

js中各种时间日期格式之间的转换

前言&#xff1a;近几天在做百度地图时,需要转换时间格式并做显示,下面这篇文章主要给大家介绍了关于js中各种时间格式的转换方法的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下 &#x1f308;&#x1f308;文章目录 先来认识 js 的时间格式有哪些&#xf…

CSS3旋转、平移、缩放、倾斜

CSS3平移、缩放、倾斜、旋转 前言 下面代码用到了盒子如下&#xff1a; 使用 一、平移translate() 语法&#xff1a;translate(x轴平移距离, y轴平移距离) 使用方式如下&#xff1a; /* x轴平移200px&#xff0c;y轴平移100px */ transform: translate(200px, 100px);二、…

JavaWeb——Vue组件库Element(5/6):案例:组件实现(概述、Form表单、Table表格、Pagination 分页、效果展示、完整代码)

目录 概述 Form表单 Table表格 Pagination 分页 效果展示 完整代码 概述 在刚才制作出来的页面当中&#xff0c;上面项目的名称已制作好&#xff0c;左侧的菜单栏也已配置好。 接下来主要处理的是右侧主展示区域当中的组件编写。 在右侧的主展示区域&#xff0c;主要有…

【C++】多肽

目录 一 多肽定义 1. 多肽的构成条件 1 例一 2 例二 2. 虚函数 3. 虚函数重写的两个意外 1 协变 2 析构函数的重写 二 关键字override 和 final 1. final 2.override 三 三重对比 1. 练习 四 多肽的原理 1. 多肽调用和普通调用 2.虚函数表 3. 分析 4. 原理 …

【web安全】——文件包含漏洞

1. 文件包含基础 和SQL注入等攻击方式一样&#xff0c;文件包含漏洞也是一种注入型漏洞&#xff0c;其本质就是输入一段用户能够控制的脚本或者代码&#xff0c;并让服务端执行。 1.1. 文件包含简介 什么叫包含呢&#xff1f;以PHP为例&#xff0c;我们常常把可重复使用的函…

【CKA】十二、持久化存储卷PersistentVolume

12、持久化存储卷PersistentVolume 1. 考题内容&#xff1a; 2. 答题思路&#xff1a; 按题目要求检查各个参数&#xff0c;我就是第一次没看清楚&#xff0c;把ReadWriteOnce写成ReadWriteMany了&#xff0c;幸亏做完检查了一遍 这个参数可有可无&#xff0c;加上也不影响 …

【Go语言】Ergo:构建分布式系统的现代化 Erlang 框架

Ergo 是一个基于 Go 语言的开源框架&#xff0c;专门用于构建分布式系统。它为开发人员提供了与 Erlang/OTP 类似的编程模型和功能。Ergo 通过将 Erlang 的强大分布式并发编程模型带入 Go 语言的生态中&#xff0c;使得开发者能够轻松创建高度可靠、可扩展的分布式应用程序。 …