spring boot 使用redis做缓存学习记录

本文介绍如何在Spring Boot应用中配置Redis缓存,并通过注解和自定义方式实现缓存管理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一 、配置文件中的内容

  • redis 系统配置,即在application.yml文件中的配置
  • RedisPoolConfig配置
  • RedisPool配置
  • RedisConnectionFactory配置
  • StringRedisTemplate
  • RedisTemplate
package com.seedyee.config;

import java.lang.reflect.Method;
import java.net.UnknownHostException;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectMapper.DefaultTyping;

import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

/**
 * @author lcl
 * @createDate 2016年11月22日上午11:00:08 redis 缓存配置类
 * 这里实现CachingConfigurerSupport主要是方便使用自定义keyGenerator
 */
@Configuration
@EnableCaching // 启用缓存
public class RedisCacheConfig extends CachingConfigurerSupport {

    @Value("${spring.redis.host}")
    private String host;
    @Value("${spring.redis.port}")
    private int port;
    @Value("${spring.redis.timeout}")
    private int timeout;
    @Value("${spring.redis.password}")
    private String password;
    @Value("${spring.redis.pool.max-active}")
    private int maxActive;
    @Value("${spring.redis.pool.max-wait}")
    private int maxWait;
    @Value("${spring.redis.pool.max-idle}")
    private int maxIdle;
    @Value("${spring.redis.pool.min-idle}")
    private int mainIdle;

    /**
     * 配置JedisPoolConfig
     * @return JedisPoolConfig实体
     */
    @Bean
    public JedisPoolConfig jedisPoolConfig() {
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        jedisPoolConfig.setMaxIdle(this.maxIdle);
        jedisPoolConfig.setMaxWaitMillis(this.maxWait);
        jedisPoolConfig.setMinIdle(this.mainIdle);
        return jedisPoolConfig;
    }

    /**
     * 配置JedisPool
     * @return
     */
    @Bean
    public JedisPool jedisPool() {
        JedisPool jedisPool = null;
        if (this.password != null) {
            jedisPool = new JedisPool(this.jedisPoolConfig(), this.host, this.port, this.timeout, this.password);
        } else {
            jedisPool = new JedisPool(this.jedisPoolConfig(), this.host, this.port);
        }
        return jedisPool;
    }

    /**
     * RedisConnectionFactory配置
     * @return
     */
    @Bean
    public RedisConnectionFactory redisConnectionFactory() {
        return new JedisConnectionFactory(this.jedisPoolConfig());
    }

    /**
     * 配置StringRedisTemplate实体
     * @return
     */
    @Bean
    public StringRedisTemplate stringRedisTemplate() {
        StringRedisTemplate stringRedisTemplate = new StringRedisTemplate();
        stringRedisTemplate.setConnectionFactory(this.redisConnectionFactory());
        return stringRedisTemplate;
    }
    /**
     * 配置RedisTemplate
     * @return 返回redisTemplate实体
     */
    @Bean
    public RedisTemplate<String, Object> redisTemplate() throws UnknownHostException {
        RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
        template.setConnectionFactory(this.redisConnectionFactory());
        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<Object>(
                Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, Visibility.ANY);
        om.enableDefaultTyping(DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        //使用StringRedisSerializer作为序列化key,默认是使用JdkSerializationRedisSerializer,会出现脏字段在key中
        template.setKeySerializer(new StringRedisSerializer());
        template.setValueSerializer(jackson2JsonRedisSerializer);
        template.afterPropertiesSet();
        return template;
    }

    /**
     * 自定义keyGenerator
     * 
     * @return
     */
    @Bean
    public KeyGenerator wiselyKeyGenerator() {
        return new KeyGenerator() {

            @Override
            public Object generate(Object target, Method method, Object... params) {
                StringBuffer sb = new StringBuffer();
                sb.append("mykey" + ":");
                sb.append(method.getName() + ":");
                for (Object object : params) {
                    sb.append(object.toString());
                }
                return sb.toString();
            }
        };
    }

    /**
     * 配置redis缓存管理对象
     * 
     * @param redisTemplate
     * @return
     */
    @Bean(name = "cacheManager")
    public CacheManager cacheManager(RedisTemplate<?, ?> redisTemplate) {
        return new RedisCacheManager(redisTemplate);
    }
}

注意:在配置文件中配置RedisTemplate的之后需要注意,Redis默认使用JdkSerializationRedisSerializer作为序列化key和value的,所以需要重新设置key和value的序列化,本文在代码中采用的key的序列化为StringRedisSerializer,value的序列化采用jackson2JsonRedisSerializer,具体代码请查看以上配置文件的代码。如果不设置的话插入redis数据库中的数据的key的形式为:\xAC\xED\x00\x05t\x00\x1810001,其中10001是自己存的key的值,会多前面这一窜,value的话分为对象和字符串的两种情况,字符串的情况和id的情况是一样的,对象的话就是把属性分为每个字符串的情况。

二、使用

2.1 使用注解实现方法级缓存

可以自定义缓存切入点,可以在dao层做,也可以在service层做,具体可以根据需求,下面记录的是在service层做的:

package com.seedyee.service;

import java.util.Collection;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import com.seedyee.dao.EmailDao;
import com.seedyee.dao.RedisDao;
import com.seedyee.dao.UserDao;
import com.seedyee.domain.User;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

/**
 * @author lcl
 * @createDate 2016年11月21日下午5:30:23
 *
 */
@Service
public class UserService {

    @Autowired
    private CacheManager cacheManager;

    @Autowired
    private RedisDao redis;

    @Autowired
    private UserDao userDao;

    @Autowired
    private EmailDao emailDao;


    //@Cacheable(cacheNames = {"users"}, key= "#user.id")
    public Object createUser(User user) {

        User createUser = null;
        createUser = userDao.save(user);
        return createUser;
    }
    @Cacheable(cacheNames = {"users"}, key = "#id" )
    public Object getUserInfo(String id) {
        User user = null;
        user = userDao.findById(id);
        Collection<String> cacheNames = cacheManager.getCacheNames();
        for (String string : cacheNames) {
            System.out.println(string);
            System.out.println(cacheManager.getCache(string));
        }
        System.out.println("--------------进来说明没有使用缓存-------------------");
        return user;
    }
    @CacheEvict(cacheNames = {"users"}, key = "#user.id")
    public Object updateUserInfo(User user) {
        User formUser = userDao.findById(user.getId());
        if (user.getName() != null && formUser != null) {
            formUser.setName(user.getName());

            //修改成功删除缓存中的数据
            //redis.delete(formUser.getId());
            return userDao.save(formUser);
        }
        return "修改出现异常";
    }
    @CacheEvict(cacheNames = {"users"})
    public Object deleteUser(String id) {
        userDao.delete(id);
        //删除成功删除缓存中的数据
        //redis.delete(id);
        return "ok";
    }
}

2.2 选择在需要的地方存储或是删除缓存的

2.2.1 配置redis对数据库操作类

使用配置文件中配置好的StringRedisTemplate和RedisTemplate来完成对数据库数据的CRUD操作,以下代码主要是存储和删除操作:
文件名 RedisDao.java

package com.seedyee.dao;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

/**
 * @author lcl
 * @createDate 2016年11月24日下午11:03:57
 *
 */
@Component
public class RedisDao {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

//  @Resource(name = "stringRedisTemplate")
//  private ValueOperations<String, String> valOpsStr;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

//  @Resource
//  private ValueOperations<String, Object> valOps;
    /**
     * 存储字符串
     * @param key string类型的key
     * @param value String类型的value
     */
    public void set(String key, String value) {
        stringRedisTemplate.opsForValue().set(key, value);
    }

    /**
     * 存储对象
     * @param key String类型的key
     * @param value Object类型的value
     */
    public void set(String key, Object value) {
        redisTemplate.opsForValue().set(key, value);
    }
    /**
     * 根据key获取字符串数据
     * @param key
     * @return
     */
    public String getValue(String key) {
        return stringRedisTemplate.opsForValue().get(key);
    }
    /**
     * 根据key获取对象
     * @param key
     * @return
     */
    public Object getValueOfObject(String key) {
        return redisTemplate.opsForValue().get(key);
    }
    /**
     * 根据key删除缓存信息
     * @param key
     */
    public void delete(String key) {
        redisTemplate.delete(key);
    }
}

2.2.2 对缓存进行操作

在需要对缓存进行操作的地方使用redisDao的示例对象进行操作,下面的代码主要是记录删除时候的操作:

package com.seedyee.service;

import java.util.Collection;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import com.seedyee.dao.EmailDao;
import com.seedyee.dao.RedisDao;
import com.seedyee.dao.UserDao;
import com.seedyee.domain.User;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

/**
 * @author lcl
 * @createDate 2016年11月21日下午5:30:23
 *
 */
@Service
public class UserService {

    @Autowired
    private CacheManager cacheManager;

    @Autowired
    private RedisDao redis;

    @Autowired
    private UserDao userDao;

    @Autowired
    private EmailDao emailDao;


    //@Cacheable(cacheNames = {"users"}, key= "#user.id")
    public Object createUser(User user) {

        User createUser = null;
        createUser = userDao.save(user);
        return createUser;
    }
    @Cacheable(cacheNames = {"users"}, key = "#id" )
    public Object getUserInfo(String id) {
        User user = null;
        user = userDao.findById(id);
        Collection<String> cacheNames = cacheManager.getCacheNames();
        for (String string : cacheNames) {
            System.out.println(string);
            System.out.println(cacheManager.getCache(string));
        }
        System.out.println("--------------进来说明没有使用缓存-------------------");
        return user;
    }
    //@CacheEvict(cacheNames = {"users"}, key = "#user.id")
    public Object updateUserInfo(User user) {
        User formUser = userDao.findById(user.getId());
        if (user.getName() != null && formUser != null) {
            formUser.setName(user.getName());

            //修改成功删除缓存中的数据
            redis.delete(formUser.getId());
            return userDao.save(formUser);
        }
        return "修改出现异常";
    }
    //@CacheEvict(cacheNames = {"users"})
    public Object deleteUser(String id) {
        userDao.delete(id);
        //删除成功删除缓存中的数据
        *redis.delete(id);*
        return "ok";
    }
}

注意:在使用第二种方法实现缓存的时候,上面代码中删除缓存对应的信息以后,cacheName下的key的值没有删掉,cacheName下存储同一类的不同key。这里记录一下,寻求解决方法中。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值