🚀Spring Boot + Redis:构建高效缓存系统

举报
bug菌 发表于 2024/11/29 10:03:21 2024/11/29
【摘要】 @TOC 前言 🌟在现代应用程序中,性能是至关重要的因素之一。随着用户请求的增加,数据库负载会随之增加,这时缓存就成了提升系统性能的关键解决方案。而在缓存技术中,Redis 作为一个高效的内存数据存储引擎,已经成为了最流行的选择之一。那么,如何将 Redis 集成到 Spring Boot 中,以构建一个高效的缓存系统呢?别急,今天我们就来详细探讨如何在 Spring Boot 中使用 R...

@TOC

前言 🌟

在现代应用程序中,性能是至关重要的因素之一。随着用户请求的增加,数据库负载会随之增加,这时缓存就成了提升系统性能的关键解决方案。而在缓存技术中,Redis 作为一个高效的内存数据存储引擎,已经成为了最流行的选择之一。那么,如何将 Redis 集成到 Spring Boot 中,以构建一个高效的缓存系统呢?别急,今天我们就来详细探讨如何在 Spring Boot 中使用 Redis,实现轻松的数据缓存。

1. 什么是 Redis? 🤔

Redis 是一个开源的内存数据结构存储系统,常用于缓存、消息队列等场景。它支持丰富的数据类型,如字符串、哈希、列表、集合、有序集合等,可以在内存中快速读取和写入数据,这使得 Redis 成为提升系统性能的理想选择。

为什么要使用 Redis 作为缓存?

  • 高效快速:Redis 基于内存操作,读写速度非常快,比传统的数据库要高效得多。
  • 数据持久化:虽然 Redis 是内存数据库,但它支持数据持久化到磁盘,保证了数据不丢失。
  • 丰富的数据类型:Redis 提供了多种数据结构,能够满足各种复杂数据存储需求。
  • 分布式支持:Redis 支持集群模式,适合大规模分布式部署。

2. 在 Spring Boot 中集成 Redis 🔄

Spring Boot 提供了对 Redis 的原生支持,通过 spring-boot-starter-data-redis 启动器,开发者可以非常方便地将 Redis 集成到 Spring Boot 项目中。

步骤 1: 引入依赖 🛠️

首先,在 pom.xml 文件中添加 Redis 相关的依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-redis</artifactId>
</dependency>
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId> <!-- Jedis 是 Redis 的客户端 -->
</dependency>

这里使用 spring-boot-starter-data-redis 来简化 Redis 集成。jedis 是 Redis 官方提供的客户端,Spring Data Redis 支持的常见客户端还有 lettuce,可以根据需求选择使用。

步骤 2: 配置 Redis 连接 📝

接下来,在 application.propertiesapplication.yml 中配置 Redis 连接信息:

# Redis 配置
spring.redis.host=localhost
spring.redis.port=6379
spring.redis.password=yourpassword  # 如果有密码
spring.redis.database=0  # 使用的数据库索引
spring.redis.timeout=2000  # 连接超时时间,单位毫秒

在默认情况下,Redis 使用 6379 端口,并且没有密码。如果你的 Redis 配置了密码或者使用了不同的端口,记得修改这些配置。

步骤 3: 创建 Redis 配置类 🔧

虽然 Spring Boot 会自动配置 Redis,但有时我们需要对 Redis 连接池等进行个性化配置。此时可以创建一个配置类,手动配置 RedisTemplateStringRedisTemplate

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;

@Configuration
public class RedisConfig {

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(factory);
        // 设置默认的序列化方式
        template.setDefaultSerializer(RedisSerializer.json());
        return template;
    }

    @Bean
    public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory factory) {
        return new StringRedisTemplate(factory);
    }
}

在这个配置类中,我们通过 RedisTemplateStringRedisTemplate 分别为 Redis 提供了两种不同的操作模板:

  • RedisTemplate 用于操作 Redis 的各种数据结构,如 ListSetHash 等。
  • StringRedisTemplate 仅用于处理 String 类型的数据,通常用于缓存字符串。

代码解析:

在本次的代码演示中,我将会深入剖析每句代码,详细阐述其背后的设计思想和实现逻辑。通过这样的讲解方式,我希望能够引导同学们逐步构建起对代码的深刻理解。我会先从代码的结构开始,逐步拆解每个模块的功能和作用,并指出关键的代码段,并解释它们是如何协同运行的。通过这样的讲解和实践相结合的方式,我相信每位同学都能够对代码有更深入的理解,并能够早日将其掌握,应用到自己的学习和工作中。

这段代码展示了如何使用 Spring Data Redis 配置 Redis 连接和模板。主要功能是定义了两个 Redis 模板:一个 RedisTemplate<String, Object> 用于处理通用对象类型的数据,另一个 StringRedisTemplate 用于处理 Redis 中的字符串类型数据。

1. RedisConfig 配置类

@Configuration
public class RedisConfig {
    // ...
}
  • @Configuration 注解标记这是一个配置类,Spring 会自动扫描并加载这个类中的 Bean 定义。

2. redisTemplate Bean

@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
    RedisTemplate<String, Object> template = new RedisTemplate<>();
    template.setConnectionFactory(factory);
    // 设置默认的序列化方式
    template.setDefaultSerializer(RedisSerializer.json());
    return template;
}
  • @Bean 注解标记该方法会向 Spring 容器注册一个 Bean,并作为 RedisTemplate 的实例提供给其他组件。
  • RedisTemplate<String, Object>:这是一个通用的 Redis 模板,用于操作 Redis 中的键值对,其中键是 String 类型,值是 Object 类型。该模板用于执行 Redis 的基本操作,如 setgetdelete 等。
  • RedisConnectionFactory:该对象提供了与 Redis 的连接。通过 factory 参数,RedisTemplate 可以连接到 Redis 服务。
  • template.setDefaultSerializer(RedisSerializer.json()):此行代码指定 RedisTemplate 使用 JSON 格式进行序列化和反序列化。RedisSerializer.json() 返回一个将对象序列化为 JSON 格式的序列化器。通过这种方式,所有存入 Redis 中的对象都会被自动转换为 JSON 字符串,而从 Redis 中获取时也会反序列化回对象。

3. stringRedisTemplate Bean

@Bean
public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory factory) {
    return new StringRedisTemplate(factory);
}
  • StringRedisTemplate 是一个简化版的 RedisTemplate,专门用于操作 Redis 中的字符串数据。
  • RedisConnectionFactory 是 Redis 连接的工厂类,它用于创建 Redis 的连接。
  • StringRedisTemplate 仅支持字符串类型的键和值,因此它适用于只需要操作字符串数据的场景,如简单的键值存储。

4. 配置说明

  • RedisTemplateStringRedisTemplate 都依赖于 RedisConnectionFactory,这是 Redis 的连接工厂,负责创建与 Redis 服务的连接。Spring 会自动配置一个默认的连接工厂,可以通过 @EnableAutoConfiguration 来启用 Redis 连接的自动配置。
  • 通过配置 RedisTemplate,我们能够定制各种数据类型的序列化方式。此处我们将所有对象序列化为 JSON,这使得我们可以存储任何类型的 Java 对象,且能保证其在 Redis 中以 JSON 格式进行存储。

5. 如何使用

在 Spring 应用中,通过注入这两个模板对象,我们就可以方便地进行 Redis 操作:

@Autowired
private RedisTemplate<String, Object> redisTemplate;

@Autowired
private StringRedisTemplate stringRedisTemplate;

public void demo() {
    // 使用 StringRedisTemplate 操作字符串
    stringRedisTemplate.opsForValue().set("key", "value");
    String value = stringRedisTemplate.opsForValue().get("key");
    
    // 使用 RedisTemplate 操作对象
    MyObject obj = new MyObject("test", 123);
    redisTemplate.opsForValue().set("myObject", obj);
    MyObject retrievedObj = (MyObject) redisTemplate.opsForValue().get("myObject");
}

