springboot2.x+shiro+redis整合填坑redis只做缓存的情况

我是属车的      2022-04-16     140

关键词:

主要记录关键和有坑的地方

前提:

1、SpringBoot+shiro已经集成完毕,如果没有集成,先查阅之前的Springboot2.0 集成shiro权限管理

2、redis已经安装完成

3、redis客户端使用Lettuce,这也是sprinboot2.0后默认的,与jedis的区别,自行百度

4、json使用springboot默认的

一、依赖

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-cache</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
    //在用使用shiro的情况下集成redis,可以带这个依赖,shiro-redis已经实现了shiro的redis缓存和session管理
    //如果shiro和redis集成但是不交互,可以不引入,可以自定义 <dependency> <groupId>org.crazycake</groupId> <artifactId>shiro-redis</artifactId> <version>3.1.0</version> </dependency>

连接池:

    <!--连接池,redis依赖-->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>

 

 

必须注销:

        <!--与reids缓存冲突-->
        <!--<dependency>-->
            <!--<groupId>org.springframework.boot</groupId>-->
            <!--<artifactId>spring-boot-devtools</artifactId>-->
            <!--<optional>true</optional>-->
        <!--</dependency>-->

二、Application.yml


spring:
...省略

cache:
redis:
time-to-live: 60s
type: redis
redis:
host: 127.0.0.1
port: 6379
password: 123456@abc.com
timeout: 10000
lettuce:
pool:
max-idle: 10
max-active: 10
min-idle: 5
max-wait: 10000
database: 0

 

三、redis配置类

@Configuration
@EnableCaching //开启Springboot缓存,重要!!!
public class RedisConfig extends CachingConfigurerSupport {
    @Resource
    private LettuceConnectionFactory lettuceConnectionFactory;
    private Duration timeToLive = Duration.ofSeconds(60); 

    @Bean //在没有指定缓存Key的情况下,key生成策略
    public KeyGenerator keyGenerator() {
        return new KeyGenerator() {
            @Override
            public Object generate(Object target, Method method, Object... params) {
                StringBuffer sb = new StringBuffer();
                sb.append(target.getClass().getName());
                sb.append(method.getName());
                for (Object obj : params) {
                    sb.append(obj.toString());
                }
                return sb.toString();
            }
        };
    }

    // 缓存管理器 使用Lettuce,和jedis有很大不同
    @Bean
    public CacheManager cacheManager() {
//关键点,spring cache的注解使用的序列化都从这来,没有这个配置的话使用的jdk自己的序列化,实际上不影响使用,只是打印出来不适合人眼识别 RedisCacheConfiguration config
= RedisCacheConfiguration.defaultCacheConfig() .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(keySerializer()))//key序列化方式 .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(valueSerializer()))//value序列化方式 .disableCachingNullValues()
.entryTtl(timeToLive);//缓存过期时间 RedisCacheManager.RedisCacheManagerBuilder builder
= RedisCacheManager.RedisCacheManagerBuilder .fromConnectionFactory(lettuceConnectionFactory) .cacheDefaults(config) .transactionAware(); return builder.build(); } /** * RedisTemplate配置 在单独使用redisTemplate的时候 重新定义序列化方式 */ @Bean public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory lettuceConnectionFactory) { // 设置序列化 Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<Object>( Object.class); ObjectMapper om = new ObjectMapper(); om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); jackson2JsonRedisSerializer.setObjectMapper(om); // 配置redisTemplate RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>(); redisTemplate.setConnectionFactory(lettuceConnectionFactory); RedisSerializer<?> stringSerializer = new StringRedisSerializer(); redisTemplate.setKeySerializer(stringSerializer);// key序列化 redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);// value序列化 redisTemplate.setHashKeySerializer(stringSerializer);// Hash key序列化 redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);// Hash value序列化 redisTemplate.afterPropertiesSet(); return redisTemplate; } private RedisSerializer<String> keySerializer() { return new StringRedisSerializer(); } private RedisSerializer<Object> valueSerializer() { // 设置序列化 Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<Object>( Object.class); ObjectMapper om = new ObjectMapper(); om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); jackson2JsonRedisSerializer.setObjectMapper(om); return jackson2JsonRedisSerializer; //或者使用GenericJackson2JsonRedisSerializer //return new GenericJackson2JsonRedisSerializer(); } }

在自定义序列化过程,GenericJackson2JsonRedisSerializer和Jackson2JsonRedisSerializer大部分时候表现没有区别,实际上如果对象中有LinkedHashMap时候,后者会出错,这个以前坑了我很久,自我怀疑了很久。

建议使用GenericJackson2JsonRedisSerializer来序列化。

GenericJackson2JsonRedisSerializer和Jackson2JsonRedisSerializer都有一个问题,无法反序列化接口的动态代理类,原因应该是动态代理类没有缺省构造函数,对JPA的自定义结果集支持不好,对Page分页支持不好。

 

四、在service上使用缓存,具体Springboot的Cache注解百度上很多。

@CacheConfig(cacheNames = "user")
public interface UserService {
    @Cacheable(key = "'userName'.concat(#userName)")
    User findByUserName(String userName);   
}

 

五、必须修改Shiro的AuthorizingRealm,这里也是最坑的地方

public class MyShiroRealm extends AuthorizingRealm {

    @Resource
    @Lazy //就是这里,必须延时加载,根本原因是bean实例化的顺序上,shiro的bean必须要先实例化,否则@Cacheable注解无效,理论上可以用@Order控制顺序
    private UserService userService;

    //权限信息,包括角色以及权限
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
      略
    }

    /*主要是用来进行身份认证的,也就是说验证用户输入的账号和密码是否正确。*/
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token)
            throws AuthenticationException {
      略
    }

}

