Springboot自身缓存集合Redis的实现方式

Springboot自身缓存集合Redis的实现方式

一、Redis介绍
Redis是当前比较热门的NOSQL系统之一,它是一个开源的使用ANSI c语言编写的key-value存储系统
(区别于MySQL的二维表格的形式存储。)。和Memcache类似,但很大程度补偿了Memcache的不
足。和Memcache一样,Redis数据都是缓存在计算机内存中,不同的是,Memcache只能将数据缓存到
内存中,无法自动定期写入硬盘,这就表示,一断电或重启,内存清空,数据丢失。所以Memcache的
应用场景适用于缓存无需持久化的数据。而Redis不同的是它会周期性的把更新的数据写入磁盘或者把修
改操作写入追加的记录文件,实现数据的持久化。
Redis的特点:
1,Redis读取的速度是110000次/s,写的速度是81000次/s;
2,原子 。Redis的所有操作都是原子性的,同时Redis还支持对几个操作全并后的原子性执行。
3,支持多种数据结构:string(字符串);list(列表);hash(哈希),set(集合);zset(有序集合)
4,持久化,集群部署
5,支持过期时间,支持事务,消息订阅

Springboot缓存

SpringBoot支持很多种缓存方式:redis、guava、ehcahe、jcache等等。
缓存注解详解

@CacheConfig

主要用于配置该类中会用到的一些共用的缓存配置。 在这里@CacheConfig(cacheNames = “users”):配置了该数据访问对象中返回的内容将存储于名为users的缓存对象中,我们也可以不使用该注解,直接通过@Cacheable自己配置缓存集的名字来定义。

@Cacheable

配置了findByName函数的返回值将被加入缓存。同时在查询时,会先从缓存中获取,若不存在才再发起对数据库的访问。
注解参数:

value、cacheNames:两个等同的参数(cacheNames为Spring 4新增,作为value的别名),用于指定缓存组件的名字,数组形式。由于Spring 4中新增了@CacheConfig,因此在Spring 3中原本必须有的value属性,也成为非必需项了

key:缓存对象存储在Map集合中的key值,非必需,缺省按照函数的所有参数组合作为key值,若自己配置需使用SpEL表达式,比如:编写SpEL; #id,参数id的值 ,,#a0(第一个参数), #p0(和a0的一样的意义) ,#root.args[0]