小结

  • 该配置类提供了对 RedisTemplateStringRedisTemplate 的自定义配置。
  • RedisTemplate 使用了 JSON 序列化器,这样我们可以存储任何对象并且将它们转换为 JSON 格式存储在 Redis 中。
  • StringRedisTemplate 提供了一个更简单的接口,专门用于处理 Redis 中的字符串数据。

步骤 4: 使用 Redis 操作缓存 🌈

一切配置好之后,就可以通过 RedisTemplate 在 Spring Boot 中操作 Redis 了。下面是一些常见的 Redis 操作示例。

1. 存储和获取简单数据

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

@Service
public class RedisService {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    // 存储数据
    public void setData(String key, String value) {
        stringRedisTemplate.opsForValue().set(key, value);
    }

    // 获取数据
    public String getData(String key) {
        return stringRedisTemplate.opsForValue().get(key);
    }
}

在这个示例中,我们通过 StringRedisTemplateopsForValue() 方法实现了最基本的存取操作:通过 set 方法存储数据,通过 get 方法获取数据。

代码解析

在本次的代码演示中,我将会深入剖析每句代码,详细阐述其背后的设计思想和实现逻辑。通过这样的讲解方式,我希望能够引导同学们逐步构建起对代码的深刻理解。我会先从代码的结构开始,逐步拆解每个模块的功能和作用,并指出关键的代码段,并解释它们是如何协同运行的。通过这样的讲解和实践相结合的方式,我相信每位同学都能够对代码有更深入的理解,并能够早日将其掌握,应用到自己的学习和工作中。

这段代码展示了如何使用 Spring Data Redis 来存储和获取 Redis 中的数据。它通过 StringRedisTemplate 来操作 Redis,并提供了简单的 setDatagetData 方法来存储和读取数据。

1. @Service 注解

@Service
public class RedisService {
  • @Service 注解用于标记该类是一个 Spring 服务类,它的作用类似于 @Component,用于让 Spring 托管这个类的实例,并将它作为一个 Bean 注入到 Spring 容器中。
2. @Autowired 注解
@Autowired
private StringRedisTemplate stringRedisTemplate;
  • @Autowired 注解表示自动注入依赖。Spring 会自动将 StringRedisTemplate 类型的 Bean 注入到 RedisService 中。
  • StringRedisTemplate 是 Spring Data Redis 提供的一个用于操作 Redis 字符串数据的模板类。
3. setData 方法
public void setData(String key, String value) {
    stringRedisTemplate.opsForValue().set(key, value);
}
  • 这个方法使用 StringRedisTemplate 来将数据存入 Redis 中。
  • opsForValue() 获取到操作字符串类型数据的 ValueOperations,该接口提供了很多常见的 Redis 字符串操作方法,如 setgetincrement 等。
  • set(key, value) 方法将 keyvalue 存入 Redis。
4. getData 方法
public String getData(String key) {
    return stringRedisTemplate.opsForValue().get(key);
}
  • 这个方法从 Redis 中获取指定 key 的值,并返回。
  • opsForValue().get(key) 会返回对应 key 的字符串值,如果该 key 不存在,则返回 null
使用方式

在 Spring Boot 应用中,可以通过注入 RedisService 类来进行 Redis 数据的存储和读取。以下是如何使用该服务类的示例:

@Autowired
private RedisService redisService;

public void demo() {
    // 存储数据到 Redis
    redisService.setData("name", "Alice");

    // 获取数据
    String value = redisService.getData("name");
    System.out.println("Retrieved value: " + value);
}
重点说明
  • StringRedisTemplate 仅适用于操作 Redis 中的字符串类型数据。如果需要处理其他类型的数据(如对象),应该使用 RedisTemplate<String, Object>
  • opsForValue() 方法提供了对 Redis 中字符串的操作接口,常用于存储简单的键值对。
小结
  • RedisService 是一个服务类,封装了 Redis 存取操作,提供了 setDatagetData 方法来与 Redis 交互。
  • 使用了 StringRedisTemplate 来进行 Redis 字符串类型数据的存储与读取。
  • 该类可以方便地集成到 Spring Boot 应用中,用于处理缓存、会话存储或简单的键值存储等功能。

2. 使用 RedisTemplate 操作复杂数据结构

Redis 还支持多种数据类型,如 ListHash 等,下面是如何通过 RedisTemplate 操作这些数据类型的示例。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

@Service
public class RedisTemplateService {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    // 存储对象
    public void setObject(String key, Object value) {
        redisTemplate.opsForValue().set(key, value);
    }

