关于redis:SpringBoot234整合Redis实现缓存

文章次要内容

一、SpringCache 介绍

二、SpringCache 注解

三、注解形式实现Redis缓存(Windows版Redis)

四、RedisUtils工具类原生形式实现Redis缓存(Windows版Redis)

一、SpringCache介绍

官网文档地址:https://docs.spring.io/spring…

在Spring Boot中,数据的缓存治理存储依赖于Spring框架中cache相干的org.springframework.cache.Cache和org.springframework.cache.CacheManager缓存管理器接口。

如果程序中没有定义类型为CacheManager的Bean组件或者是名为cacheResolver的CacheResolver缓存解析器,Spring Boot将尝试抉择并启用以下缓存组件(依照指定的程序):

(1)Generic

(2)JCache (JSR-107)(EhCache 3、Hazelcast、Infinispan等)

(3)EhCache 2.x

(4)Hazelcast

(5)Infinispan

(6)Couchbase

(7)Redis

(8)Caffeine

(9)Simple

下面依照Spring Boot缓存组件的加载程序,列举了反对的9种缓存组件,在我的项目中增加某个缓存治理组件(例如Redis)后,Spring Boot我的项目会抉择并启用对应的缓存管理器。如果我的项目中同时增加了多个缓存组件,且没有指定缓存管理器或者缓存解析器(CacheManager或者cacheResolver),那么Spring Boot会依照上述程序在增加的多个缓存中优先启用指定的缓存组件进行缓存治理。

Spring Boot默认缓存治理中,没有增加任何缓存治理组件能实现缓存治理。这是因为开启缓存治理后,Spring Boot会依照上述列表程序查找无效的缓存组件进行缓存治理,如果没有任何缓存组件,会默认应用最初一个Simple缓存组件进行治理。Simple缓存组件是Spring Boot默认的缓存治理组件,它默认应用内存中的ConcurrentMap进行缓存存储,所以在没有增加任何第三方缓存组件的状况下,能够实现内存中的缓存治理,然而咱们不举荐应用这种缓存治理形式

当在Spring Boot默认缓存治理的根底上引入Redis缓存组件,即在pom.xml文件中增加Spring Data Redis依赖启动器后,SpringBoot会应用RedisCacheConfigratioin当做失效的主动配置类进行缓存相干的主动拆卸,容器中应用的缓存管理器是RedisCacheManager, 这个缓存管理器创立的Cache为 RedisCache, 进而操控redis进行数据的缓存

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

核心思想:当咱们调用一个办法时会把该办法的参数和返回后果最为一个键值对寄存在缓存中,等下次利用同样的参数来调用该办法时将不会再执行,而是间接从缓存中获取后果进行返回。

了解:springboot 的缓存机制是通过切面编程 aop来实现的

二、SpringCache 注解

Spring Cache 提供了 @Cacheable 、@CachePut 、@CacheEvict 、@Caching 等注解,在办法上应用。

基于注解形式SpringCache引入Redis做缓存,须要先理解@EnableCaching、@CacheConfig、@Cacheable、@CachePut、@CacheEvict、@Caching相干注解的应用

1、@EnableCaching

开启缓存性能,个别放在启动类上或者自定义的RedisConfig配置类上。

2、@CacheConfig

当咱们须要缓存的中央越来越多,能够应用@CacheConfig(cacheNames = “cacheName”)注解在 class 之上来对立指定value的值,对立治理keys,这时可省略value,如果你在你的办法仍旧写上了value,那么仍然以办法的value值为准。

示例:

@Service
@CacheConfig(cacheNames = "categories")
public class CategoryServiceImpl implements CategoryService{
 
    ......
}

3、@Cacheable

依据办法对其返回后果进行缓存,下次申请时,如果缓存存在,则间接读取缓存数据返回;如果缓存不存在,则执行办法,并把返回的后果存入缓存中。个别用在查询方法上。 查看源码,属性值如下:

属性/办法名 解释
value 缓存名,指定了缓存寄存在哪块命名空间(必须)
cacheNames 与value差不多,二选一即可
key 缓存的key,能够应用SPEL标签自定义缓存的key
keyGenerator key的生存器。key/keyGenerator二选一应用
cacheManager 指定缓存管理器
cacheResolver 指定获取解析器
condition 条件合乎则缓存
unless 条件合乎则不缓存
sync 是否应用异步模式,默认为false

4、@CachePut

应用该注解标记的办法,每次都会执行,并将后果存入指定的缓存中。其余办法能够间接从响应的缓存中读取缓存数据,而不须要再去查询数据库。个别用在新增办法上。 查看源码,属性值同上@Cacheable差不多

5、@CacheEvict

应用该注解标记的办法,会清空指定的缓存。个别用在更新或者删除办法上

查看源码,属性值与@Cacheable差不多,独有的两个属性如下:

属性/办法名 解释
allEntries 是否清空所有缓存,默认为false。如果指定为true,则办法调用后将立刻清空所有的缓存
beforeInvocation 是否在办法执行前就清空所有缓存,默认为false。如果指定为true,则办法执行前就会清空所有的缓存

6、@Caching

该注解能够实现同一个办法上同时应用多种注解。可从其源码看出:

public @interface Caching {
    
    Cacheable[] cacheable() default {};
    CachePut[] put() default {};
    CacheEvict[] evict() default {};
}

三、注解形式实现Redis缓存(Windows版Redis)

1、数据库及数据环境筹备

CREATE DATABASE `redistest`CHARACTER SET utf8 COLLATE utf8_general_ci; 
USE `redistest`; 

CREATE TABLE `user`(
  id INT(11)NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(255)DEFAULT NULL,
  `password` VARCHAR(255)DEFAULT NULL,
  PRIMARY KEY(id)
)ENGINE=INNODB DEFAULT CHARSET=utf8;

INSERT INTO `user` VALUES(1,'张三',"123456789");
INSERT INTO `user` VALUES(2,'李四',"asdfghj");
INSERT INTO `user` VALUES(3,'王麻子',"kjfdskjf");
INSERT INTO `user` VALUES(4,'小明',"hellorworld");
INSERT INTO `user` VALUES(5,'李华',"redis");

2、构建一个SpringBoot我的项目,勾选相应的模块,增加Pom依赖

增加其余的Pom依赖

<!-- mybatis 长久层-->
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.1.1</version>
</dependency>

3、application.properties配置文件

# ============数据库============
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/redistest?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
spring.datasource.username=root
spring.datasource.password=admin

# ============mybatis============
mybatis.mapper-locations=classpath:/mapper/*.xml
mybatis.type-aliases-package=com.cqy.pojo
mybatis.configuration.map-underscore-to-camel-case=true
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

# ============redis============
# 默认是应用0号数据库,这里咱们应用1号,笔者当初0号有其余数据- -
spring.redis.database=1 
spring.redis.host=localhost
spring.redis.port=6379
# 默认明码为空
spring.redis.password=
# 连接池最大连接数
spring.redis.lettuce.pool.max-active=8
# 连接池最大阻塞等待时间
spring.redis.lettuce.pool.max-wait=-1ms
# 连接池中的最大闲暇连贯
spring.redis.lettuce.pool.max-idle=8
# 连接池中的最小闲暇连贯
spring.redis.lettuce.pool.min-idle=0

4、pojo实体类

@AllArgsConstructor
@NoArgsConstructor
@Data
public class User {
    
    private int id;
    private String name;
    private String password;
}

5、dao层的Mapper接口

@Repository
@Mapper
public interface UserMapper {

    /**
     * 减少
     * @param user
     * @return
     */
    public int addUser(User user);

    /**
     * 删除
     * @param id
     * @return
     */
    public int deleteUser(@Param("id") int id);

    /**
     * 批改
     * @param user
     * @return
     */
    public int updateUser(User user);

    /**
     * 查问获取所有User对象
     * @return
     */
    public List<User> selectUser();

    /**
     * 依据id查问获取某个User对象
     * @param id
     * @return
     */
    public User selectUserById(@Param("id") int id);
    
    /**
     * 查问一共有几条数据
     * @return
     */
    public int countUser();
}

