当前位置: 代码网 > it编程>编程语言>Java > SpringBoot + Mybatis Plus 整合 Redis的详细步骤

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

2025年03月18日 Java 我要评论
redis 在用户管理系统中的典型应用场景结合你的用户增删改查接口,以下是 redis 的实用场景和具体实现方案:场景作用实现方案用户信息缓存减少数据库压力,加速查询响应使用 spring cache

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;
    }
    // 配置缓存管理器
    @bean
    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 entity) {
        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.springframework.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内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com