    // 获取对象
    public Object getObject(String key) {
        return redisTemplate.opsForValue().get(key);
    }

    // 存储 List
    public void setList(String key, List<String> list) {
        redisTemplate.opsForList().rightPushAll(key, list);
    }

    // 获取 List
    public List<String> getList(String key) {
        return redisTemplate.opsForList().range(key, 0, -1);
    }
}
代码解析

在本次的代码演示中,我将会深入剖析每句代码,详细阐述其背后的设计思想和实现逻辑。通过这样的讲解方式,我希望能够引导同学们逐步构建起对代码的深刻理解。我会先从代码的结构开始,逐步拆解每个模块的功能和作用,并指出关键的代码段,并解释它们是如何协同运行的。通过这样的讲解和实践相结合的方式,我相信每位同学都能够对代码有更深入的理解,并能够早日将其掌握,应用到自己的学习和工作中。

这段代码展示了如何使用 RedisTemplate 来存储和获取 Redis 中的不同数据类型(如对象、列表等)。与之前的 StringRedisTemplate 示例不同,RedisTemplate 提供了更为通用的方式,支持存储各种类型的数据。

1. @Service 注解
@Service
public class RedisTemplateService {
  • @Service 注解用于标记 RedisTemplateService 类为一个 Spring 服务类,使其能够被 Spring 容器管理。
2. @Autowired 注解
@Autowired
private RedisTemplate<String, Object> redisTemplate;
  • @Autowired 注解表示自动注入依赖。这里 RedisTemplate<String, Object> 类型的 Bean 被注入到 RedisTemplateService 中。
  • RedisTemplate 是一个通用的 Redis 操作类,可以操作 Redis 中的各种数据类型,如字符串、列表、哈希、集合等。
3. setObject 方法
public void setObject(String key, Object value) {
    redisTemplate.opsForValue().set(key, value);
}
  • 该方法使用 redisTemplate.opsForValue() 来存储一个对象类型的值。
  • opsForValue() 提供了对 Redis 字符串类型的操作,尽管这里存储的是一个 ObjectRedisTemplate 会自动进行序列化,将对象转换为字节数组存储在 Redis 中。
4. getObject 方法
public Object getObject(String key) {
    return redisTemplate.opsForValue().get(key);
}
  • 该方法从 Redis 获取存储在 key 下的值,并将其返回。
  • opsForValue().get(key) 返回的是存储的对象,RedisTemplate 会自动进行反序列化,返回原始的对象类型。
5. setList 方法
public void setList(String key, List<String> list) {
    redisTemplate.opsForList().rightPushAll(key, list);
}
  • 该方法使用 redisTemplate.opsForList() 来存储一个字符串列表(List<String>)。
  • rightPushAll(key, list)list 中的所有元素依次压入 Redis 列表的右端。
6. getList 方法
public List<String> getList(String key) {
    return redisTemplate.opsForList().range(key, 0, -1);
}
  • 该方法从 Redis 获取存储在 key 下的列表,并返回该列表的所有元素。
  • opsForList().range(key, 0, -1) 返回从 Redis 列表中获取的所有元素,其中 0 是起始索引,-1 表示获取整个列表。
使用方式

在 Spring Boot 应用中,您可以通过注入 RedisTemplateService 类来进行 Redis 数据的存储和读取。以下是如何使用该服务类的示例:

@Autowired
private RedisTemplateService redisTemplateService;

public void demo() {
    // 存储一个对象到 Redis
    redisTemplateService.setObject("user", new User("Alice", 30));

    // 获取对象
    User user = (User) redisTemplateService.getObject("user");
    System.out.println("Retrieved user: " + user);

    // 存储一个列表到 Redis
    List<String> languages = Arrays.asList("Java", "Python", "C++");
    redisTemplateService.setList("languages", languages);

    // 获取列表
    List<String> retrievedLanguages = redisTemplateService.getList("languages");
    System.out.println("Retrieved languages: " + retrievedLanguages);
}
注意事项
  1. 对象存储与序列化

