Spring Boot集成Spring Security系列五之Redis持久化缓存

999 阅读4分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第17天,点击查看活动详情

大家好,我是程序员路飞,三年的下水道打杂前端,喜欢研究技术,正在往全栈发展
欢迎小伙伴们加我微信:DZHningmeng,一起讨论,期待与大家共同成长🥂

前言

这是Spring Boot集成Spring Security的第五章,我将会通过这个系列文章,包括完整的项目搭建、编码过程实现(认证和授权),关键点讲解,来帮助大家了解Spring Security在实际项目中的应用

今天这篇内容主要是Redis持久化缓存

源码链接

往期系列

Spring Boot集成Spring Security系列一之搭建项目

Spring Boot集成Spring Security系列二之查询用户

Spring Boot集成Spring Security系列三之自定义登录

Spring Boot集成Spring Security系列四之接口鉴权

功能实现

需求

在第四章,我们的Spring Security在接口每次进来的时候,每次获取userDetailpermission,当请求量大的时候对数据库的压力是比较大,而且这两个用户的信息变化的频次是低的,所以我们可以考虑把对应的信息保存在Redis中,获取数据更快,也能减小数据库压力。

Redis安装连接参考

Redis客户端连接工具

引入依赖和配置

<!--redis依赖配置-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

在spring节点下增加配置

redis:
  host: localhost # Redis服务器地址
  database: 0 # Redis数据库索引(默认为0)
  port: 6379
  password: # Redis服务器连接密码,默认为空
  jedis:
    pool:
      max-active: 8 # 连接池最大连接数(使用负值表示没有限制)
      max-wait: -1ms # 连接池最大等待时间(使用负值表示没有限制)
      max-idle: 8 # 连接池中的最大空闲连接
      min-idle: 0 # 连接池中的最小空闲连接
  timeout: 30000ms # 连接超时时间(毫秒)

在根节点添加自定义redis配置

# 自定义Redis key
redis:
  key:
    prefix:
      authCode: "portal:authCode:"
    expire:
      authCode: 120 # 验证码超期时间

实现Redis Service

package com.example.springsecurity.service;

public interface RedisService {
    /**
     * 存储数据
     */
    void set(String key, String value);

    /**
     * 获取数据
     */

    String get(String key);

    /**
     * 设置过期时间
     */
    boolean expire(String key, long expire);

    /**
     * 删除数据
     */
    void remove(String key);

    /**
     * 自增操作
     */
    Long increment(String key, long delta);
}

实现类

package com.example.springsecurity.service.Impl;

import com.example.springsecurity.service.RedisService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;

import java.util.concurrent.TimeUnit;

public class RedisServiceImpl implements RedisService {
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Override
    public void set(String key, String value) {
        stringRedisTemplate.opsForValue().set(key, value);
    }

    @Override
    public String get(String key) {
        return stringRedisTemplate.opsForValue().get(key);
    }

    @Override
    public boolean expire(String key, long expire) {
        return stringRedisTemplate.expire(key, expire, TimeUnit.SECONDS);
    }

    @Override
    public void remove(String key) {
        stringRedisTemplate.delete(key);
    }

    @Override
    public Long increment(String key, long delta) {
        return stringRedisTemplate.opsForValue().increment(key, delta);
    }
}

修改UserServiceImpl

@Override
public User queryUserByUsername(String username) {
    String userStr = redisService.get(REDIS_KEY_PREFIX_AUTH_CODE + username);
    User user = null;
    if(userStr == null) {
        user = userMapper.queryUserByName(username);
        redisService.set(REDIS_KEY_PREFIX_AUTH_CODE + username, JSONUtil.toJsonStr(user));
        redisService.expire(REDIS_KEY_PREFIX_AUTH_CODE + username, AUTH_CODE_EXPIRE_SECONDS);
    } else {
        user = JSONUtil.toBean(userStr, User.class);
    }

    return user;
}

验证

启动redis

image.png

image.png

启动项目,访问http://localhost:8080/user/queryUserByUsername?username=admin

第一次Redis没有对应用户信息的时候,会从数据库获取信息,从控制台打印的sql可以看出,而且Redis数据也成功保存

image.png

image.png

第二次访问http://localhost:8080/user/queryUserByUsername?username=admin

因为权限没有做Redis缓存,使用从数据库取,用户信息从Redis直接返回,这样就达到我们缓存的目的

当然有同学会问到如果用户信息更新我们如何处理,我们只要在用户更新的service里面set对应的key就可以完成更新Redis用户数据,保证数据的一致性

image.png

我们改造下下代码,将permission集成到用户信息里面,不用额外的key,具体可以参照源代码,这里就不具体讲解了

小结

到这里,我们的用户信息缓存就完成了,结合Redis实现功能需求,到这里我们的基本功能要求就符合要求了,后面会进入高级的内容,结合前端完成一个完整的用户登录,认证,权限的系统

🚴‍♀️ 结束语

通过项目实践,结合具体的步骤,输出相关的文章,给小伙伴一些有些的知识点,希望大家喜欢我的文章,希望认识到更多志同道合的伙伴,如果你也对技术感兴趣,可以加我好友互相探讨一起进步

Github: Cheering-baby

公众号: 程序员路飞

vx: DZHningmeng

最后,如果喜欢我的文章,可以给个赞👍或者关注➕都是对我最大的支持