6、Mapper接口对应的Mapper.xml文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.cqy.dao.UserMapper">

    <insert id="addUser" parameterType="user">
        insert into `user` (`name`,password) values (#{name},#{password})
    </insert>

    <delete id="deleteUser" parameterType="_int">
        delete from `user` where id =#{id}
    </delete>

    <update id="updateUser" parameterType="user">
        update `user` set `name`=#{name},password=#{password} where id=#{id}
    </update>

    <select id="selectUser" resultType="user">
        select * from `user`
    </select>

    <select id="selectUserById" parameterType="_int" resultType="user">
        select * from `user` where id =#{id}
    </select>
    
    <select id="countUser" resultType="_int">
        select count(*) from `user`
    </select>

</mapper>

7、UserService和UserServiceImpl

UserService接口同UserMapper的内容一样,略。

UserServiceImpl:

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    UserMapper userMapper;

    @Override
    public int addUser(User user) {
        return userMapper.addUser(user);
    }

    @Override
    public int deleteUser(int id) {
        return userMapper.deleteUser(id);
    }

    @Override
    public int updateUser(User user) {
        return userMapper.updateUser(user);
    }

    @Override
    public List<User> selectUser() {
        return userMapper.selectUser();
    }

    @Override
    public User selectUserById(int id) {
        return userMapper.selectUserById(id);
    }
    
    @Override
    public int countUser() {
        return userMapper.countUser();
    }
}

8、单元测试简略的CRUD是否胜利

@SpringBootTest
class RedisTestSpringbootApplicationTests {

    @Autowired
    UserService userService;

    @Test
    void test() {
        List<User> users = userService.selectUser();
        for (User user : users) {
            System.out.println(user);
        }
    }
}

发现报错:

解决:增加Pom依赖

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
    <version>2.8.0</version>
</dependency>

9、构建RedisConfig配置类

通常咱们都应用Json序列化后存入Redis,而SpringBoot1.x和SpringBoot2.x版本在自定义CacheManager有很大的区别,须要自行研读源码。

在此简略阐明,但不做源码详细分析。

在SpringBoot1.x中,RedisCacheManager是能够应用RedisTemplate作为参数注入的

  @Bean
    public CacheManager cacheManager(RedisTemplate redisTemplate) {
        RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);
        return cacheManager;
    } 

但在SpringBoot2.x中,有很大的不同,RedisCacheManager结构器如下,曾经无奈再应用RedisTemplate进行结构

官网文档中:

阐明当初配置RedisCacheManager须要一个RedisCacheConfiguration来作为配置对象,通过RedisCacheConfiguration这个对象来指定对应的序列化策略

SpringBoot2.x后自定义CacheManager有多种形式,笔者此处间接给出本人所用的一种。其余的构建办法,可自行百度,有很多办法。

@Configuration
@SuppressWarnings("all")
@EnableCaching
public class RedisConfig {

    @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);

        // 配置序列化(解决乱码的问题)
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofDays(1))
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))
                .disableCachingNullValues();

        RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
                .cacheDefaults(config)
                .build();
        return cacheManager;
    }
}

RedisConfig的json序列化配置文章参考:

1、https://blog.csdn.net/weixin_…

2、https://blog.csdn.net/qq_4153…

10、在UserServiceImpl应用注解进行Redis缓存

留神:须要先在RedisConfig加上@EnableCaching,示意开启缓存性能

@Service
@CacheConfig(cacheNames = "user")
public class UserServiceImpl implements UserService {

    @Autowired
    UserMapper userMapper;

    @Override
    @CachePut(key = "'user-id-'+ #user.id")
    public int addUser(User user) {
        System.out.println("写入缓存");
        return userMapper.addUser(user);
    }

    @Override
    @CacheEvict(key = "'user-id-'+#p0")//依据key革除缓存,个别该注解标注在批改和删除办法上
    public int deleteUser(int id) {
        return userMapper.deleteUser(id);
    }

    @Override
    @CacheEvict(key = "'user-id-'+#user.id")//依据key革除缓存,个别该注解标注在批改和删除办法上
    public int updateUser(User user) {
        System.out.println("更新数据并革除之前的缓存");
        return userMapper.updateUser(user);
    }