    • 当使用 RedisTemplate 存储对象时,Spring Data Redis 会自动使用默认的序列化机制(JdkSerializationRedisSerializer)将对象转化为字节数组进行存储。
    • 如果希望自定义序列化方式,可以使用 GenericJackson2JsonRedisSerializer 等其他序列化机制。
  2. 列表存储

    • opsForList() 提供了对 Redis 列表的操作支持,可以用来执行如 rightPushAllrange 等操作,操作的是 Redis 的列表类型。
小结
  • RedisTemplateService 类封装了 Redis 数据存储和读取的基本操作,支持存储对象和列表。
  • 使用 RedisTemplate<String, Object>,可以灵活地操作 Redis 中的多种数据类型。
  • 通过 opsForValue()opsForList(),分别实现了对象和列表的存储与读取。
  • 该类可以帮助你更方便地操作 Redis 中的复杂数据结构。

步骤 5: 缓存注解实现自动缓存 🧩

Spring 提供了一个非常便捷的方式来与 Redis 进行集成,那就是使用缓存注解(@Cacheable, @CachePut, @CacheEvict)。这些注解可以帮助你自动实现缓存操作,无需手动操作 RedisTemplate

代码示例
  1. 启用缓存功能

在 Spring Boot 应用中,只需要在主类或者配置类上加上 @EnableCaching 注解,就可以启用缓存支持:

import org.springframework.cache.annotation.EnableCaching;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@EnableCaching
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
  1. 使用 @Cacheable 注解
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

@Service
public class UserService {

    @Cacheable(value = "userCache", key = "#userId")
    public User getUserById(Long userId) {
        // 模拟数据库操作
        System.out.println("Fetching user from database...");
        return new User(userId, "John Doe");
    }
}

在这个示例中,@Cacheable 注解会自动将方法的返回值缓存到 Redis 中,当下次请求相同 userId 时,Spring 会直接从 Redis 中获取数据,而不是重新执行方法。

代码解析:

在本次的代码演示中,我将会深入剖析每句代码,详细阐述其背后的设计思想和实现逻辑。通过这样的讲解方式,我希望能够引导同学们逐步构建起对代码的深刻理解。我会先从代码的结构开始,逐步拆解每个模块的功能和作用,并指出关键的代码段,并解释它们是如何协同运行的。通过这样的讲解和实践相结合的方式,我相信每位同学都能够对代码有更深入的理解,并能够早日将其掌握,应用到自己的学习和工作中。

这段代码演示了如何在 Spring Boot 中使用 缓存 来提高应用程序的性能,具体使用了 @EnableCaching@Cacheable 注解来启用和配置缓存。

代码解析
1. 启用缓存功能
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@EnableCaching
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
  • @SpringBootApplication: 这是一个组合注解,包含了 @Configuration, @EnableAutoConfiguration, 和 @ComponentScan。它表示这是一个 Spring Boot 应用的入口类。
  • @EnableCaching: 这个注解用于启用 Spring 的缓存功能。它会自动配置 Spring Cache 抽象层,使得在应用中能够使用缓存相关的注解,如 @Cacheable@CachePut@CacheEvict 等。

SpringApplication.run(Application.class, args); 会启动 Spring Boot 应用并自动进行缓存配置。

2. 使用 @Cacheable 注解进行缓存
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

@Service
public class UserService {

