IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 大数据 -> Redis缓存在SpringBoot工程中的应用 -> 正文阅读

[大数据]Redis缓存在SpringBoot工程中的应用

目录

一、基于RedisTemplate方式

1、业务描述

2、业务逻辑代码

3、自定义配置类

二、基于AOP方式

1、业务描述

2、业务逻辑代码

3、自定义配置类

3.1、定义key生成器

3.2、定义cache管理对象

三、加入本地缓存策略

1、业务描述

2、业务实现


一、基于RedisTemplate方式

1、业务描述

RedisTemplate方式实现业务操作优先查询redis缓存,如果redis缓存中没有数据再查询mysql数据库。

2、业务逻辑代码

    //注入RedisTemplate对象
    @Autowired
    private RedisTemplate redisTemplate;
    //业务处理
    @Override
    public List<Tag> selectTags() {
        //1.从redis查询Tag信息,redis有则直接返回
        ValueOperations<String,List<Tag>> valueOperations =
        redisTemplate.opsForValue();
        List<Tag> tags=valueOperations.get("tags");
        if(tags!=null&&!tags.isEmpty())return tags;
        //2.从redis没有获取tag信息,查询mysql
        tags = tagMapper.selectList(null);
        //3.将从mysql查询到tag信息存储到redis
        valueOperations.set("tags", tags);
        //4.返回查询结果
        return tags;
   }

3、自定义配置类

1、自定义RedisTemplate的泛型,默认泛型为Object,实际业务中需要进行自定义配置。

默认为:RedisTemplate<Object,Object>
修改为:RedisTemplate<String, ? extends Object>
其中:  ? extends Object  意为上界限定通配符

2、自定义RedisTemplate中的序列化方式,Redis容易默认采用的是JDK的序列化方式,非Java程序读取的情况下无法阅读容器中的对象。

具体代码如下:

 /**
     * 1、自定义RedisTemplate的泛型
     * 2、自定义RedisTemplate中的序列化方式
     * 代码定制参考RedisAutoConfiguration类
     */
    @Bean
    @ConditionalOnMissingBean(name = {"redisTemplate"})
    public RedisTemplate<String, ? extends Object> redisTemplate(
            RedisConnectionFactory redisConnectionFactory) {
        //定义RedisTemplate的泛型类型
        RedisTemplate<String, ? extends Object> template = new RedisTemplate();
        template.setConnectionFactory(redisConnectionFactory);

        //定义redisTemplate对象的序列号方式
        //1、定义key的序列化方式
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        template.setKeySerializer(stringRedisSerializer);
        template.setHashKeySerializer(stringRedisSerializer);
        //2、定义value的序列化方式
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer =
                new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        objectMapper.activateDefaultTyping(
                objectMapper.getPolymorphicTypeValidator(),
                ObjectMapper.DefaultTyping.NON_FINAL,
                JsonTypeInfo.As.PROPERTY);
        jackson2JsonRedisSerializer.setObjectMapper(objectMapper);

        template.setValueSerializer(jackson2JsonRedisSerializer);
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        //3.修改redisTemplate默认样式
        template.afterPropertiesSet();//after表示除了序列化,其他原有特性不丢
        template.setEnableTransactionSupport(true);
        return template;
    }

二、基于AOP方式

1、业务描述

AOP方式实现业务操作优先查询redis缓存,如果redis缓存中没有数据再查询mysql数据库。

2、业务逻辑代码

只需在业务方法上添加 @Cacheable?注解即可,value的值为redis容器中key的值。

注:@Cacheable?注解生效前提需要在启动类或者配置类上添加?@EnableCaching?注解。

    /**
     * @Cacheable注解描述的方法为缓存切入点方法
     * 访问此方法时系统底层会先从缓存查找数据,假如缓存没有会查询mysql
     * 这个注解假如想生效需要在启动类或者配置上添加@EnableCaching注解
     */
    @Cacheable(value = "tagCache")
    @Override
    public List<Tag> selectTags() {
        return tagMapper.selectList(null);
    }