condition:缓存对象的条件,非必需,也需使用SpEL表达式,只有满足表达式条件的内容才会被缓存,比如:@Cacheable(key = “#p0”, condition = “#p0.length() < 3”),表示只有当第一个参数的长度小于3的时候才会被缓存,若做此配置上面的AAA用户就不会被缓存,读者可自行实验尝试。

unless:另外一个缓存条件参数,非必需,需使用SpEL表达式。它不同于condition参数的地方在于它的判断时机,该条件是在函数被调用之后才做判断的,所以它可以通过对result进行判断。

keyGenerator:用于指定key生成器,非必需。若需要指定一个自定义的key生成器,我们需要去实现org.springframework.cache.interceptor.KeyGenerator接口,并使用该参数来指定。需要注意的是:key/keyGenerator:二选一使用;不能同时使用

cacheManager:用于指定使用哪个缓存管理器,非必需。只有当有多个时才需要使用

cacheResolver:用于指定使用那个缓存解析器,非必需。需通过org.springframework.cache.interceptor.CacheResolver接口来实现自己的缓存解析器,并用该参数指定。

sync:是否使用异步模式

@CachePut

配置于函数上,能够根据参数定义条件来进行缓存,它与@Cacheable不同的是,它每次都会真是调用函数,所以主要用于数据新增和修改操作上。 它的参数与@Cacheable类似,具体功能可参考上面对@Cacheable参数的解析
@CacheEvict

配置于函数上,通常用在删除方法上,用来从缓存中移除相应数据。也就是清除缓存除了同@Cacheable一样的参数之外,它还有下面两个参数:

allEntries:非必需,默认为false。当为true时,会移除所有数据

beforeInvocation:非必需,**默认为false,会在调用方法之后移除数据。**当为true时,会在调用方法之前移除数据。

@Caching注解

用于定义复杂的缓存规则,可以集成@Cacheable和 @CachePut

// @Caching 定义复杂的缓存规则
    @Caching(
            cacheable = {
                    @Cacheable(/*value={"emp"},*/key = "#lastName")
            },
            put = {
                    @CachePut(/*value={"emp"},*/key = "#result.id"),
                    @CachePut(/*value={"emp"},*/key = "#result.email")
            }
    )
    public Employee getEmpByLastName(String lastName){
        return employeeMapper.getEmpByLastName(lastName);
    }

SpEL表达式用法

在这里插入图片描述

Spring Boot 整合 缓存开发

相关注解

(1)缓存@Cacheable
根据方法对其返回结果进行缓存,下次请求时,如果缓存存在,则直接读取缓存数据返回;如果缓存不
存在,则执行方法,并把返回的结果存入缓存中。一般用在查询方法上。
查看源码,属性值如下
在这里插入图片描述
(2)缓存@CachePut
使用该注解标志的方法,每次都会执行,并将结果存入指定的缓存中。其他方法可以直接从响应的缓存
中读取缓存数据,而不需要再去查询数据库。一般用在新增方法上。
查看源码,属性值如下:
在这里插入图片描述
(3)缓存@CacheEvict
使用该注解标志的方法,会清空指定的缓存。一般用在更新或者删除方法上
查看源码,属性值如下:
在这里插入图片描述

相关配置
 <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>


#数据库连接
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/mytest_springboot_cache?useUnicode=true
    driver-class-name: com.mysql.jdbc.Driver
    username: root
    password: lzh
 
  ## Redis 配置
  redis:
    ## Redis数据库索引(默认为0)
    database: 0
    ## Redis服务器地址
    host: 192.168.126.129
    ## Redis服务器连接端口
    port: 6379
    ## Redis服务器连接密码(默认为空)
    password:
    jedis:
      pool:
        ## 连接池最大连接数(使用负值表示没有限制)
        #spring.redis.pool.max-active=8
        max-active: 8
        ## 连接池最大阻塞等待时间(使用负值表示没有限制)
        #spring.redis.pool.max-wait=-1
        max-wait: -1
        ## 连接池中的最大空闲连接
        #spring.redis.pool.max-idle=8
        max-idle: 8
        ## 连接池中的最小空闲连接
        #spring.redis.pool.min-idle=0
        min-idle: 0
    ## 连接超时时间(毫秒)
    timeout: 1200

Redis集群配置

spring:
  redis:
    cluster:
      nodes:
        - 192.168.1.236:7001
        - 192.168.1.236:7002
        - 192.168.1.236:7003
        - 192.168.1.244:7004
        - 192.168.1.244:7005
        - 192.168.1.244:7006
      max-redirects: 3  # 获取失败 最大重定向次数
    pool:
      max-active: 1000  # 连接池最大连接数(使用负值表示没有限制)
      max-idle: 10    # 连接池中的最大空闲连接
      max-wait: -1   # 连接池最大阻塞等待时间(使用负值表示没有限制)
      min-idle:  5     # 连接池中的最小空闲连接
    timeout: 6000  # 连接超时时长(毫秒)

编写java配置类
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {
 
    /**
     * 选择redis作为默认缓存工具
     * @param redisConnectionFactory
     * @return
     */
    /*@Bean
    //springboot 1.xx
    public CacheManager cacheManager(RedisTemplate redisTemplate) {
        RedisCacheManager rcm = new RedisCacheManager(redisTemplate);
        return rcm;
    }*/
    @Bean
    public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
        RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofHours(1)); // 设置缓存有效期一小时
        return RedisCacheManager
                .builder(RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory))
                .cacheDefaults(redisCacheConfiguration).build();
    }
 
    /**
     * retemplate相关配置
     * @param factory
     * @return
     */
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
 
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        // 配置连接工厂
        template.setConnectionFactory(factory);
 
        //使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值(默认使用JDK的序列化方式)
        Jackson2JsonRedisSerializer jacksonSeial = new Jackson2JsonRedisSerializer(Object.class);
 
        ObjectMapper om = new ObjectMapper();
        // 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和public
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        // 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer等会跑出异常
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jacksonSeial.setObjectMapper(om);
 
        // 值采用json序列化
        template.setValueSerializer(jacksonSeial);
        //使用StringRedisSerializer来序列化和反序列化redis的key值
        template.setKeySerializer(new StringRedisSerializer());
 
        // 设置hash key 和value序列化模式
        template.setHashKeySerializer(new StringRedisSerializer());
        template.setHashValueSerializer(jacksonSeial);
        template.afterPropertiesSet();
 
        return template;
    }
 
    /**
     * 对hash类型的数据操作
     *
     * @param redisTemplate
     * @return
     */
    @Bean
    public HashOperations<String, String, Object> hashOperations(RedisTemplate<String, Object> redisTemplate) {
        return redisTemplate.opsForHash();
    }
 
    /**
     * 对redis字符串类型数据操作
     *
     * @param redisTemplate
     * @return
     */
    @Bean
    public ValueOperations<String, Object> valueOperations(RedisTemplate<String, Object> redisTemplate) {
        return redisTemplate.opsForValue();
    }
 
    /**
     * 对链表类型的数据操作
     *
     * @param redisTemplate
     * @return
     */
    @Bean
    public ListOperations<String, Object> listOperations(RedisTemplate<String, Object> redisTemplate) {
        return redisTemplate.opsForList();
    }
 
    /**
     * 对无序集合类型的数据操作
     *
     * @param redisTemplate
     * @return
     */
    @Bean
    public SetOperations<String, Object> setOperations(RedisTemplate<String, Object> redisTemplate) {
        return redisTemplate.opsForSet();
    }
 
    /**
     * 对有序集合类型的数据操作
     *
     * @param redisTemplate
     * @return
     */
    @Bean
    public ZSetOperations<String, Object> zSetOperations(RedisTemplate<String, Object> redisTemplate) {
        return redisTemplate.opsForZSet();
    }
}