    @Cacheable(value = "userCache", key = "#userId")
    public User getUserById(Long userId) {
        // 模拟数据库操作
        System.out.println("Fetching user from database...");
        return new User(userId, "John Doe");
    }
}
  • @Service: 这是一个服务类注解,标识该类是一个服务层组件,Spring 会将它自动注册到应用上下文中。
  • @Cacheable(value = "userCache", key = "#userId"):
    • @Cacheable 注解表示该方法的返回值会被缓存。具体来说,当方法被调用时,Spring 会检查缓存中是否已有相应的值。如果有,直接返回缓存中的值;如果没有,执行方法并将返回结果存入缓存。
    • value:缓存的名称,这里是 "userCache",表示使用名为 userCache 的缓存。
    • key:缓存的 key,"#userId" 表示使用方法参数 userId 作为缓存的 key。这样不同的 userId 会对应不同的缓存值。
3. 缓存操作

当你调用 getUserById 方法时,第一次调用时会从数据库(模拟的)获取数据,并将结果缓存。之后再调用相同的 userId 时,Spring 会直接从缓存中返回数据,而不再执行数据库查询操作。

流程分析
  1. 第一次调用 getUserById(1L) 时,"Fetching user from database..." 会被打印出来,说明从数据库获取了数据。同时,这个结果会被缓存,缓存的 key 是 1L,缓存的 value 是 User(1L, "John Doe")

  2. 第二次调用 getUserById(1L) 时,Spring 会检查缓存中是否存在 key 为 1L 的数据。如果存在,它将直接返回缓存中的值,而不再执行数据库操作,也不会打印 "Fetching user from database..."

  3. 如果调用 getUserById(2L),缓存中没有该 key,方法会被执行并缓存结果。每个不同的 userId 会有独立的缓存。

小结
  • 缓存的优势:缓存的主要作用是减少数据库或其他外部资源的访问,从而提升应用的响应速度和性能。通过使用 @Cacheable 注解,Spring 自动为我们处理了缓存的逻辑。
  • 缓存存储:可以将缓存存储在内存中(如 ConcurrentMapCache),也可以将缓存配置为使用外部缓存系统(如 Redis, EhCache, etc.)。可以通过 application.propertiesapplication.yml 文件来配置缓存的存储方式。
  • 缓存过期和清理:除了 @Cacheable 注解,Spring 还提供了 @CacheEvict@CachePut 注解,用于手动控制缓存的过期和更新。

通过这种方式,Spring 提供的缓存注解可以大大简化缓存的使用,使得开发者能够更加专注于业务逻辑的实现。

3. 小结 🏁

Spring Boot 与 Redis 的集成非常简单,通过简单的配置和少量代码,你就可以实现一个高效的缓存系统,显著提升应用的性能。通过 Redis,我们可以有效减轻数据库负担、加速数据访问,特别是在需要频繁读取相同数据的场景中。更重要的是,Spring 提供了注解驱动的缓存方案,使得缓存的管理更加方便,极大地简化了代码。

希望这篇文章能帮助你理解如何将 Redis 集成到 Spring Boot 中,并通过它提升应用的性能。如果你还没试过 Redis,赶快动手实践一下吧,构建一个更高效、更快的应用!🎉

🧧福利赠与你🧧

  无论你是计算机专业的学生,还是对编程有兴趣的小伙伴,都建议直接毫无顾忌的学习此专栏「滚雪球学SpringBoot」,bug菌郑重承诺,凡是学习此专栏的同学,均能获取到所需的知识和技能,全网最快速入门SpringBoot,就像滚雪球一样,越滚越大, 无边无际,指数级提升。

最后,如果这篇文章对你有所帮助,帮忙给作者来个一键三连,关注、点赞、收藏,您的支持就是我坚持写作最大的动力。

同时欢迎大家关注公众号:「猿圈奇妙屋」 ,以便学习更多同类型的技术文章,免费白嫖最新BAT互联网公司面试题、4000G pdf电子书籍、简历模板、技术文章Markdown文档等海量资料。

✨️ Who am I?

我是bug菌,CSDN | 掘金 | InfoQ | 51CTO | 华为云 | 阿里云 | 腾讯云 等社区博客专家,C站博客之星Top30,华为云2023年度十佳博主,掘金多年度人气作者Top40,掘金等各大社区平台签约作者,51CTO年度博主Top12,掘金/InfoQ/51CTO等社区优质创作者;全网粉丝合计 30w+;更多精彩福利点击这里;硬核微信公众号「猿圈奇妙屋」,欢迎你的加入!免费白嫖最新BAT互联网公司面试真题、4000G PDF电子书籍、简历模板等海量资料,你想要的我都有,关键是你不来拿。

-End-

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。