六、实体中如果有java8time,诸如LocalDateTime,redis缓存反序列化的时候会失败,必须在实体中指定json序列化和反序列化的类@JsonDeserialize和@JsonSerialize

    @JsonDeserialize(using = LocalDateTimeDeserializer.class)
    @JsonSerialize(using = LocalDateTimeSerializer.class)
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    //格式化前台页面收到的json时间格式,不指定的话会变成缺省的"yyyy-MM-dd'T'HH:mm:ss"
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime createTime;//创建时间
    @JsonDeserialize(using = LocalDateDeserializer.class)
    @JsonSerialize(using = LocalDateSerializer.class)
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    @JsonFormat(pattern = "yyyy-MM-dd")
    private LocalDate expiredDate;//过期日期

 

暂时就是这些关键点和关键坑,记录,不然肯定忘记。

springboot2.x+maven+mybatis+shiro+redis

...的一哥们的springboot1.X整合shiro和redis的demo,我用的是springboot2.X,改了下,添加了druid和swagger2,部分,公司屏蔽git,只能上传csdn备份。那位哥们的原文找不到了,sorry。部署resource/sql/shiro.sql;修改applicati... 查看详情

springboot2.x以上整合shiro1.7.1和redis的一些注意事项(代码片段)

因为之前用的shiro版本一直是1.4.0,后来我们老大跟我说版本太低了,不安全,叫我升级到1.7.1。升级后发现有些配置很不一样的,需要注意一下。一、pom.xml<parent><groupId>org.springframework.boot</groupId><ar... 查看详情

springboot2.x以上整合shiro1.7.1和redis的一些注意事项(代码片段)

因为之前用的shiro版本一直是1.4.0,后来我们老大跟我说版本太低了,不安全,叫我升级到1.7.1。升级后发现有些配置很不一样的,需要注意一下。一、pom.xml<parent><groupId>org.springframework.boot</groupId><ar... 查看详情

springboot2.x集成单节点redis

Springboot2.x集成单节点Redis说明在Springboot1.x版本中,默认使用Jedis客户端来操作Redis,而在Springboot2.x版本中,默认使用Lettuce客户端来操作Redis。Springboot提供了RedisTemplate来统一封装了对Redis操作,开发者只需要使用RedisTemplate就可以... 查看详情

springboot2.x版本整合redis集群

参考技术A启动Redis集群搭建方式SpringBoot1.x版本默认使用jedis连接,2.x版本使用lettuce连接ymlyml测试 查看详情

springboot2.x集成redis哨兵模式

Springboot2.x集成Redis哨兵模式说明Redis哨兵模式是Redis高可用方案的一种实现方式,通过哨兵来自动实现故障转移,从而保证高可用。准备条件pom.xml中引入相关jar<!--集成Redis--><dependency><groupId>org.springframework.boot</group... 查看详情

springboot2.x整合redis

pom文件<!--springboot中的redis依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency>配置#R 查看详情

springboot2.x整合redis

#准备工作配置application.ymlspring:thymeleaf:#thymeleafcache:falsedatasource:#datasourcedriver-class-name:com.mysql.cj.jdbc.Driverurl:jdbc:mysql://localhost:3306/mp?useUnicode=true&characterEncoding=utf 查看详情

springboot2.x版本整合redis(单机/集群)(使用lettuce)

在springboot1.x系列中,其中使用的是jedis,但是到了springboot2.x其中使用的是Lettuce。此处springboot2.x,所以使用的是Lettuce。关于jedis跟lettuce的区别:Lettuce和Jedis的定位都是Redis的client,所以他们当然可以直接连接redisserver。Jedis在实现... 查看详情

springboot2.x集成redis缓存(代码片段)

SpringBoot集成Redis缓存在此章,我们将SpringBoot集成Redis缓存,Redis是一个开源的,基于内存的数据结构存储,可以用作数据库、缓存和消息代理,在本章仅讲解缓存集成。准备工作当前项目工具及环境开发工具IDEA2020.3依赖管理MavenS... 查看详情

springboot2.x:springboot集成redis

Redis简介什么是RedisRedis是目前使用的非常广泛的免费开源内存数据库,是一个高性能的key-value数据库。Redis与其他key-value缓存(如Memcached)相比有以下三个特点:1.Redis支持数据的持久化,它可以将内存中的数据保存在磁盘中,重... 查看详情

springboot2.x整合redis以及连接哨兵模式/集群模式

依赖:<!--spirngboot版本为2.x--><!--加载springbootredis包,springboot2.0中直接使用jedis或者lettuce配置连接池,默认为lettuce连接池,这里使用jedis连接池--><!--加载springbootredis包--><dependency> <groupId>org.spr 查看详情

springboot2.x(十四):整合redis,看这一篇就够了

Redis简介Redis是一个开源的使用ANSIC语言编写、遵守BSD协议、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API的非关系型数据库(NoSQL)。Redis的特性Redis的所有操作都是原子性的,意思就是要么成... 查看详情

springboot2.x基础教程:使用集中式缓存redis

之前我们介绍了两种进程内缓存的用法,包括SpringBoot默认使用的ConcurrentMap缓存以及缓存框架EhCache。虽然EhCache已经能够适用很多应用场景,但是由于EhCache是进程内的缓存框架,在集群模式下时,各应用服务器之间的缓存都是独... 查看详情

springboot2.x最佳实践《一》之springboot2.x初体验

SpringBoot2.X最佳实践前言本系列文章,从零基础接触 SpringBoot2.x新版本,基础入门使用,热部署,到整合各个主流框架Redis4.x,消息队列AciveMQ,RocketMQ等,搜索框架ElasticSearch5.6版本,到web-flux反应式编程,到Actuator监控应用信息... 查看详情

spring-data-redis2.0的使用

在使用SpringBoot2.x运行Redis时,发现百度不到顺手的文档,搞通后发现其实这个过程非常简单和简洁,觉得有必要拿出来分享一下。SpringBoot2.x不再使用Jedis,换成了Lettuce。Lettuce是基于Netty实现的,所以性能更好。但是我看到很多... 查看详情

springboot2.x微信公众平台开发环境说明

本文随时更新~~~ JDK:1.8SpringBoot:2.0.4Redis测试公众号数据库暂时还没用到目前的pom.xml<projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://m 查看详情

用idea基于springboot2+mybatis+redis实现一个秒杀系统

实现一个秒杀系统,采用springboot2.x+mybatis+redis+swagger2+lombok实现。先说说基本流程,就是提供一个秒杀接口,然后针对秒杀接口进行限流,限流的方式目前我实现了两种,上次实现的是累计计数方式,这次还有这个功能,并且我... 查看详情