    @Override
    @Cacheable(cacheNames = "userList") // 标记读取缓存操作,如果缓存不存在,则调用指标办法,并将后果放入缓存
    public List<User> selectUser() {
        System.out.println("缓存不存在,执行办法");
        return userMapper.selectUser();
    }

    @Override
    @Cacheable(key = "'user-id-'+#p0")
    public User selectUserById(int id) {
        System.out.println("缓存不存在,执行办法");
        return userMapper.selectUserById(id);
    }
}

其中#p0是指的第一个参数,#p1是第二个参数,以此类推。

11、单元测试查看缓存

启动redis-server和RedisDesktopManager

运行单元测试,管理工具查看缓存

@SpringBootTest
class RedisTestSpringbootApplicationTests {

    @Autowired
    UserService userService;

    @Test
    void select() {
        List<User> users = userService.selectUser();
        for (User user : users) {
            System.out.println(user);
        }
    }

    @Test
    void selectById() {
        User users = userService.selectUserById(3);
        System.out.println(users);
    }

    @Test
    void add() {
        userService.addUser(new User(6,"小红","56458848"));
    }

    @Test
    void update() {
        userService.updateUser(new User(6,"纸飞机","1111111"));
    }

    @Test
    void delete() {
        userService.deleteUser(6);
    }
}

四、RedisUtils工具类原生形式实现Redis缓存(Windows版Redis)

应用SpringCache的注解形式实现Redis缓存,底层逻辑原理其实就是Redis的set、get命令操作key-value,将操作返回的后果存到Redis中,下次执行同样操作的时候,进行判断逻辑看Redis中是否有值,存在的话就间接从Redis中拿value,实现缓存成果。

因而,咱们可间接利用RedisUtils的形式,进行逻辑的set、get实现缓存。这种形式很多时候序列化和key的设置都绝对更灵便一些,但绝对也较简单一些。

1、数据库及数据环境筹备

2、构建一个SpringBoot我的项目,勾选相应的模块,增加Pom依赖

3、application.properties配置文件

4、pojo实体类

5、dao层的Mapper接口

6、Mapper接口对应的Mapper.xml文件

7、UserService和UserServiceImpl

8、单元测试简略的CRUD是否胜利

以上步骤都同第三局部一样,不再赘述。

9、构建RedisConfig配置类

RedisConfig中自定义redisTemplate的bean

@Configuration
@SuppressWarnings("all")
public class RedisConfig {


    @Bean(name="myredisTemplate")
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(factory);
        //Json序列化设置
        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        //通过ObjectMapper本义json
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
        //String类型的序列化
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        //key采纳String的序列化形式
        template.setKeySerializer(stringRedisSerializer);
        //hash的key也采纳String的序列化形式
        template.setHashKeySerializer(stringRedisSerializer);
        //value的序列化形式采纳jackson
        template.setValueSerializer(jackson2JsonRedisSerializer);
        //hash的value序列化形式采纳jackson
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        template.afterPropertiesSet();
        return template;
    }
}

10、RedisUtils封装工具类筹备


@Component
public class RedisUtils {

    @Autowired
    @Qualifier("myredisTemplate")
    private RedisTemplate<String,Object> redisTemplate;

    // =============================common============================
    /**
     * 指定缓存生效工夫
     * @param key 键
     * @param time 工夫(秒)
     * @return
     */
    public boolean expire(String key,long time){
        try {
            if (time > 0){
                redisTemplate.expire(key,time, TimeUnit.SECONDS);
            }
            return true;
        } catch (Exception e){
            e.printStackTrace();
            return false;
        }
    }


    /**
     * 依据key获取过期工夫
     * @param key 键  不能为null
     * @return 工夫(秒) 返回0代表为永恒无效
     */
    public long getExpire(String key){
        return redisTemplate.getExpire(key,TimeUnit.SECONDS);
    }




    /**
     * 判断key是否存在
     * @param key  键
     * @return  true的话存在,false不存在
     */
    public boolean hasKey(String key){
        try {
            return redisTemplate.hasKey(key);
        } catch (Exception e){
            e.printStackTrace();
            return false;
        }
    }