3、自定义配置类

3.1、定义key生成器

默认key可读性较差。

需要注意的是定义 KeyGenerator?bean对象时配置类需要继承CachingConfigurerSupport?类。

    /**
     * 自定义缓存key的生成器,不定义也可以使用默认的key
     * 注:定义KeyGenerator对象key生成器时,配置类需要继承CachingConfigurerSupport对象
     */
    @Bean
    public KeyGenerator keyGenerator(){
        return (o, method, objects) -> {
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder
                    .append(o.getClass().getName())
                    .append("::")
                    .append(method.getClass().getName());
            for (Object object : objects) { //方法没有参数就没有这个循环了
                stringBuilder.append(object);
            }
            return stringBuilder.toString();
        };
    }

3.2、定义cache管理对象

在AOP方式下使用的序列化方式默认也是JDK方式,需要转换为Json方式的话也需要自己配置。

 /**
     * 自定义Cache管理器对象,按照指定的序列化方式进行序列化,
     * 将序列化修改为Json方式(redis默认的序列化方式是JDK序列化)
     * redis默认的序列化方式是JDK序列化
     */
    @Bean
    public CacheManager CacheManager(RedisConnectionFactory redisConnectionFactory){

        RedisCacheConfiguration config = RedisCacheConfiguration
                .defaultCacheConfig()
                .entryTtl(Duration.ofSeconds(60))//设置key的有效时间,可根据业务需求设置
        //配置key的序列化
                .serializeKeysWith(RedisSerializationContext
                .SerializationPair
                .fromSerializer(new StringRedisSerializer()))
        //配置value的序列化
                .serializeValuesWith(RedisSerializationContext
                .SerializationPair
                .fromSerializer(new Jackson2JsonRedisSerializer<Object>(Object.class)))
                .disableCachingNullValues();//不存储空值

        return RedisCacheManager
                .builder(redisConnectionFactory)
                .cacheDefaults(config)//修改默认对象
                .transactionAware()//启动默认事物
                .build();
    }

三、加入本地缓存策略

1、业务描述

查询优先查询本地缓存,如果本地缓存没有数据查询redis缓存,?如果redis缓存没有数据最后再查询数据库。

2、业务实现

1、使用 CopyOnWriteArrayList 对象,相对于 ArrayList?这种方式线程安全。

2、采用了双重校验的方法,保证线程安全,同时减少阻塞。

@RestController
@RequestMapping("/tag")
public class TagController {
    @Autowired
    private TagService tagService;
    //此对象存在JVM
    private List<Tag> tags=new CopyOnWriteArrayList<>();//本地 cache
    @GetMapping
    public  List<Tag> doSelectTags(){
       if(tags.isEmpty()) {
           synchronized (tags) {
               if(tags.isEmpty()) {
                   tags.addAll(tagService.selectTags());//1.redis,2.mysql
               }
           }
       }
       return tags;
    }
}
序列化:
狭义层面:将对象转换为字节(I/O 相当于序列化的子集)
广义层面:将对象转换为指定格式字符串(例如:json)
封装:
狭义层面:属性私有化,方法能公开则公开
广义层面:一个系统有哪些服务(子系统),一个服务有哪些模块,一个模块有哪些对象,一个对象有哪些属性
  大数据 最新文章
实现Kafka至少消费一次
亚马逊云科技:还在苦于ETL?Zero ETL的时代
初探MapReduce
【SpringBoot框架篇】32.基于注解+redis实现
Elasticsearch:如何减少 Elasticsearch 集
Go redis操作
Redis面试题
专题五 Redis高并发场景
基于GBase8s和Calcite的多数据源查询
Redis——底层数据结构原理
上一篇文章      下一篇文章      查看所有文章
加:2021-10-15 11:51:47  更:2021-10-15 11:54:18 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 1:04:47-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码