溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Spring Boot使用注解集成Redis緩存的方法是什么

發(fā)布時間:2021-12-21 11:53:32 來源:億速云 閱讀:146 作者:iii 欄目:編程語言

這篇文章主要介紹“Spring Boot使用注解集成Redis緩存的方法是什么”,在日常操作中,相信很多人在Spring Boot使用注解集成Redis緩存的方法是什么問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Spring Boot使用注解集成Redis緩存的方法是什么”的疑惑有所幫助!接下來,請跟著小編一起來學(xué)習(xí)吧!

Spring Boot 熟悉后,集成一個外部擴展是一件很容易的事,集成Redis也很簡單,看下面步驟配置:

一、添加pom依賴

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

二、創(chuàng)建 RedisClient.java
注意該類存放的package

package org.springframework.data.redis.connection.jedis;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.UnsupportedEncodingException;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Protocol;
import redis.clients.jedis.exceptions.JedisException;
/**
 * 工具類 RedisClient
 * 因為本類中獲取JedisPool調(diào)用的是JedisConnectionFactory中protected修飾的方法fetchJedisConnector()
 * 所以該類需要與JedisConnectionFactory在同一個package中
 *
 * @author 單紅宇(CSDN CATOOP)
 * @create 2017年4月9日
 */
public class RedisClient {
    private static Logger logger = LoggerFactory.getLogger(RedisClient.class);
    private JedisConnectionFactory factory;
    public RedisClient(JedisConnectionFactory factory) {
        super();
        this.factory = factory;
    }
    /**
     * put操作(存儲序列化對象)+ 生效時間
     * 
     * @param key
     * @param value
     * @return
     */
    public void putObject(final String key, final Object value, final int cacheSeconds) {
        if (StringUtils.isNotBlank(key)) {
            redisTemplete(key, new RedisExecute<Object>() {
                @Override
                public Object doInvoker(Jedis jedis) {
                    try {
                        jedis.setex(key.getBytes(Protocol.CHARSET), cacheSeconds, serialize(value));
                    } catch (UnsupportedEncodingException e) {
                    }
                    return null;
                }
            });
        }
    }
    /**
     * get操作(獲取序列化對象)
     * 
     * @param key
     * @return
     */
    public Object getObject(final String key) {
        return redisTemplete(key, new RedisExecute<Object>() {
            @Override
            public Object doInvoker(Jedis jedis) {
                try {
                    byte[] byteKey = key.getBytes(Protocol.CHARSET);
                    byte[] byteValue = jedis.get(byteKey);
                    if (byteValue != null) {
                        return deserialize(byteValue);
                    }
                } catch (UnsupportedEncodingException e) {
                    return null;
                }
                return null;
            }
        });
    }
    /**
     * setex操作
     * 
     * @param key
     *            鍵
     * @param value
     *            值
     * @param cacheSeconds
     *            超時時間,0為不超時
     * @return
     */
    public String set(final String key, final String value, final int cacheSeconds) {
        return redisTemplete(key, new RedisExecute<String>() {
            @Override
            public String doInvoker(Jedis jedis) {
                if (cacheSeconds == 0) {
                    return jedis.set(key, value);
                }
                return jedis.setex(key, cacheSeconds, value);
            }
        });
    }
    /**
     * get操作
     * 
     * @param key
     *            鍵
     * @return 值
     */
    public String get(final String key) {
        return redisTemplete(key, new RedisExecute<String>() {
            @Override
            public String doInvoker(Jedis jedis) {
                String value = jedis.get(key);
                return StringUtils.isNotBlank(value) && !"nil".equalsIgnoreCase(value) ? value : null;
            }
        });
    }
    /**
     * del操作
     * 
     * @param key
     *            鍵
     * @return
     */
    public long del(final String key) {
        return redisTemplete(key, new RedisExecute<Long>() {
            @Override
            public Long doInvoker(Jedis jedis) {
                return jedis.del(key);
            }
        });
    }
    /**
     * 獲取資源
     * 
     * @return
     * @throws JedisException
     */
    public Jedis getResource() throws JedisException {
        Jedis jedis = null;
        try {
            jedis = factory.fetchJedisConnector();
        } catch (JedisException e) {
            logger.error("getResource.", e);
            returnBrokenResource(jedis);
            throw e;
        }
        return jedis;
    }
    /**
     * 獲取資源
     * 
     * @return
     * @throws JedisException
     */
    public Jedis getJedis() throws JedisException {
        return getResource();
    }
    /**
     * 歸還資源
     * 
     * @param jedis
     * @param isBroken
     */
    public void returnBrokenResource(Jedis jedis) {
        if (jedis != null) {
            jedis.close();
        }
    }
    /**
     * 釋放資源
     * 
     * @param jedis
     * @param isBroken
     */
    public void returnResource(Jedis jedis) {
        if (jedis != null) {
            jedis.close();
        }
    }
    /**
     * 操作jedis客戶端模板
     * 
     * @param key
     * @param execute
     * @return
     */
    public <R> R redisTemplete(String key, RedisExecute<R> execute) {
        Jedis jedis = null;
        try {
            jedis = getResource();
            if (jedis == null) {
                return null;
            }
            return execute.doInvoker(jedis);
        } catch (Exception e) {
            logger.error("operator redis api fail,{}", key, e);
        } finally {
            returnResource(jedis);
        }
        return null;
    }
    /**
     * 功能簡述: 對實體Bean進(jìn)行序列化操作.
     * 
     * @param source
     *            待轉(zhuǎn)換的實體
     * @return 轉(zhuǎn)換之后的字節(jié)數(shù)組
     * @throws Exception
     */
    public static byte[] serialize(Object source) {
        ByteArrayOutputStream byteOut = null;
        ObjectOutputStream ObjOut = null;
        try {
            byteOut = new ByteArrayOutputStream();
            ObjOut = new ObjectOutputStream(byteOut);
            ObjOut.writeObject(source);
            ObjOut.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (null != ObjOut) {
                    ObjOut.close();
                }
            } catch (IOException e) {
                ObjOut = null;
            }
        }
        return byteOut.toByteArray();
    }
    /**
     * 功能簡述: 將字節(jié)數(shù)組反序列化為實體Bean.
     * 
     * @param source
     *            需要進(jìn)行反序列化的字節(jié)數(shù)組
     * @return 反序列化后的實體Bean
     * @throws Exception
     */
    public static Object deserialize(byte[] source) {
        ObjectInputStream ObjIn = null;
        Object retVal = null;
        try {
            ByteArrayInputStream byteIn = new ByteArrayInputStream(source);
            ObjIn = new ObjectInputStream(byteIn);
            retVal = ObjIn.readObject();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (null != ObjIn) {
                    ObjIn.close();
                }
            } catch (IOException e) {
                ObjIn = null;
            }
        }
        return retVal;
    }
    interface RedisExecute<T> {
        T doInvoker(Jedis jedis);
    }
}

