spring 和 redis的集成(使用註解方式)

spring 和 redis的集成(使用註解方式)

1.原因

  原因很簡單,某些數據會被頻繁的進行調用,之前是進行查詢數據庫,爲了避免對數據庫的壓力,使用redis進行緩存,在調用接口的時候,先訪問一下redis中是否存在,存在的話就在redis中進行取到,沒有則進行查詢數據庫,並且在將查到的數據存到redis緩存中去。這讓我想到了spring通過切面去定義的Cache不是可以完美的解決這個問題麼。廢話少說。

2.配置文件

需要配置spring的cache管理裏面去,redis在spring的配置不用說了,主要是在SimpleCacheManager中進行註冊,因爲使用了另外的緩存機制。

<bean id="cacheManager" class="org.springframework.cache.support.SimpleCacheManager">
        <property name="caches">
            <set>
                <bean class="XXX.XXXX.XX.RedisCache">
                    <property name="name" value="redis"/>
                    <property name="redisTemplate"  ref="redisTemplate"/>
                    <property name="liveTime" value="${redis.car.liveTime}"/><!-- 設置過期時間 -->
                </bean>
            </set>
        </property>
    </bean>

3.redisCache

 主要是實現了spring 的Cache接口,這樣就可以Cache了。

@Data
@Component
public class RedisCache implements Cache {

    private static final Logger logger = LoggerFactory.getLogger(RedisCache.class);

    /**
     * 區分名稱
     */
    private String name;

    /**
     * redisTemplate
     */
    private RedisTemplate<String, Object> redisTemplate;


    /**
     * 過期時間
     */
    private Long liveTime;

    @Override
    public String getName() {
        return this.name;
    }

    @Override
    public Object getNativeCache() {
        return this.redisTemplate;
    }

    /**
     * 得到數據
     *
     * @param key
     * @return
     */
    @Override
    public ValueWrapper get(Object key) {
        logger.info("get cache, key:{}", key);
        final String keyf = (String) key;
        Object object = null;
        object = redisTemplate.execute((RedisConnection connection) -> {
            byte[] keyb = keyf.getBytes();
            byte[] value = connection.get(keyb);
            if (value == null) {
                return null;
            }
            return toObject(value);
        });
        return (object != null ? new SimpleValueWrapper(object) : null);
    }


    /**
     * 反序列化
     *
     * @param bytes
     * @return
     */
    private Object toObject(byte[] bytes) {
        Object obj = null;
        try (ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
             ObjectInputStream ois = new ObjectInputStream(bis)) {
             obj = ois.readObject();
        } catch (IOException ex) {
            logger.error("IOException", ex);
        } catch (ClassNotFoundException ex) {
            logger.error("ClassNotFoundException", ex);
        }
        return obj;
    }

    @Override
    public <T> T get(Object o, Class<T> aClass) {
        return null;
    }

    /**
     * key-value 的形式放入緩存
     *
     * @param key
     * @param value
     */
    @Override
    public void put(Object key, Object value) {
        logger.info("put cache, key:{}", key);
        final String keyf = (String) key;
        final Object valuef = value;

        redisTemplate.execute((RedisConnection connection) -> {
            byte[] keyb = keyf.getBytes();
            byte[] valueb = toByteArray(valuef);
            connection.set(keyb, valueb);
            if (liveTime > 0L) {
                connection.expire(keyb, liveTime);
            }
            return 1L;
        });
    }

    /**
     * 序列化成二進制
     *
     * @param obj
     * @return
     */
    private byte[] toByteArray(Object obj) {
        byte[] bytes = null;
        try (ByteArrayOutputStream bos = new ByteArrayOutputStream();
             ObjectOutputStream oos = new ObjectOutputStream(bos)) {

            oos.writeObject(obj);
            oos.flush();
            bytes = bos.toByteArray();
        } catch (IOException ex) {
            logger.error("IOException", ex);
        }
        return bytes;
    }

    @Override
    public ValueWrapper putIfAbsent(Object o, Object o1) {
        return null;
    }

    /**
     * 通過對應的key 進行刪除緩存
     *
     * @param key
     */
    @Override
    public void evict(Object key) {
        logger.info("delete cache ,key:{}", key);
        final String keyf = (String) key;
        redisTemplate.execute((RedisConnection connection) -> {
            return connection.del(keyf.getBytes());
        });
    }

    /**
     * 清除緩存
     */
    @Override
    public void clear() {
        redisTemplate.execute((RedisConnection connection) -> {
            connection.flushDb();
            return "success";
        });
    }
}

4. @Cacheable @CacheEvint

 Cacheable註解是進入該方法的時候,去查看緩存中是否存在,如果存在的話,直接從緩存中去拿到數據,不進入方法。如果緩存中不存在,則進入該方法將方法的返回值按照一定的規則,進行保存到緩存中去。
CacheEvint註解則是清除緩存,返回類型可以爲void,註解是通過傳過來的參數和註解上的key定義的規則,進行刪除緩存中對應的值。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章