Redis

spring-data-redis缓存的使用

2019-02-20  本文已影响0人  流欣儿

公司最近需要将一个老项目升级,其中涉及到缓存,从memcached到Redis。

如果简单的key/value 存储应该选择memcached

jedis

首先通过maven引入jedis的依赖:

<!-- 注意:2.9.0以后版本才支持集群,且该版本集群密码有问题 -->
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>2.9.0</version>
</dependency>

创建Jedis对象,调用set方法,并通过get方法获取到值并打印:

Jedis jedis = new Jedis("localhost", 6379);
jedis.set("singleJedis", "hello jedis!");
System.out.println(jedis.get("singleJedis"));
jedis.close();

需要自己实现一些jedis的工具类,使用不方便。

spring-data-redis

spring已经将redis集成,并提供了较为友好的redisTemplate访问redis。这里配置集群环境

spring集成

pom加入:

<!-- jedis (一个redis client端的jar)-->
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>2.9.0</version>
</dependency>
<!-- spring-data-redis 依赖-->
<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-redis</artifactId>
    <version>1.7.1.RELEASE</version>
</dependency>

添加配置文件redis.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:task="http://www.springframework.org/schema/task" xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:cache="http://www.springframework.org/schema/cache"
    xsi:schemaLocation="
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd
    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd
    http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.1.xsd
    http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd
    http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd">

     <!--  redis连接池  这里引用的是jedis 包中的功能  -->
    <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
        <property name="maxTotal" value="${redis.maxActive:1024}" />
        <property name="maxIdle" value="${redis.maxIdle:1024}" />
        <property name="maxWaitMillis" value="${redis.maxWait:10000}" />
        <property name="testOnBorrow" value="${redis.testOnBorrow:true}" />
        <property name="testOnReturn" value="${redis.testOnReturn:true}" />
    </bean>

    <!-- Redis集群配置     这里使用的是spring-data-redis  包中内容 -->
     <bean id="redisClusterConfig" class="org.springframework.data.redis.connection.RedisClusterConfiguration">
        <property name="maxRedirects" value="6"></property>
        <property name="clusterNodes">
            <set>
                <bean class="org.springframework.data.redis.connection.RedisNode">
                    <constructor-arg name="host" value="192.168.1.105"></constructor-arg>
                    <constructor-arg name="port" value="7111"></constructor-arg>
                </bean>

                <bean class="org.springframework.data.redis.connection.RedisNode">
                    <constructor-arg name="host" value="192.168.1.105"></constructor-arg>
                    <constructor-arg name="port" value="7112"></constructor-arg>
                </bean>
                <bean class="org.springframework.data.redis.connection.RedisNode">
                    <constructor-arg name="host" value="192.168.1.105"></constructor-arg>
                    <constructor-arg name="port" value="7116"></constructor-arg>
                </bean>
                <bean class="org.springframework.data.redis.connection.RedisNode">
                    <constructor-arg name="host" value="192.168.1.102"></constructor-arg>
                    <constructor-arg name="port" value="7113"></constructor-arg>
                </bean>
                 <bean class="org.springframework.data.redis.connection.RedisNode">
                    <constructor-arg name="host" value="192.168.1.102"></constructor-arg>
                    <constructor-arg name="port" value="7114"></constructor-arg>
                </bean>
                 <bean class="org.springframework.data.redis.connection.RedisNode">
                    <constructor-arg name="host" value="192.168.1.102"></constructor-arg>
                    <constructor-arg name="port" value="7115"></constructor-arg>
                </bean>
            </set>
        </property>
    </bean> 
    <!-- Redis连接工厂     -->
    <bean id="redis4CacheConnectionFactory"
        class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
        <constructor-arg name="clusterConfig" ref="redisClusterConfig" />
        <property name="timeout" value="${redis.timeout:10000}" />
        <property name="poolConfig" ref="jedisPoolConfig" />
    </bean>
    <!-- 存储序列化 -->
    <bean name="stringRedisSerializer"
        class="org.springframework.data.redis.serializer.StringRedisSerializer" />

    <!-- 集群Resis使用模板 -->
    <bean id="clusterRedisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
        <property name="connectionFactory" ref="redis4CacheConnectionFactory" />
        <property name="keySerializer" ref="stringRedisSerializer" />
        <property name="hashKeySerializer" ref="stringRedisSerializer" />
        <property name="valueSerializer" ref="stringRedisSerializer" />
        <property name="hashValueSerializer" ref="stringRedisSerializer" />
    </bean>