三、創(chuàng)建Redis配置類
   RedisConfig.java

package com.shanhy.example.redis;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.connection.jedis.RedisClient;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
/**
 * Redis配置
 * 
 * @author 單紅宇(CSDN catoop)
 * @create 2016年9月12日
 */
@Configuration
public class RedisConfig {
    @Bean
    public RedisTemplate<String, Object> redisTemplate(JedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
        template.setConnectionFactory(factory);
        template.setKeySerializer(new StringRedisSerializer());
        template.setValueSerializer(new RedisObjectSerializer());
        template.afterPropertiesSet();
        return template;
    }
    @Bean
    public RedisClient redisClient(JedisConnectionFactory factory){
        return new RedisClient(factory);
    }
}
RedisObjectSerializer.java
package com.shanhy.example.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;
/**
 * 實現(xiàn)對象的序列化接口
 * @author   單紅宇(365384722)
 * @myblog  http://blog.csdn.net/catoop/
 * @create    2017年4月9日
 */
public class RedisObjectSerializer implements RedisSerializer<Object> {
    private Converter<Object, byte[]> serializer = new SerializingConverter();
    private Converter<byte[], Object> deserializer = new DeserializingConverter();
    static final byte[] EMPTY_ARRAY = new byte[0];
    @Override
    public Object deserialize(byte[] bytes) {
        if (isEmpty(bytes)) {
            return null;
        }
        try {
            return deserializer.convert(bytes);
        } catch (Exception ex) {
            throw new SerializationException("Cannot deserialize", ex);
        }
    }
    @Override
    public byte[] serialize(Object object) {
        if (object == null) {
            return EMPTY_ARRAY;
        }
        try {
            return serializer.convert(object);
        } catch (Exception ex) {
            return EMPTY_ARRAY;
        }
    }
    private boolean isEmpty(byte[] data) {
        return (data == null || data.length == 0);
    }
}

