开发者

SpringBoot + Mybatis Plus 整合 Redis的详细步骤

目录
  • Redis 在用户管理系统中的典型应用场景
  • MAC M1 安装 Redis 详细步骤
    • 1. 通过 Homebrew 安装 Redis
    • 2. 启动 Redis 服务
    • 3. 验证安装
  • Spring Boot 3 整合 Redis
    • 1. 添加依赖
    • 2. 配置 Redis 连接
    • 3. 示例
  • 总结

    Redis 在用户管理系统中的典型应用场景

    结合你的用户增删改查接口,以下是 Redis 的实用场景和具体实现方案:

    场景作用实现方案
    用户信息缓存减少数据库压力,加速查询响应使用 Spring Cache + Redis 注解缓存
    登录 Token 存储分布式 Session 或 JWT Token 管理将 Token 与用户信息绑定,设置过期时间
    接口限流防止恶意刷接口基于 Redis 计数器实现滑动窗口限流
    重复提交拦截防止用户重复提交表单用 Redis 存储请求唯一标识,设置短期过期
    热点数据预加载提前缓存高频访问数据定时任务 + Redis 存储

    Mac M1 安装 Redis 详细步骤

    1. 通过 Homebrew 安装 Redis

    # 安装 Homebrew(如果尚未安装)
    /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
    # 安装 Redis
    brew install redis

    2. 启动 Redis 服务

    # 前台启动(测试用,Ctrl+C 退出)
    redis-server
    # 后台启动(推荐)
    brew services start redis

    3. 验证安装

    # 连接 Redis 客户端
    redis-cli ping  # 应返回 "PONG"

    Spring Boot 3 整合 Redis

    1. 添加依赖

    pom.XML 中:

    		<!-- Spring Cache 核心依赖 -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-cache</artifactId>
            </dependency>
    
            <!-- Redis 驱动 -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-redis</artifactId>
            </dependency>
            <dependency>
                <groupId>com.fasterxml.jackson.core</groupId>
                <artifactId>jackson-databind</artifactId>
            </dependency>
    

    2. 配置 Redis 连接

    application.yml

    spring:
      data:
        redis:
          host: localhost
          port: 6379
          # password: your-password  # 如果设置了密码
          lettuce:
            pool:
              max-active: 8
              max-idle: 8

    3. 示例

    配置类

    package com.example.spring_demo01.config;
    import org.springframework.cache.CacheManager;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.data.redis.cache.RedisCacheConfiguration;
    import org.springframework.data.redis.cache.RedisCacheManager;
    import org.springframework.data.redis.connection.RedisConnectionFactory;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.data.redis.serializer.*;
    import Java.time.Duration;
    @Configuration
    public class RedisConfig {
        // 配置 RedisTemplate
        @Bean
        public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
            RedisTemplate<String, Object> template = new RedisTemplate<>();
            template.setConnectionFactory(factory);
            // Key 序列化
            template.setKeySerializer(new StringRedisSerializer());
            // Value 序列化为 jsON
            template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
            // Hash 结构序列化
            template.setHashKeySerializer(new StringRedisSerializer());
            template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
            return template;
        python}
        // 配置缓存管理器
        @BeadwoAQrDBfYn
        public CacheManager cacheManager(RedisConnectionFactory factory) {
            RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                   编程客栈 .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
                    .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()))
                    .entryTtl(Duration.ofMinutes(30)); // 设置默认过期时间
            return RedisCacheManager.builder(factory)
                    .cacheDefaults(config)
                    .build();
        }
    }

    接口限流工具类

    package com.example.spring_demo01.utils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.stereotype.Component;
    import java.util.UUID;
    import java.util.concurrent.TimeUnit;
    @Component
    public class RateLimiter {
        @Autowired
        private RedisTemplate<String, Object> redisTemplate;
        public boolean allowRequest(String userId) {
            String key = "rate_limit:" + userId;
            long now = System.currentTimeMillis();
            long windowMs = 60_000; // 1 分钟
            // 移除窗口外的请求记录
            redisTemplate.opsForZSet().removeRangeByScore(key, 0, now - windowMs);
            // 统计当前窗口内请求数
            Long count = redisTemplate.opsForZSet().zCard(key);
            if (count != null && count >= 10) {
                return false; // 超过限制
            }
            // 记录本次请求
            redisTemplate.opsForZSet().add(key, UUID.randomUUID().toString(), now);
            redisTemplate.expire(key, windowMs, TimeUnit.MILLISECONDS);
            return true;
        }
    }

    实体类

    package com.example.spring_demo01.entity;
    import com.baomidou.myBATisplus.annotation.*;
    import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
    import lombok.Data;
    import java.io.Serializable;
    @Data
    @TableName("user")
    @JsonIgnoreProperties(ignoreUnknown = true) // 防止 JSON 反序列化问题
    public class User implements Serializable { // 实现 Serializable
        @TableId(type = IdType.AUTO) // 主键自增
        private Long id;
        private String name;
        private Integer age;
        private String email;
    }

    service层

    package com.example.spring_demo01.service.impl;
    import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
    import com.example.spring_demo01.entity.User;
    import com.example.spring_demo01.mapper.UserMapper;
    import com.example.spring_demo01.service.UserService;
    import org.springframework.cache.annotation.CacheEvict;
    import org.springframework.cache.annotation.Cacheable;
    import org.springframework.stereotype.Service;
    import java.io.Serializable;
    @Service
    public class UserServiceImpl
            extends ServiceImpl<UserMapper, User>
            implements UserService {
        // 对 MyBatis Plus 的 getById 方法添加缓存
        @Cacheable(value = "user", key = "#id")
        @Override
        public User getById(Serializable id) {
            return super.getById(id);
        }
        // 更新时清除缓存
        @CacheEvict(value = "user", key = "#entity.id")
        @Override
        public boolean updateById(User javascriptentity) {
            return super.updateById(entity);
        }
        // 删除时清除缓存
        @CacheEvict(value = "user", key = "#id")
        @Override
        public boolean removeById(Serializable id) {
            return super.removeById(id);
        }
    }

    controller层

    package com.example.spring_demo01.controller;
    import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
    import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
    import com.example.spring_demo01.annotation.AdminOnly;
    import com.example.spring_demo01.entity.User;
    import com.example.spring_demo01.service.UserService;
    import com.example.spring_demo01.utils.RateLimiter;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.web.bind.annotation.*;
    import java.time.Duration;
    import java.util.List;
    import java.util.UUID;
    @Slf4j
    @RestController
    @RequestMapping("/user")
    public class UserController {
        @Autowired
        private UserService userService;
        @Autowired
        private RedisTemplate<String, Object> redisTemplate;
        @Autowired
        private RateLimiter rateLimiter;
        // ------------------------------ 增 ------------------------------
        @PostMapping
        public String addUser(@RequestBody User user, @RequestHeader String clientId) {
            String key = "SUBMIT_LOCK:" + clientId + ":" + user.hashCode();
            // 10秒内不允许重复提交
            Boolean success = redisTemplate.opsForValue()
                    .setIfAbsent(key, "", Duration.ofSeconds(10));
            if (Boolean.FALSE.equals(success)) {
                throw new RuntimeException("请勿重复提交");
            }
            userService.save(user);
            return "新增成功";
        }
        // ------------------------------ 删 ------------------------------
        @DeleteMapping("/{id}")
        public String deleteUser(@PathVariable Long id) {
            userService.removeById(id);
            return "删除成功";
        }
        @DeleteMapping("/batch")
        public String deleteBatch(@RequestBody List<Long> ids) {
            userService.removeByIds(ids);
            return "批量删除成功";
        }
        // ------------------------------ 改 ------------------------------
        @PutMapping
        public String updateUser(@RequestBody User user) {
            userService.updateById(user);
            return "更新成功";
        }
        // ------------------------------ 查 ------------------------------
        @GetMapping("/{id}")
        @AdminOnly
        public User getUserById(@PathVariable Long id) {
            return userService.getById(id);
        }
        @GetMapping("/list")
        public List<User> listUsers(
                @RequestParam(required = false) String name,
                @RequestParam(required = false) Integer age) {
            QueryWrapper<User> wrapper = new QueryWrapper<>();
            if (name != null) {
                wrapper.like("name", name); // 模糊查询姓名
            }
            if (age != null) {
                wrapper.eq("age", age);     // 精确查询年龄
            }
            return userService.list(wrapper);
        }
        @GetMapping("/page")
        public Page<User> pageUsers(
                @RequestParam(defaultValue = "1") Integer pageNum,
                @RequestParam(defaultValue = "10") Integer pageSize,
                @RequestHeader(value = "Authorization") String token) {
            // 从 Token 中获取用户ID
            log.info("token:{}", token);
            log.info("User:{}", redisTemplate.opsForValue().get(token.split(" ")[1]));
            User user = (User) redisTemplate.opsForValue().get(token.split(" ")[1]);
            if (user == null) throw new RuntimeException("未登录");
            // 限流校验
            if (!rateLimiter.allowRequest("PAGE_" + user.getId())) {
                throw new RuntimeException("请求过于频繁");
            }
            return userService.page(new Page<>(pageNum, pageSize));
        }
        // ------------------------------ other ------------------------------
        @GetMapping("/error")
        public String getError() {
            throw new RuntimeException();
        }
        @PostMapping("/login")
        public String login(@RequestBody User user) {
            log.info("login user:{}", user);
            // 验证用户逻辑(示例简化)
            User dbUser = userService.getOne(new QueryWrapper<User>()
                    .eq("id", user.getId())
                    .eq("name", user.getName()));
            if (dbUser == null) {
                throw new RuntimeException("登录失败");
            }
            // 生成 Token 并存储
            String token = "TOKEN_" + UUID.randomUUID();
            redisTemplate.opsForValue().set(
                    token,
                    dbUser,
                    Duration.ofMinutes(30)
            );
            return token;
        }
    }

    在启动类添加注解:

    package com.example.spring_demo01;
    import org.mybatis.spring.annotation.MapperScan;
    import org.springframeworkpython.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.boot.web.servlet.ServletComponentScan;
    import org.springframework.cache.annotation.EnableCaching;
    @SpringBootApplication
    @MapperScan("com.example.spring_demo01.mapper")
    @ServletComponentScan // 启用 Servlet 组件扫描(如 Filter、Servlet)
    @EnableCaching // 启动缓存,Redis使用
    public class SpringDemo01Application {
        public static void main(String[] args) {
            SpringApplication.run(SpringDemo01Application.class, args);
        }
    }

    常见问题排查

    Q1: 连接 Redis 超时

    • 检查服务状态:运行 redis-cli ping 确认 Redis 是否正常运行
    • 查看端口占用lsof -i :6379
    • 关闭防火墙sudo ufw allow 6379

    Q2: Spring Boot 无法注入 RedisTemplate

    • 确认配置类:添加 @EnableCaching 和 @Configuration
    • 检查序列化器:显式配置序列化方式避免 ClassCastException
    @Configuration
    public class RedisConfig {
        @Bean
        public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
            RedisTemplate<String, Object> template = new RedisTemplate<>();
            template.setConnectionFactory(factory);
            template.setKeySerializer(new StringRedisSerializer());
            template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
            return template;
        }
    }

    总结

    通过 Redis 你可以为项目快速实现:

    • 高性能缓存层 - 降低数据库负载
    • 分布式会话管理 - 支持横向扩展
    • 精细化流量控制 - 保障系统稳定性

    到此这篇关于SpringBoot + Mybatis Plus 整合 Redis的详细步骤的文章就介绍到这了,更多相关SpringBoot Mybatis Plus 整合 Redis内容请搜索编程客栈(www.devze.com)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程客栈(www.devze.com)!

    0

    上一篇:

    下一篇:

    精彩评论

    暂无评论...
    验证码 换一张
    取 消

    最新开发

    开发排行榜