这里主要是使用RedisTemplate来对远程redis操作,每次访问controller暴露的接口,首先判断redis缓存中是否存在该数据,若不存在就从数据库中读取数据,然后保存到redis缓存中,当下次访问的时候,就直接从缓存中取出来。这样就不用每次都执行sql语句,能够提高访问速度。 但是在保存数据到缓存中,通过设置键和值和超时删除,注意设置超时删除缓存时间不要太长,否则会给服务器带来压力。

也可以使用注解的形式,使用方式和Ehcache的使用方式一致。

其他Redis配置
/**
 * @Description: redis配置文件
 * @Author: xudada
 * @Date: 2022-8-03 20:46
 */
@EnableCaching //开启缓存
@Configuration  //配置类
public class RedisConfig extends CachingConfigurerSupport {

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        RedisSerializer<String> redisSerializer = new StringRedisSerializer();
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        template.setConnectionFactory(factory);
        //key序列化方式
        template.setKeySerializer(redisSerializer);
        //value序列化
        template.setValueSerializer(jackson2JsonRedisSerializer);
        //value hashmap序列化
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        return template;
    }

    @Bean
    public CacheManager cacheManager(RedisConnectionFactory factory) {
        RedisSerializer<String> redisSerializer = new StringRedisSerializer();
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        //解决查询缓存转换异常的问题
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        // 配置序列化(解决乱码的问题),过期时间600秒
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofSeconds(600))
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))
                .disableCachingNullValues();
        RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
                .cacheDefaults(config)
                .build();
        return cacheManager;
    }
}

在service上加返回的数据会保存倒redis通过注解@Cacheable进行配置
@Service
public class CrmBannerServiceImpl extends ServiceImpl<CrmBannerMapper, CrmBanner>
implements CrmBannerService {
@Cacheable(value = "banner", key = "'selectIndexList'")
@Override
public List<CrmBanner> selectIndexList() {
List<CrmBanner> list = baseMapper.selectList(new
QueryWrapper<CrmBanner>().orderByDesc("sort"));
return list;
 }
@Override
public void pageBanner(Page<CrmBanner> pageParam, Object o) {
baseMapper.selectPage(pageParam,null);
 }
@Override
public CrmBanner getBannerById(String id) {
return baseMapper.selectById(id);
 }
@CacheEvict(value = "banner", allEntries=true)
@Override
public void saveBanner(CrmBanner banner) {
baseMapper.insert(banner);
 }

@CacheEvict(value = "banner", allEntries=true)
@Override
public void updateBannerById(CrmBanner banner) {
baseMapper.updateById(banner);
 }
@CacheEvict(value = "banner", allEntries=true)
@Override
public void removeBannerById(String id) {
baseMapper.deleteById(id);
 }
}

案例

@Service
public class CrmBannerServiceImpl extends ServiceImpl<CrmBannerMapper, CrmBanner> implements CrmBannerService {

    /**
     * 查询所有轮播图,并存入缓存中做为热数据
     * @return
     */
    @Cacheable(value = "banner",key = "'selectIndexList'")//存放在缓存中
    @Override
    public List<CrmBanner> selectBanner() {
        //根据id进行降序排序,显示排列后前两条记录
        QueryWrapper wrapper = new QueryWrapper();
        wrapper.orderByAsc("sort");
        List<CrmBanner> list = baseMapper.selectList(wrapper);
        return list;
    }
}

结果
在这里插入图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: Spring Boot是一个开源的Java开发框架,它简化了Java应用程序的开发过程。它提供了一系列的工具、库和约定,使得开发人员可以轻松地构建独立的、可执行的、可部署的Spring应用程序。 Vue是一个渐进式的JavaScript框架,用于构建用户界面。它提供了一些先进的特性,如数据绑定、组件化和虚拟DOM,使得开发人员能够更高效地构建交互式的Web应用程序。 Redis是一个开源的内存数据库,它提供了丰富的数据结构和功能,如字符串、哈希、列表、集合和有序集合。它被广泛用于缓存、会话管理和消息队列等场景,可以大大提高应用程序的性能和可扩展性。 结合使用Spring Boot、Vue和Redis可以构建一个强大的Web应用程序。Spring Boot提供了简化开发和部署的能力,Vue提供了灵活、高效的前端开发框架,而Redis提供了高性能的数据存储和访问能力。 使用Spring Boot和Vue可以实现前后端分离的开发模式,前后端可以独立开发和部署。通过调用Spring Boot的RESTful接口,Vue可以获取、修改和展示数据。此外,Vue的SPA(单页应用)特性可以使得应用程序更加流畅和用户友好。 而Redis可以用作应用程序的缓存层,存储常用、频繁访问的数据,从而减轻数据库的负载,提高响应速度。同时,Redis还可以用作分布式锁和消息队列,使应用程序更加健壮和可靠。 总之,Spring Boot、Vue和Redis的结合可以提供一个高效、可伸缩的Web开发解决方案。通过合理地利用它们的特性和功能,开发人员可以构建出功能丰富、性能优异的Web应用程序。 ### 回答2: Spring Boot是一个开源的Java开发框架,它简化了Java应用程序的开发过程。它基于Spring框架,提供了自动化配置和默认值设置,使得开发人员可以更加快速、简便地构建可独立运行的、生产级别的Spring应用程序。 Vue是一个开源的JavaScript框架,用于构建用户界面。与传统的JavaScript开发方式相比,Vue采用了响应式数据绑定和组件化的开发方式,使得开发者可以更加高效地构建交互式的前端界面。 Redis是一个开源的内存数据库,它支持多种数据结构的存储和操作。Redis具有高性能的特点,可以有效地存储和访问大量的数据。它还提供了多种数据操作命令和集群部署方案,供开发人员使用。 将这三个技术结合在一起可以带来一些好处。首先,Spring Boot提供了对Redis的集成支持,使得开发人员可以方便地使用Redis进行缓存和数据存储。这可以提高应用程序的性能和响应速度。 其次,Vue可以通过Ajax和后端的Spring Boot应用程序进行交互。Vue的组件化开发方式使得前端界面的开发更加模块化和可维护。开发人员可以使用Vue的响应式数据绑定和组件通信机制,实现复杂的用户界面交互逻辑。 最后,Redis的高性能和多种数据结构的支持可以为应用程序提供强大的数据存储和缓存能力。开发人员可以使用Redis提供的命令进行数据操作,例如设置、获取和删除数据,以及对数据进行排序和计数等操作。 综上所述,结合Spring Boot、Vue和Redis可以构建高效、可靠的应用程序。使用Spring Boot进行后端开发,Vue进行前端开发,同时利用Redis提供的缓存和数据存储能力,可以使得应用程序的开发过程更加简单和高效,同时提高应用程序的性能和用户体验。 ### 回答3: Spring Boot是一个基于Spring框架的快速开发框架,它通过简化配置和自动化功能来提高开发效率。它集成了许多常用的开发工具和组件,提供了快速构建和部署应用程序的能力。Vue是一个前端框架,它可以通过编写组件化的界面来开发用户界面。Redis是一个内存数据库,它可以用来缓存数据,提高应用程序的性能。 通过结合使用Spring Boot、Vue和Redis,可以实现一个强大的Web应用程序。首先,使用Spring Boot提供的快速开发能力来构建后端逻辑和API接口。Spring Boot具有良好的松耦合性和高度灵活性,可以轻松集成各种其他组件和技术,比如数据库访问、安全认证等。 然后,在前端部分使用Vue来构建用户界面。Vue的组件化开发模式使得开发者可以将界面划分为多个独立的组件,每个组件负责特定的功能和视图。这样可以实现更好的代码重用和维护性,并提供良好的用户体验。 最后,使用Redis缓存数据以提高应用程序的性能。Redis具有快速的读写能力,并支持多种数据结构的存储,如字符串、列表、哈希等。通过将经常访问的数据存储到Redis中,可以减少数据库的访问次数,从而加快应用程序的响应速度。 综上所述,通过结合使用Spring Boot、Vue和Redis,可以构建一个高效、可扩展的Web应用程序。Spring Boot提供了快速开发和集成能力,Vue提供了优秀的用户界面开发方式,而Redis可以提供高速的数据缓存能力。这样的技术组合可以满足现代Web应用程序对性能和可靠性的要求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员小徐同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值