四、創(chuàng)建測試方法
下面代碼隨便放一個Controller里

@Autowired
private RedisTemplate<String, Object> redisTemplate;
/**
 * 緩存測試
 *
 * @return
 * @author  SHANHY
 * @create  2016年9月12日
 */
@RequestMapping("/redisTest")
public String redisTest() {
    try {
        redisTemplate.opsForValue().set("test-key", "redis測試內(nèi)容", 2, TimeUnit.SECONDS);// 緩存有效期2秒
        logger.info("從Redis中讀取數(shù)據(jù):" + redisTemplate.opsForValue().get("test-key").toString());
        TimeUnit.SECONDS.sleep(3);
        logger.info("等待3秒后嘗試讀取過期的數(shù)據(jù):" + redisTemplate.opsForValue().get("test-key"));
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    return "OK";
}

五、配置文件配置Redis
   application.yml

spring:
  # Redis配置
  redis:
    host: 192.168.1.101
    port: 6379
    password:
    # 連接超時時間(毫秒)
    timeout: 10000
    pool:
      max-idle: 20
      min-idle: 5
      max-active: 20
      max-wait: 2

這樣就完成了Redis的配置,可以正常使用 redisTemplate 了。

atoop/article/details/71275331

一、創(chuàng)建 Caching 配置類

RedisKeys.java

package com.shanhy.example.redis;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.PostConstruct;
import org.springframework.stereotype.Component;
/**
 * 方法緩存key常量
 * 
 * @author SHANHY
 */
@Component
public class RedisKeys {
    // 測試 begin
    public static final String _CACHE_TEST = "_cache_test";// 緩存key
    public static final Long _CACHE_TEST_SECOND = 20L;// 緩存時間
    // 測試 end
    // 根據(jù)key設(shè)定具體的緩存時間
    private Map<String, Long> expiresMap = null;
    @PostConstruct
    public void init(){
        expiresMap = new HashMap<>();
        expiresMap.put(_CACHE_TEST, _CACHE_TEST_SECOND);
    }
    public Map<String, Long> getExpiresMap(){
        return this.expiresMap;
    }
}

CachingConfig.java

package com.shanhy.example.redis;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
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.cache.interceptor.SimpleKeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.core.RedisTemplate;
/**
 * 注解式環(huán)境管理
 * 
 * @author 單紅宇(CSDN catoop)
 * @create 2016年9月12日
 */
@Configuration
@EnableCaching
public class CachingConfig extends CachingConfigurerSupport {
    /**
     * 在使用@Cacheable時,如果不指定key,則使用找個默認(rèn)的key生成器生成的key
     *
     * @return
     * 
     * @author 單紅宇(CSDN CATOOP)
     * @create 2017年3月11日
     */
    @Override
    public KeyGenerator keyGenerator() {
        return new SimpleKeyGenerator() {
            /**
             * 對參數(shù)進(jìn)行拼接后MD5
             */
            @Override
            public Object generate(Object target, Method method, Object... params) {
                StringBuilder sb = new StringBuilder();
                sb.append(target.getClass().getName());
                sb.append(".").append(method.getName());
                StringBuilder paramsSb = new StringBuilder();
                for (Object param : params) {
                    // 如果不指定,默認(rèn)生成包含到鍵值中
                    if (param != null) {
                        paramsSb.append(param.toString());
                    }
                }
                if (paramsSb.length() > 0) {
                    sb.append("_").append(paramsSb);
                }
                return sb.toString();
            }
        };
    }
    /**
     * 管理緩存
     *
     * @param redisTemplate
     * @return
     */
    @Bean
    public CacheManager cacheManager(RedisTemplate<String, Object> redisTemplate, RedisKeys redisKeys) {
        RedisCacheManager rcm = new RedisCacheManager(redisTemplate);
        // 設(shè)置緩存默認(rèn)過期時間(全局的)
        rcm.setDefaultExpiration(1800);// 30分鐘
        // 根據(jù)key設(shè)定具體的緩存時間,key統(tǒng)一放在常量類RedisKeys中
        rcm.setExpires(redisKeys.getExpiresMap());
        List<String> cacheNames = new ArrayList<String>(redisKeys.getExpiresMap().keySet());
        rcm.setCacheNames(cacheNames);
        return rcm;
    }
}

二、創(chuàng)建需要緩存數(shù)據(jù)的類

TestService.java

package com.shanhy.example.service;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import com.shanhy.example.redis.RedisKeys;
@Service
public class TestService {
    /**
     * 固定key
     *
     * @return
     * @author SHANHY
     * @create  2017年4月9日
     */
    @Cacheable(value = RedisKeys._CACHE_TEST, key = "'" + RedisKeys._CACHE_TEST + "'")
    public String testCache() {
        return RandomStringUtils.randomNumeric(4);
    }
    /**
     * 存儲在Redis中的key自動生成,生成規(guī)則詳見CachingConfig.keyGenerator()方法
     *
     * @param str1
     * @param str2
     * @return
     * @author SHANHY
     * @create  2017年4月9日
     */
    @Cacheable(value = RedisKeys._CACHE_TEST)
    public String testCache2(String str1, String str2) {
        return RandomStringUtils.randomNumeric(4);
    }
}

說明一下,其中 @Cacheable 中的 value 值是在 CachingConfig的cacheManager 中配置的,那里是為了配置我們的緩存有效時間。其中 methodKeyGenerator 為 CachingConfig 中聲明的 KeyGenerator。
另外,Cache 相關(guān)的注解還有幾個,大家可以了解下,不過我們常用的就是 @Cacheable,一般情況也可以滿足我們的大部分需求了。還有 @Cacheable 也可以配置表達(dá)式根據(jù)我們傳遞的參數(shù)值判斷是否需要緩存。
注: TestService 中 testCache 中的 mapper.get 大家不用關(guān)心,這里面我只是訪問了一下數(shù)據(jù)庫而已,你只需要在這里做自己的業(yè)務(wù)代碼即可。

三、測試方法

下面代碼,隨便放一個 Controller 中

package com.shanhy.example.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.jedis.RedisClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.shanhy.example.service.TestService;
/**
 * 測試Controller
 * 
 * @author 單紅宇(365384722)
 * @myblog http://blog.csdn.net/catoop/
 * @create 2017年4月9日
 */
@RestController
@RequestMapping("/test")
public class TestController {
    private static final Logger LOG = LoggerFactory.getLogger(TestController.class);
    @Autowired
    private RedisClient redisClient;
    @Autowired
    private TestService testService;
    @GetMapping("/redisCache")
    public String redisCache() {
        redisClient.set("shanhy", "hello,shanhy", 100);
        LOG.info("getRedisValue = {}", redisClient.get("shanhy"));
        testService.testCache2("aaa", "bbb");
        return testService.testCache();
    }
}

到此,關(guān)于“Spring Boot使用注解集成Redis緩存的方法是什么”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識,請繼續(xù)關(guān)注億速云網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI