Springboot整合(8)——Redis

Springboot整合(8)——Redis

0. 搭建redis环境,可参考我之前的文章:用docker搭建redis

1. pom中增加redis依赖

        <!-- redis -->

        <dependency>

            <groupId>org.springframework.boot</groupId>

            <artifactId>spring-boot-starter-data-redis</artifactId>

        </dependency>

2. 在application.yml中spring的节点下(跟datasource同一层)增加redis配置

  #Redis配置

  redis:

    database: 0

    host: 192.168.59.103

    port: 6379

    pool:

      max-idle: 8

      min-idle: 0

      max-active: 8

      max-wait: -1

3. 编写redis序列化对象类

import org.springframework.core.convert.converter.Converter;

import org.springframework.core.serializer.support.DeserializingConverter;

import org.springframework.core.serializer.support.SerializingConverter;

import org.springframework.data.redis.serializer.RedisSerializer;

import org.springframework.data.redis.serializer.SerializationException;

 

/**

 * redis序列化对象

 */

publicclass RedisObjectSerializer implements RedisSerializer<Object> {

    private Converter<Object, byte[]> serializer = new SerializingConverter();

    private Converter<byte[], Object> deserializer = new DeserializingConverter();

    staticfinalbyte[] EMPTY_ARRAY = newbyte[0];

 

    public Object deserialize(byte[] bytes) {

        if (isEmpty(bytes)) {

            returnnull;

        }

        try {

            returndeserializer.convert(bytes);

        } catch (Exception ex) {

            thrownew SerializationException("Cannot deserialize", ex);

        }

    }

 

    publicbyte[] serialize(Object object) {

        if (object == null) {

            returnEMPTY_ARRAY;

        }

        try {

            returnserializer.convert(object);

        } catch (Exception ex) {

            returnEMPTY_ARRAY;

        }

    }

 

    privateboolean isEmpty(byte[] data) {

        return (data == null || data.length == 0);

    }

}

 

4. 编写redis配置类RedisCacheConfig

/**

 * Redis缓存配置类

 */

@Configuration

@EnableCaching

publicclass RedisCacheConfig extends CachingConfigurerSupport {

 

    // 自定义缓存key生成策略

    @Bean

    public KeyGenerator keyGenerator() {

        returnnew KeyGenerator() {

            @Override

            public Object generate(Object target, java.lang.reflect.Method method, Object... params) {

                StringBuffer sb = new StringBuffer();

                sb.append(target.getClass().getName());

                sb.append(method.getName());

                for (Object obj : params) {

                    if (obj == null) {

                        continue;

                    }

                    sb.append(obj.toString());

                }

                returnsb.toString();

            }

        };

    }

 

    // 缓存管理器

    @Bean

    public CacheManager cacheManager(@SuppressWarnings("rawtypes") RedisTemplate redisTemplate) {

        RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);

        // 设置缓存过期时间

        cacheManager.setDefaultExpiration(1800);

        returncacheManager;

    }

 

    @Bean

    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory factory) {

        RedisTemplate<Object, Object> template = new RedisTemplate<Object, Object>();

        template.setConnectionFactory(factory);

        template.setKeySerializer(new StringRedisSerializer());

        template.setValueSerializer(new RedisObjectSerializer ());

        returntemplate;

    }

 

}

 

5. 使用缓存有2种方法,一种是直接在Controller里使用注解的方式,另一种是自已手动读取写入缓存,前者更加方便,后者更加灵活,根据实际需求选择具体使用哪种,下面将2中方法分别说明

5.1 在Controller中使用注解方式使用缓存

@Cacheable 从缓存读取数据

@CacheEvict 清除缓存

示例:

Springboot整合(8)——Redis
① 访问http://localhost:8088/KnowledgeIsland/user/cacheList,首次后台会打印sql,再次访问就不会打印sql,从redis里读取

② 进入http://localhost:8088/KnowledgeIsland/user/add,添加一个user,查看redis,会看到redis里user的缓存已经被清除,再次访问http://localhost:8088/KnowledgeIsland/user/cacheList,又会去数据库查询

 

5.2 自己编码实现读取写入缓存

① 编写操作缓存的工具类

/**

 * Cache工具类

 */

