1. 程式人生 > >spring +redis 快取應用

spring +redis 快取應用

 

安裝redis資料庫 此處省略

 

1.spring-context.xml
 

<!-- 讀入配置屬性檔案 -->
<!--     <context:property-placeholder location="classpath:config.properties" />
<context:property-placeholder location="classpath:pgsql-config.properties" />
     -->
    <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">  
    <property name="locations">  
       <list>  
          <value>classpath:config.properties</value>  
          <value>classpath:pgsql-config.properties</value>  
        </list>  
    </property>  
</bean>  
    
    
    <!-- 引入spring-redis.xml -->
     <import resource="classpath:spring-redis.xml" /> 

2.config.properties

# Redis settings  
redis.host=127.0.0.1
redis.port=6379  
#redis.pass=password
redis.dbIndex=0  
redis.expiration=3000  
redis.maxIdle=300  
redis.maxActive=600  
redis.maxWait=1000  
redis.testOnBorrow=true

3.spring-redis.xml

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


    <!-- redis config start -->
    <!-- 配置JedisPoolConfig例項 -->
    <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
        <property name="maxIdle" value="${redis.maxIdle}" />
        <property name="maxTotal" value="${redis.maxActive}" />
        <property name="maxWaitMillis" value="${redis.maxWait}" />
        <property name="testOnBorrow" value="${redis.testOnBorrow}" />
    </bean>

    <!-- 配置JedisConnectionFactory -->
    <bean id="jedisConnectionFactory"
        class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
        <property name="hostName" value="${redis.host}" />
        <property name="port" value="${redis.port}" />
        <!-- <property name="password" value="${redis.pass}" /> -->
        <property name="database" value="${redis.dbIndex}" />
        <property name="poolConfig" ref="poolConfig" />
    </bean>

    <!-- 配置RedisTemplate -->
    <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
        <property name="connectionFactory" ref="jedisConnectionFactory" />
    </bean>

    <!-- 配置RedisCacheManager -->
    <bean id="redisCacheManager" class="org.springframework.data.redis.cache.RedisCacheManager">
        <constructor-arg name="redisOperations" ref="redisTemplate" />
        <property name="defaultExpiration" value="${redis.expiration}" />
    </bean>

    <!-- 配置RedisCacheConfig -->
    <bean id="redisCacheConfig" class="com.bigname.common.utils.RedisCacheConfig">
        <constructor-arg ref="jedisConnectionFactory" />
        <constructor-arg ref="redisTemplate" />
        <constructor-arg ref="redisCacheManager" />
    </bean>
    <!-- redis config end -->
</beans>

4.RedisCacheConfig

package com.bigname.common.utils;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

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.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import com.fasterxml.jackson.databind.ObjectMapper;

//@Configuration  
//@EnableCaching
public class RedisCacheConfig extends CachingConfigurerSupport{

    private volatile JedisConnectionFactory jedisConnectionFactory;
    private volatile RedisTemplate<String, String> redisTemplate;
    private volatile RedisCacheManager redisCacheManager;

    public RedisCacheConfig() {
        super();
    }

    /**
     * 帶引數的構造方法 初始化所有的成員變數
     * 
     * @param jedisConnectionFactory
     * @param redisTemplate
     * @param redisCacheManager
     */
    public RedisCacheConfig(JedisConnectionFactory jedisConnectionFactory, RedisTemplate<String, String> redisTemplate,
            RedisCacheManager redisCacheManager) {
        this.jedisConnectionFactory = jedisConnectionFactory;
        this.redisTemplate = redisTemplate;
        this.redisCacheManager = redisCacheManager;
    }

    public JedisConnectionFactory getJedisConnecionFactory() {
        return jedisConnectionFactory;
    }

    public RedisTemplate<String, String> getRedisTemplate() {
        return redisTemplate;
    }

    public RedisCacheManager getRedisCacheManager() {
        return redisCacheManager;
    }

    //@Bean
    public KeyGenerator customKeyGenerator() {
        return new KeyGenerator() {
            public Object generate(Object target, Method method, Object... objects) {
                StringBuilder sb = new StringBuilder();
                sb.append(target.getClass().getName());
                sb.append(method.getName());
                for (Object obj : objects) {
                    sb.append(obj.toString());
                }
                return sb.toString();
            }
        };
    }
    
    
   // @Bean
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<Object, Object>();
        redisTemplate.setConnectionFactory(redisConnectionFactory);
 
        // 使用Jackson2JsonRedisSerialize 替換預設序列化
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
 
        ObjectMapper objectMapper = new ObjectMapper();
        //objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
 
        jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
 
        // 設定value的序列化規則和 key的序列化規則
        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
        redisTemplate.setKeySerializer(new StringRedisSerializer());
 
        redisTemplate.setHashKeySerializer(jackson2JsonRedisSerializer);
        redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
 
        redisTemplate.setDefaultSerializer(jackson2JsonRedisSerializer);
        redisTemplate.setEnableDefaultSerializer(true);
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }
}


5.RedisHelper

package com.bigname.common.utils;

import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.log4j.Logger;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

public class RedisHelper {
    private static Logger logger = Logger.getLogger(RedisHelper.class);

    private static JedisPool jedisPool;
    
    public RedisHelper(JedisPool pool) {
        RedisHelper.jedisPool = pool;
    }
    
    public static String set(String key, String value) {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            String rtn = jedis.set(key, value);
            return rtn;
        } catch(Exception e) {
            logger.error("set方法報錯:key=" + key + ",value=" + value, e);
            throw new RuntimeException("set方法報錯。");
        } finally {
            if(jedis != null) {
                jedisPool.returnResource(jedis);
            }
        }
    }
    
    public static String set(byte[] key, byte[] value) {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            String rtn = jedis.set(key, value);
            return rtn;
        } catch(Exception e) {
            logger.error("set方法報錯:key=" + key + ",value=" + value, e);
            throw new RuntimeException("set方法報錯。");
        } finally {
            if(jedis != null) {
                jedisPool.returnResource(jedis);
            }
        }
    }

    /** 根據key從redis刪除相關值 */
    public static void del(String key) {
        Jedis jedis = null;
        try{
            jedis = jedisPool.getResource();
            jedis.del(key);
        } catch(Exception e) {
            logger.error("del方法報錯:key=" + key, e);
        } finally {
            if(jedis != null) {
                jedisPool.returnResource(jedis);
            }
        }
    }
    
    /** 可以設定過期時間的set方法 */
    public static String setWithExpireTime(String key, String value, int seconds) {
        Jedis jedis = null;
        try{
            jedis = jedisPool.getResource();
            String rtn = jedis.set(key, value);
            jedis.expire(key, seconds);
            return rtn;
        } catch(Exception e) {
            logger.error("setWithExpireTime方法報錯:key=" + key + ",value=" + value, e);
            throw new RuntimeException("get方法報錯。");
        } finally {
            if(jedis != null) {
                jedisPool.returnResource(jedis);
            }
        }
    }
    
    /** 根據key從redis獲取相關值 */
    public static String get(String key) {
        Jedis jedis = null;
        try{
            jedis = jedisPool.getResource();
            String rtn = jedis.get(key);
            return rtn;
        } catch(Exception e) {
            logger.error("get方法報錯:key=" + key, e);
            throw new RuntimeException("get方法報錯。");
        } finally {
            if(jedis != null) {
                jedisPool.returnResource(jedis);
            }
        }
    }

    /**
     * 根據key從redis獲取相關值
     * @param key byte[]
     * @return byte[]
     */
    public static byte[] get(byte[] key) {
        Jedis jedis = null;
        try{
            jedis = jedisPool.getResource();
            byte[] rtn = jedis.get(key);
            return rtn;
        } catch(Exception e) {
            logger.error("get方法報錯:key=" + key, e);
            throw new RuntimeException("get方法報錯。");
        } finally {
            if(jedis != null) {
                jedisPool.returnResource(jedis);
            }
        }
    }

    /** 往redis中設定map物件 */
    public static String hmset(String key, Map<String, String> hash) {
        Jedis jedis = null;
        try{
            jedis = jedisPool.getResource();
            String rtn = jedis.hmset(key, hash);
            return rtn;
        } catch(Exception e) {
            logger.error("hmset方法報錯:key=" + key, e);
            throw new RuntimeException("hmset方法報錯。");
        } finally {
            if(jedis != null) {
                jedisPool.returnResource(jedis);
            }
        }
    }
    
    /** 從redis中獲取map物件 */
    public static Map<String, String> hgetall(String key) {
        Jedis jedis = null;
        try{
            jedis = jedisPool.getResource();
            Map<String, String> rtn = jedis.hgetAll(key);
            return rtn;
        } catch(Exception e) {
            logger.error("hgetall方法報錯:key=" + key, e);
            throw new RuntimeException("hgetall方法報錯。");
        } finally {
            if(jedis != null) {
                jedisPool.returnResource(jedis);
            }
        }
    }

    /** 往redis中設定List物件 */
    public static void setList(String key, List<String> list) {
        if(list != null) {
            Jedis jedis = null;
            try{
                jedis = jedisPool.getResource();
                jedis.del(key);
                for (String str : list) {
                    jedis.rpush(key, str);
                }
            } catch(Exception e) {
                logger.error("setList方法報錯:key=" + key, e);
                throw new RuntimeException("setList方法報錯。");
            } finally {
                if(jedis != null) {
                    jedisPool.returnResource(jedis);
                }
            }
        }
    }
    
    /** 給特定key的值新增制定值,返回新增後該key的值 */
    public static long incrBy(String key, long value) {
        Jedis jedis = null;
        try{
            jedis = jedisPool.getResource();
            long rtn = jedis.incrBy(key, value);
            return rtn;
        } catch(Exception e) {
            logger.error("incrBy方法報錯:key=" + key + ",value=" + value, e);
            throw new RuntimeException("incrBy方法報錯。");
        } finally {
            if(jedis != null) {
                jedisPool.returnResource(jedis);
            }
        }
    }

    /** 給特定key的值減少指定,返回修改後該key的值 */
    public static long decrBy(String key, long value) {
        Jedis jedis = null;
        try{
            jedis = jedisPool.getResource();
            long rtn = jedis.decrBy(key, value);
            return rtn;
        } catch(Exception e) {
            logger.error("decrBy方法報錯:key=" + key + ",value=" + value, e);
            throw new RuntimeException("decrBy方法報錯。");
        } finally {
            if(jedis != null) {
                jedisPool.returnResource(jedis);
            }
        }
    }
    
    /** 判斷key是否已經在快取中存在 */
    public static boolean isKeyExistSetWithExpire(String key, int seconds) {
        Jedis jedis = null;
        try{
            jedis = jedisPool.getResource();
            long rtn = jedis.setnx(key, "1");
            if(1 == rtn && seconds > 0) {
                jedis.expire(key, seconds);
            }
            return rtn == 0;
        } catch(Exception e) {
            logger.error("isKeyExistSetWithExpire方法報錯:key=" + key + ",seconds=" + seconds, e);
            throw new RuntimeException("isKeyExistSetWithExpire方法報錯。");
        } finally {
            if(jedis != null) {
                jedisPool.returnResource(jedis);
            }
        }
    }
    
    /** 設定過期時間的方法 */
    public static void expireByKey(String key, int seconds) {
        Jedis jedis = null;
        try{
            jedis = jedisPool.getResource();
            if(seconds > 0) {
                jedis.expire(key, seconds);
            }
        } catch(Exception e) {
            logger.error("expireByKey方法報錯:key=" + key + ",seconds=" + seconds, e);
            throw new RuntimeException("expireByKey方法報錯。");
        } finally {
            if(jedis != null) {
                jedisPool.returnResource(jedis);
            }
        }
    }
    
    /** 判斷key在快取中是否存在  */
    public static boolean isKeyExist(String key) {
        Jedis jedis = null;
        try{
            jedis = jedisPool.getResource();
            return jedis.exists(key);
        } catch(Exception e) {
            logger.error("isKeyExist方法報錯:key=" + key, e);
            throw new RuntimeException("isKeyExist方法報錯。");
        } finally {
            if(jedis != null) {
                jedisPool.returnResource(jedis);
            }
        }
    }
    
    /** 批量刪除某些字串開頭的快取 */
    public static void batchDel(String key) {
        Jedis jedis = null;
        try{
            jedis = jedisPool.getResource();
            
            Set<String> set = jedis.keys(key +"*");
            Iterator<String> it = set.iterator();
            while(it.hasNext()){
                String keyStr = it.next();
                jedis.del(keyStr);
            }
        } catch(Exception e) {
            logger.error("batchDel方法報錯:key=" + key, e);
            throw new RuntimeException("批量刪除方法報錯。");
        } finally {
            if(jedis != null) {
                jedisPool.returnResource(jedis);
            }
        }
    }
    
    /** 批量查詢某些字串開頭的快取 */
    public static void queryKeys(String key) {
        Jedis jedis = null;
        try{
            jedis = jedisPool.getResource();
            
            Set<String> set = jedis.keys(key +"*");
            Iterator<String> it = set.iterator();
            while(it.hasNext()){
                String keyStr = it.next();
                System.out.println(keyStr);
            }
        } catch(Exception e) {
            logger.error("queryKeys方法報錯:key=" + key, e);
            throw new RuntimeException("批量刪除方法報錯。");
        } finally {
            if(jedis != null) {
                jedisPool.returnResource(jedis);
            }
        }
    }
    
    /**根據表示式查詢redis中的key的集合  */
    public static Set<String> keys(String pattern) {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            return jedis.keys(pattern);
        } catch(Exception e) {
            logger.error("keys方法報錯:key=" + pattern, e);
            throw new RuntimeException("keys方法報錯。");
        } finally {
            if(jedis != null) {
                jedisPool.returnResource(jedis);
            }
        }
    }
    
    /**獲取hash key值下所有Item的key  */
    public static Set<String> hKeys(String pattern) {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            return jedis.hkeys(pattern);
        } catch(Exception e) {
            logger.error("keys方法報錯:key=" + pattern, e);
            throw new RuntimeException("keys方法報錯。");
        } finally {
            if(jedis != null) {
                jedisPool.returnResource(jedis);
            }
        }
    }


}
6.serviceimpl 必須在service實現類加上@Cacheable("getUserById") 這個註解 想做到同步資料 最好在新增和修改的方法上面也加上這個註解 方可實現快取同步

//@Cacheable("getUserById") //標註該方法查詢的結果進入快取,再次訪問時直接讀取快取中的資料
    public List queryUserAll() {
        // TODO Auto-generated method stub
        return userdao.queryAll();
    }

 

注;有可能出現redis資料庫亂碼問題,但是不影響快取 目前這塊正在研究 網上 說的好多都不行