</beans>

springboot集成

pom加入:

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

添加ReisConfig.java配置文件

package com.i2f.i2work.core.common.redis;

import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.CacheErrorHandler;
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.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;

import java.lang.reflect.Method;

/**
 * @author ltlixer
 * @date 2017/12/7 上午11:02
 */
@Slf4j
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {

    @Bean
    @Override
    public KeyGenerator keyGenerator() {
        return new KeyGenerator() {
            @Override
            public Object generate(Object target, Method method, Object... params) {
                StringBuilder sb = new StringBuilder();
                sb.append(target.getClass().getName());
                sb.append(method.getName());
                for (Object obj : params) {
                    sb.append(obj.toString());
                }
                return sb.toString();
            }
        };
    }

    @SuppressWarnings("rawtypes")
    @Bean
    public CacheManager cacheManager(RedisTemplate redisTemplate) {
        RedisCacheManager rcm = new RedisCacheManager(redisTemplate);
        //设置缓存过期时间,1个月
        rcm.setDefaultExpiration(60 * 60 * 24 * 30);
        return rcm;
    }

    @Bean
    public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {
        StringRedisTemplate template = new StringRedisTemplate(factory);
        //自定义redis序列化方式
        template.setValueSerializer(new I2WorkSerializer());
        template.afterPropertiesSet();
        return template;
    }

    /**
     * redis异常处理器
     * 默认SimpleCacheErrorHandler是抛出异常,此处自定义处理方式不抛出
     *
     * @return
     */
    @Bean
    @Override
    public CacheErrorHandler errorHandler() {
        return new CacheErrorHandler() {
            @Override
            public void handleCacheGetError(RuntimeException e, Cache cache, Object key) {
                log.error("cache get error", e);
            }

            @Override
            public void handleCachePutError(RuntimeException e, Cache cache, Object key, Object value) {
                log.error("cache put error", e);
            }

            @Override
            public void handleCacheEvictError(RuntimeException e, Cache cache, Object key) {
                log.error("cache evict error", e);
            }

            @Override
            public void handleCacheClearError(RuntimeException e, Cache cache) {
                log.error("cache clear error", e);
            }
        };
    }
}

注意:需要使用相同的序列化方式
spring-data-redis提供了若干个Serializer,主要包括:

JacksonJsonRedisSerializer
JdkSerializationRedisSerializer
OxmSerializer
我自己使用alibaba的fastjson实现了一个自定义的序列化方式

package com.i2f.i2work.core.common.redis;

import com.alibaba.fastjson.JSON;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.SerializationException;
import org.springframework.util.Assert;

import java.nio.charset.Charset;

/**
 * 自定义序列化
 * 使用fastJson
 *
 * @author ltlixer
 * @date 2017/12/28 下午2:30
 */
public class I2WorkSerializer implements RedisSerializer<Object> {

    static final byte[] EMPTY_ARRAY = new byte[0];
    private final Charset charset;

    public I2WorkSerializer() {
        this(Charset.forName("UTF8"));
    }

    public I2WorkSerializer(Charset charset) {
        Assert.notNull(charset);
        this.charset = charset;
    }

    @Override
    public byte[] serialize(Object object) throws SerializationException {
        //序列化方法
        try {
            String jsonString = JSON.toJSONString(object);
            return (jsonString == null ? EMPTY_ARRAY : jsonString.getBytes(charset));
        } catch (Exception e) {
            throw new SerializationException("Could not write JSON: " + e.getMessage(), e);
        }

    }

    @Override
    public Object deserialize(byte[] bytes) throws SerializationException {
        //反序列化
        if (bytes == null) {
            return null;
        }
        try {
            //byte数组转换为String
            String objectStr = new String(bytes, charset);
            //String转化为JSONObject
            return JSON.parse(objectStr);
        } catch (Exception e) {
            throw new SerializationException("Could not read JSON: " + e.getMessage(), e);
        }
    }

}
上一篇 下一篇

猜你喜欢

热点阅读