    /**
     * 删除缓存
     * @param key  能够传一个key或多个key
     */
    @SuppressWarnings("unchecked")
    public void del(String... key){
        if (key!=null && key.length>0){
            if (key.length==1){
                redisTemplate.delete(key[0]);
            } else {
                redisTemplate.delete(CollectionUtils.arrayToList(key));
            }
        }
    }


    // ============================String=============================


    /**
     * 一般缓存获取
     * @param key 键
     * @return 值
     */
    public Object get(String key) {
        return key == null ? null : redisTemplate.opsForValue().get(key);
    }


    /**
     * 一般缓存放入
     * @param key   键
     * @param value 值
     * @return true胜利 false失败
     */
    public boolean set(String key, Object value) {
        try {
            redisTemplate.opsForValue().set(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }


    /**
     * 一般缓存放入并设置工夫
     * @param key   键
     * @param value 值
     * @param time  工夫(秒) time要大于0 如果time小于等于0 将设置无限期
     * @return true胜利 false 失败
     */
    public boolean set(String key, Object value, long time) {
        try {
            if (time > 0) {
                redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
            } else {
                set(key, value);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }


    /**
     * 递增
     * @param key   键
     * @param delta 要减少几(大于0)
     */
    public long incr(String key, long delta) {
        if (delta < 0) {
            throw new RuntimeException("递增因子必须大于0");
        }
        return redisTemplate.opsForValue().increment(key, delta);
    }


    /**
     * 递加
     * @param key   键
     * @param delta 要缩小几(小于0)
     */
    public long decr(String key, long delta) {
        if (delta < 0) {
            throw new RuntimeException("递加因子必须大于0");
        }
        return redisTemplate.opsForValue().increment(key, -delta);
    }


    // ================================HashMap=================================


    /**
     * HashGet
     * @param key  键 不能为null
     * @param item 项 不能为null
     */
    public Object hget(String key, String item) {
        return redisTemplate.opsForHash().get(key, item);
    }


    /**
     * 获取hashKey对应的所有键值
     * @param key 键
     * @return 对应的多个键值
     */
    public Map<Object, Object> hmget(String key) {
        return redisTemplate.opsForHash().entries(key);
    }


    /**
     * HashSet
     * @param key 键
     * @param map 对应多个键值
     */
    public boolean hmset(String key, Map<String, Object> map) {
        try {
            redisTemplate.opsForHash().putAll(key, map);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }


    /**
     * HashSet 并设置工夫
     * @param key  键
     * @param map  对应多个键值
     * @param time 工夫(秒)
     * @return true胜利 false失败
     */
    public boolean hmset(String key, Map<String, Object> map, long time) {
        try {
            redisTemplate.opsForHash().putAll(key, map);
            if (time > 0) {
                expire(key, time);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }


    /**
     * 向一张hash表中放入数据,如果不存在将创立
     *
     * @param key   键
     * @param item  项
     * @param value 值
     * @return true 胜利 false失败
     */
    public boolean hset(String key, String item, Object value) {
        try {
            redisTemplate.opsForHash().put(key, item, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }


    /**
     * 向一张hash表中放入数据,如果不存在将创立
     *
     * @param key   键
     * @param item  项
     * @param value 值
     * @param time  工夫(秒) 留神:如果已存在的hash表有工夫,这里将会替换原有的工夫
     * @return true 胜利 false失败
     */
    public boolean hset(String key, String item, Object value, long time) {
        try {
            redisTemplate.opsForHash().put(key, item, value);
            if (time > 0) {
                expire(key, time);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }


    /**
     * 删除hash表中的值
     *
     * @param key  键 不能为null
     * @param item 项 能够使多个 不能为null
     */
    public void hdel(String key, Object... item) {
        redisTemplate.opsForHash().delete(key, item);
    }


    /**
     * 判断hash表中是否有该项的值
     *
     * @param key  键 不能为null
     * @param item 项 不能为null
     * @return true 存在 false不存在
     */
    public boolean hHasKey(String key, String item) {
        return redisTemplate.opsForHash().hasKey(key, item);
    }


    /**
     * hash递增 如果不存在,就会创立一个 并把新增后的值返回
     *
     * @param key  键
     * @param item 项
     * @param by   要减少几(大于0)
     */
    public double hincr(String key, String item, double by) {
        return redisTemplate.opsForHash().increment(key, item, by);
    }


    /**
     * hash递加
     *
     * @param key  键
     * @param item 项
     * @param by   要缩小记(小于0)
     */
    public double hdecr(String key, String item, double by) {
        return redisTemplate.opsForHash().increment(key, item, -by);
    }


    // ============================set=============================


    /**
     * 依据key获取Set中的所有值
     * @param key 键
     */
    public Set<Object> sGet(String key) {
        try {
            return redisTemplate.opsForSet().members(key);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }


    /**
     * 依据value从一个set中查问,是否存在
     *
     * @param key   键
     * @param value 值
     * @return true 存在 false不存在
     */
    public boolean sHasKey(String key, Object value) {
        try {
            return redisTemplate.opsForSet().isMember(key, value);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }


    /**
     * 将数据放入set缓存
     *
     * @param key    键
     * @param values 值 能够是多个
     * @return 胜利个数
     */
    public long sSet(String key, Object... values) {
        try {
            return redisTemplate.opsForSet().add(key, values);
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }


    /**
     * 将set数据放入缓存
     *
     * @param key    键
     * @param time   工夫(秒)
     * @param values 值 能够是多个
     * @return 胜利个数
     */
    public long sSetAndTime(String key, long time, Object... values) {
        try {
            Long count = redisTemplate.opsForSet().add(key, values);
            if (time > 0)
                expire(key, time);
            return count;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }


    /**
     * 获取set缓存的长度
     *
     * @param key 键
     */
    public long sGetSetSize(String key) {
        try {
            return redisTemplate.opsForSet().size(key);
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }


    /**
     * 移除值为value的
     *
     * @param key    键
     * @param values 值 能够是多个
     * @return 移除的个数
     */


    public long setRemove(String key, Object... values) {
        try {
            Long count = redisTemplate.opsForSet().remove(key, values);
            return count;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    // ===============================list=================================


    /**
     * 获取list缓存的内容
     *
     * @param key   键
     * @param start 开始
     * @param end   完结 0 到 -1代表所有值
     */
    public List<Object> lGet(String key, long start, long end) {
        try {
            return redisTemplate.opsForList().range(key, start, end);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }


    /**
     * 获取list缓存的长度
     *
     * @param key 键
     */
    public long lGetListSize(String key) {
        try {
            return redisTemplate.opsForList().size(key);
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }


    /**
     * 通过索引 获取list中的值
     *
     * @param key   键
     * @param index 索引 index>=0时, 0 表头,1 第二个元素,顺次类推;index<0时,-1,表尾,-2倒数第二个元素,顺次类推
     */
    public Object lGetIndex(String key, long index) {
        try {
            return redisTemplate.opsForList().index(key, index);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }


    /**
     * 将list放入缓存
     *
     * @param key   键
     * @param value 值
     */
    public boolean lSet(String key, Object value) {
        try {
            redisTemplate.opsForList().rightPush(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }


    /**
     * 将list放入缓存
     * @param key   键
     * @param value 值
     * @param time  工夫(秒)
     */
    public boolean lSet(String key, Object value, long time) {
        try {
            redisTemplate.opsForList().rightPush(key, value);
            if (time > 0)
                expire(key, time);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }


    /**
     * 将list放入缓存
     *
     * @param key   键
     * @param value 值
     * @return
     */
    public boolean lSet(String key, List<Object> value) {
        try {
            redisTemplate.opsForList().rightPushAll(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 将list放入缓存
     *
     * @param key   键
     * @param value 值
     * @param time  工夫(秒)
     * @return
     */
    public boolean lSet(String key, List<Object> value, long time) {
        try {
            redisTemplate.opsForList().rightPushAll(key, value);
            if (time > 0)
                expire(key, time);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 依据索引批改list中的某条数据
     *
     * @param key   键
     * @param index 索引
     * @param value 值
     * @return
     */

    public boolean lUpdateIndex(String key, long index, Object value) {
        try {
            redisTemplate.opsForList().set(key, index, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 移除N个值为value
     *
     * @param key   键
     * @param count 移除多少个
     * @param value 值
     * @return 移除的个数
     */

    public long lRemove(String key, long count, Object value) {
        try {
            Long remove = redisTemplate.opsForList().remove(key, count, value);
            return remove;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }
}

11、在UserServiceImpl中进行redis缓存逻辑bianxie


@Service
public class UserServiceImpl implements UserService {

    @Autowired
    UserMapper userMapper;
    @Autowired
    RedisUtils redisUtils;

    public static final String CACHE_KEY_USER="user:";

    @Override
    public int addUser(User user) {
        //先间接批改数据库中的数据,办法执行后再更新缓存
        int i = userMapper.addUser(user);
        redisUtils.set(CACHE_KEY_USER+user.getId(),user);
        return i;
    }

    @Override
    public int deleteUser(int id) {
        //办法执行后删除redis中相应的缓存
        int i = userMapper.deleteUser(id);
        redisUtils.del(CACHE_KEY_USER+id);
        return i;
    }

    @Override
    public int updateUser(User user) {
        //先间接批改数据库中的数据
        int i = userMapper.updateUser(user);
        //办法执行后更新redis中相应的缓存
        int id = user.getId();
        redisUtils.set(CACHE_KEY_USER+user.getId(),user);
        return i;
    }

    @Override
    public List<User> selectUser() {
        int i = countUser();
        Object object = redisUtils.get(CACHE_KEY_USER + "number:"+i);
        //判断redis中是否存在缓存的key-value
        if (null != object){
            //有,间接返回
            return (List<User>) object;
        }
        //没有,去数据库中查问,并将查问的后果存到redis中
        List<User> users = userMapper.selectUser();
        redisUtils.set(CACHE_KEY_USER + "number:"+i,users);
        return users;
    }

    @Override
    public User selectUserById(int id) {
        Object object = redisUtils.get(CACHE_KEY_USER + id);
        //判断redis中是否存在缓存的key-value
        if (null != object){
            //有,间接返回
            return (User) object;
        }
        //没有,去数据库中查问,并将查问的后果存到redis中
        User user = userMapper.selectUserById(id);
        redisUtils.set(CACHE_KEY_USER + id,user);
        return user;
    }

    @Override
    public int countUser() {
        return userMapper.countUser();
    }
}

12、单元测试查看缓存

@SpringBootTest
class RedisTest01SpringbootApplicationTests {

    @Autowired
    UserService userService;

    @Test
    void selectById() {
        User user = userService.selectUserById(3);
        System.out.println(user);
    }

    @Test
    void select() {
        List<User> users = userService.selectUser();
        for (User user : users) {
            System.out.println(user);
        }
    }

    @Test
    void add() {
        userService.addUser(new User(6,"纸飞机","1998dsadsasd"));
    }

    @Test
    void delete() {
        userService.deleteUser(6);
    }

    @Test
    void update() {
        userService.updateUser(new User(6,"纸飞机666","helloredis"));
    }
}

以上只是特地简略的redis操作,其余的设置key的过期工夫等,间接应用redisUtils进行设置即可。

五、总结

redis缓存实质仍旧是操作redis其中的五大数据类型,须要熟练掌握,并且能通晓用在何处,怎么用。

参考:

1、https://segmentfault.com/a/11… 整合Redis缓存实现 指标字节的秃秃
2、https://juejin.im/post/684490… Spring Boot 2.X(七):Spring Cache 应用 朝雾轻寒
3、https://juejin.im/post/684490… 优雅的缓存解决方案–SpringCache和Redis集成(SpringBoot) 米奇罗


谢谢您看完这篇技术文章

如果能对您有所帮忙

那将是一件很美妙的事件

放弃好奇心的一生学习也是极棒的事

愿世界简略又多彩

转载请注明出处

​ ——纸飞机

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理