publicclass CacheUtil {

 

    privatestatic Logger logger = LoggerFactory.getLogger(CacheUtil.class);

    privatestatic CacheManager cacheManager = SpringUtil.getBean(CacheManager.class);

    //是否开启缓存

    privatestaticbooleanenableCache = true;

 

    /**

     * 获取缓存

     *

     * @param cacheName

     * @param key

     * @return

     */

    publicstatic Object get(String cacheName, String key) {

        if (!enableCache) {

            returnnull;

        }

        ValueWrapper valueWrapper = getCache(cacheName).get(key);

        if (valueWrapper == null) {

            returnnull;

        }

        return getCache(cacheName).get(key).get();

    }

 

    /**

     * 获取缓存

     *

     * @param cacheName

     * @param key

     * @param defaultValue

     * @return

     */

    publicstatic Object get(String cacheName, String key, Object defaultValue) {

        if (!enableCache) {

            returndefaultValue;

        }

        Object value = get(cacheName, key);

        returnvalue != null ? value : defaultValue;

    }

 

    /**

     * 写入缓存

     *

     * @param cacheName

     * @param key

     * @param value

     */

    publicstaticvoid put(String cacheName, String key, Object value) {

        if (!enableCache) {

            return;

        }

        getCache(cacheName).put(key, value);

    }

 

    /**

     * 从缓存中移除

     *

     * @param cacheName

     * @param key

     */

    publicstaticvoid remove(String cacheName, String key) {

        if (!enableCache) {

            return;

        }

        getCache(cacheName).evict(key);

    }

 

    /**

     * 从缓存中移除所有

     *

     * @param cacheName

     */

    publicstaticvoid removeAll(String cacheName) {

        if (!enableCache) {

            return;

        }

        getCache(cacheName).clear();

        logger.info("清理缓存: {} => {}", cacheName);

    }

 

    /**

     * 获得一个Cache,没有则显示日志。

     *

     * @param cacheName

     * @return

     */

    privatestatic Cache getCache(String cacheName) {

        Cache cache = cacheManager.getCache(cacheName);

        if (cache == null) {

            thrownew RuntimeException("当前系统中没有定义“" + cacheName + "”这个缓存。");

        }

        returncache;

    }

 

}

 

注:该类引用了一个SpringUtil类,该类的作用是可以让那些没有注册为spring component的普通类调用spring bean,代码如下:

import org.springframework.beans.BeansException;

import org.springframework.context.ApplicationContext;

import org.springframework.context.ApplicationContextAware;

import org.springframework.stereotype.Component;

 

/**

 * 普通类调用Spring bean对象:说明: 1、此类需要放到App.java同包或者子包下才能被扫描,否则失效。

*/

@Component

publicclass SpringUtil implements ApplicationContextAware {

    privatestatic ApplicationContext applicationContext = null;

 

    @Override

    publicvoid setApplicationContext(ApplicationContext applicationContext) throws BeansException {

        if (SpringUtil.applicationContext == null) {

            SpringUtil.applicationContext = applicationContext;

        }

        System.out.println("---------------------------------------------------------------------");

        System.out.println("---------------------------------------------------------------------");

        System.out.println(

                "---------------com.kfit.base.util.SpringUtil------------------------------------------------------");

        System.out.println(

                "========ApplicationContext配置成功,在普通类可以通过调用SpringUtils.getAppContext()获取applicationContext对象,applicationContext="

                        + SpringUtil.applicationContext + "========");

        System.out.println("---------------------------------------------------------------------");

    }

 

    // 获取applicationContext

    publicstatic ApplicationContext getApplicationContext() {

        returnapplicationContext;

    }

 

    // 通过name获取 Bean.

    publicstatic Object getBean(String name) {

        return getApplicationContext().getBean(name);

    }

 

    // 通过class获取Bean.

    publicstatic <T> T getBean(Class<T> clazz) {

        return getApplicationContext().getBean(clazz);

    }

 

    // 通过name,以及Clazz返回指定的Bean

    publicstatic <T> T getBean(String name, Class<T> clazz) {

        return getApplicationContext().getBean(name, clazz);

    }

}

 

② 调用工具类操作缓存,操作逻辑可放在任何地方,本文示例放在UserService里。put,remove,clear,完全自由控制(本处只示例get和put)

 

controller层调用代码不变

Springboot整合(8)——Redis
③访问http://localhost:8088/KnowledgeIsland/user/list测试

6. 特别注意的地方,所有放入redis的对象,需要实现Serializable接口。将对象类型数据放入redis,本文采用的方法是将对象序列化之后放入。另一种方法是,将对象全部转为json字符串,然后再放入,拿出来的时候再转回来。

相关推荐