springboot 整合redis 做快取
阿新 • • 發佈:2018-11-23
一、新增依賴jar包
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>2.0.5.RELEASE</version>
</dependency>
二、新建一個RedisConfig.java類
pakage com.dm.krystal.redis; import com.alibaba.fastjson.support.spring.GenericFastJsonRedisSerializer; import org.springframework.cache.CacheManager; import org.springframework.cache.annotation.CachingConfigurerSupport; import org.springframework.cache.annotation.EnableCaching; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.data.redis.cache.RedisCacheConfiguration; import org.springframework.data.redis.cache.RedisCacheManager; import org.springframework.data.redis.cache.RedisCacheWriter; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.StringRedisSerializer; import java.time.Duration; @Configuration @EnableCaching//開啟註解 public class RedisConfig extends CachingConfigurerSupport { @Bean @Primary public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) { RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig() .entryTtl(Duration.ofHours(1)); // 設定快取有效期一小時 return RedisCacheManager .builder(RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory)) .cacheDefaults(redisCacheConfiguration).build(); } @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) { RedisTemplate<String, Object> template = new RedisTemplate<String, Object>(); // set key serializer StringRedisSerializer serializer = new StringRedisSerializer(); // 設定key序列化類,否則key前面會多了一些亂碼 template.setKeySerializer(serializer); template.setHashKeySerializer(serializer); // fastjson serializer GenericFastJsonRedisSerializer fastSerializer = new GenericFastJsonRedisSerializer(); template.setValueSerializer(fastSerializer); template.setHashValueSerializer(fastSerializer); // 如果 KeySerializer 或者 ValueSerializer 沒有配置,則對應的 KeySerializer、ValueSerializer 才使用這個 Serializer template.setDefaultSerializer(fastSerializer); LettuceConnectionFactory factory = (LettuceConnectionFactory) redisConnectionFactory; // factory template.setConnectionFactory(redisConnectionFactory); template.afterPropertiesSet(); return template; } @Bean public RedisFactory redisFactory(RedisConnectionFactory redisConnectionFactory) { RedisFactory redisFactory = new RedisFactory(); redisFactory.setRedisTemplate(redisTemplate(redisConnectionFactory)); return redisFactory; } }
三、新建一個用於儲存資料的RedisFactory.java工具類
package com.dm.krystal.redis; import org.springframework.dao.DataAccessException; import org.springframework.data.redis.connection.RedisConnection; import org.springframework.data.redis.core.RedisCallback; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.RedisSerializer; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Set; public class RedisFactory { private String mutexDefaultExt = "_mutex"; private long mutextDefaultExpireTime = 60l; private RedisTemplate<String, Object> redisTemplate; public RedisTemplate<String, Object> getRedisTemplate() { return redisTemplate; } public void setRedisTemplate( RedisTemplate<String, Object> redisTemplate) { this.redisTemplate = redisTemplate; } public void saveByStr(final String key, final String value) { redisTemplate.execute(new RedisCallback() { @Override public String doInRedis(RedisConnection connection) throws DataAccessException { RedisSerializer<String> redisSerializer = redisTemplate.getStringSerializer(); connection.set( redisSerializer.serialize( key), redisSerializer.serialize( value)); return null; } }); } public String getByStr(final String key) { return (String) (redisTemplate.execute(new RedisCallback() { @Override public String doInRedis(RedisConnection connection) throws DataAccessException { RedisSerializer<String> redisSerializer = redisTemplate.getStringSerializer(); byte[] keys = redisSerializer.serialize(key); if (connection.exists(keys)) { byte[] values = connection.get(keys); String retval = redisSerializer.deserialize(values); return retval; } return null; } })); } public String getSetByStr(final String key, final String value) { return (String) (redisTemplate.execute(new RedisCallback() { @Override public String doInRedis(RedisConnection connection) throws DataAccessException { RedisSerializer<String> redisSerializer = redisTemplate.getStringSerializer(); byte[] keys = redisSerializer.serialize(key); if (connection.exists(keys)) { byte[] values = redisSerializer.serialize(value); byte[] results = connection.getSet(keys, values); String retval = redisSerializer.deserialize(results); return retval; } return null; } })); } public void saveByStr(final String key, final long timer, final String value) { redisTemplate.execute(new RedisCallback() { @Override public String doInRedis(RedisConnection connection) throws DataAccessException { RedisSerializer<String> redisSerializer = redisTemplate.getStringSerializer(); connection.set( redisSerializer.serialize( key), redisSerializer.serialize( value)); if (timer != -1) { byte[] keys = redisSerializer.serialize(key); connection.expire(keys, timer); } return null; } }); } public <T> void saveByObj(final String key, final T value) { redisTemplate.execute(new RedisCallback<T>() { @Override public T doInRedis(RedisConnection connection) throws DataAccessException { RedisSerializer<T> redisSerializer = (RedisSerializer<T>) (redisTemplate.getValueSerializer()); connection.set( redisTemplate.getStringSerializer().serialize(key), redisSerializer.serialize(value)); return null; } }); } public <T> T getByObj(final String key) { return (T) (redisTemplate.execute(new RedisCallback<T>() { @Override public T doInRedis(RedisConnection connection) throws DataAccessException { byte[] keys = redisTemplate.getStringSerializer().serialize(key); if (connection.exists(keys)) { byte[] values = connection.get(keys); RedisSerializer<T> redisSerializer = (RedisSerializer<T>) (redisTemplate.getValueSerializer()); T retval = redisSerializer.deserialize(values); return retval; } return null; } })); } public <T> T getSetByObj(final String key, final T value) { return (T) (redisTemplate.execute(new RedisCallback<T>() { @Override public T doInRedis(RedisConnection connection) throws DataAccessException { byte[] keys = redisTemplate.getStringSerializer().serialize(key); if (connection.exists(keys)) { RedisSerializer<T> redisSerializer = (RedisSerializer<T>) (redisTemplate.getValueSerializer()); byte[] values = redisSerializer.serialize(value); byte[] results = connection.getSet(keys, values); T retval = redisSerializer.deserialize(results); return retval; } return null; } })); } public <T> void saveByObj(final String key, final long timer, final T value) { redisTemplate.execute(new RedisCallback<T>() { @Override public T doInRedis(RedisConnection connection) throws DataAccessException { RedisSerializer<T> redisSerializer = (RedisSerializer<T>) (redisTemplate.getValueSerializer()); connection.set( redisTemplate.getStringSerializer().serialize(key), redisSerializer.serialize(value)); if (timer != -1) { byte[] keys = redisTemplate.getStringSerializer().serialize(key); connection.expire(keys, timer); } return null; } }); } public Long delete(final String key) { return (Long) (redisTemplate.execute(new RedisCallback<Object>() { @Override public Object doInRedis(RedisConnection connection) throws DataAccessException { return connection.del( redisTemplate.getStringSerializer().serialize( key)); } })); } public void deleteByPrex(final String name) { List<String> allKeys = getAllKeyByName(name); allKeys.forEach((key) -> { delete(key); }); } public List<String> getAllKeyByName(final String name) { Set<byte[]> keyBytes = (Set<byte[]>) (redisTemplate.execute(new RedisCallback<Object>() { @Override public Object doInRedis(RedisConnection connection) throws DataAccessException { byte[] keys = redisTemplate.getStringSerializer().serialize(name + "*"); return connection.keys(keys); } })); if (keyBytes != null && keyBytes.size() > 0) { List<String> resultList = new ArrayList<String>(); for (Iterator<byte[]> it = keyBytes.iterator(); it.hasNext(); ) { String keyName = new String(it.next()); resultList.add(keyName); } return resultList; } else { return null; } } public boolean setNX(final String key) { return this.setNX(key, "1"); } public boolean setNX(final String key, final String value) { return this.setNX(key, -1, value); } public boolean setNX(final String key, final long timer, final String value) { return (boolean) (redisTemplate.execute(new RedisCallback<Object>() { @Override public Object doInRedis(RedisConnection connection) throws DataAccessException { boolean nxFlag = connection.setNX( redisTemplate.getStringSerializer().serialize( key), redisTemplate.getStringSerializer().serialize( value)); if (timer != -1) { byte[] keys = redisTemplate.getStringSerializer().serialize(key); connection.expire(keys, timer); } return nxFlag; } })); } public boolean mutexKey(String key, long validTimer, long mutexTimeout) { boolean mutexFlag = false; try { String newKey = key + this.mutexDefaultExt; if (mutexTimeout == -1) { //無限時等待 while (true) { long value = System.currentTimeMillis() + validTimer + 1; boolean acquired = this.setNX(newKey, validTimer, String.valueOf(value)); if (acquired) { mutexFlag = true; break; } else { long oldValue = Long.valueOf(this.getByStr(newKey)); //超時 if (oldValue < System.currentTimeMillis()) { long lastValue = Long.valueOf(getSetByStr(newKey, String.valueOf(value))); if (lastValue == oldValue) { // 本執行緒獲取鎖成功 mutexFlag = true; break; } else { //已被其他執行緒搶佔 mutexFlag = false; } } else { mutexFlag = false; } } Thread.sleep(300); } } else { //限時等待 long curnano = System.nanoTime(); long nanoMutexTimeout = mutexTimeout * 1000l * 1000l * 1000l; do { long value = System.currentTimeMillis() + validTimer + 1; boolean acquired = this.setNX(newKey, validTimer, String.valueOf(value)); if (acquired) { mutexFlag = true; break; } else { long oldValue = Long.valueOf(this.getByStr(newKey)); //超時 if (oldValue < System.currentTimeMillis()) { long lastValue = Long.valueOf(getSetByStr(newKey, String.valueOf(value))); if (lastValue == oldValue) { // 本執行緒獲取鎖成功 mutexFlag = true; break; } else { //已被其他執行緒搶佔 mutexFlag = false; } } else { mutexFlag = false; } } Thread.sleep(300); } while ((System.nanoTime() - curnano) < nanoMutexTimeout); } } catch (Exception ex) { mutexFlag = false; } return mutexFlag; } public Long mutexRemove(String key) { if (key.contains(mutexDefaultExt)) { return this.delete(key); } else { return this.delete(key + mutexDefaultExt); } } public boolean updateLockAndTransactionByStr(final String[] keys, final String[] values) { try { return (boolean) (redisTemplate.execute(new RedisCallback<Object>() { @Override public Object doInRedis(RedisConnection connection) throws DataAccessException { RedisSerializer<String> redisSerializer = redisTemplate.getStringSerializer(); for (String key : keys) { if (mutexKey(key, mutextDefaultExpireTime, mutextDefaultExpireTime)) { return false; } } for (String key : keys) { connection.watch(redisSerializer.serialize(key + mutexDefaultExt)); } connection.multi(); for (int i = 0; i < keys.length; i++) { connection.set(redisSerializer.serialize(keys[i] + mutexDefaultExt), redisSerializer.serialize(values[i])); } List<Object> results = connection.exec(); if (results == null || results.isEmpty()) { return false; } else { return true; } } })); } catch (Exception ex) { return false; } } public boolean updateTransactionByStr(final String[] keys, final String[] values) { try { return (boolean) (redisTemplate.execute(new RedisCallback<Object>() { @Override public Object doInRedis(RedisConnection connection) throws DataAccessException { RedisSerializer<String> redisSerializer = redisTemplate.getStringSerializer(); for (String key : keys) { connection.watch(redisSerializer.serialize(key + mutexDefaultExt)); } connection.multi(); for (int i = 0; i < keys.length; i++) { connection.set(redisSerializer.serialize(keys[i] + mutexDefaultExt), redisSerializer.serialize(values[i])); } List<Object> results = connection.exec(); if (results == null || results.isEmpty()) { return false; } else { return true; } } })); } catch (Exception ex) { return false; } } public boolean updateLockAndTransactionByObj(final String[] keys, final Object[] values) { try { return (boolean) (redisTemplate.execute(new RedisCallback<Object>() { @Override public Object doInRedis(RedisConnection connection) throws DataAccessException { for (String key : keys) { if (mutexKey(key, mutextDefaultExpireTime, mutextDefaultExpireTime)) { return false; } } for (String key : keys) { connection.watch(redisTemplate.getStringSerializer().serialize(key + mutexDefaultExt)); } connection.multi(); for (int i = 0; i < keys.length; i++) { RedisSerializer redisSerializer = (RedisSerializer) (redisTemplate.getValueSerializer()); connection.set(redisTemplate.getStringSerializer().serialize(keys[i] + mutexDefaultExt), redisSerializer.serialize(values[i])); } List<Object> results = connection.exec(); if (results == null || results.isEmpty()) { return false; } else { return true; } } })); } catch (Exception ex) { return false; } } public boolean updateTransactionByObj(final String[] keys, final Object[] values) { try { return (boolean) (redisTemplate.execute(new RedisCallback<Object>() { @Override public Object doInRedis(RedisConnection connection) throws DataAccessException { for (String key : keys) { connection.watch(redisTemplate.getStringSerializer().serialize(key + mutexDefaultExt)); } connection.multi(); for (int i = 0; i < keys.length; i++) { RedisSerializer redisSerializer = (RedisSerializer) (redisTemplate.getValueSerializer()); connection.set(redisTemplate.getStringSerializer().serialize(keys[i] + mutexDefaultExt), redisSerializer.serialize(values[i])); } List<Object> results = connection.exec(); if (results == null || results.isEmpty()) { return false; } else { return true; } } })); } catch (Exception ex) { return false; } } public boolean extPushQueue(final String queueName, final String queueTitle, final long timeout) { boolean result = false; result = (Boolean) redisTemplate.execute(new RedisCallback<Object>() { @Override public Object doInRedis(RedisConnection connection) throws DataAccessException { byte[] keys = redisTemplate.getStringSerializer().serialize(queueName); byte[] values = redisTemplate.getStringSerializer().serialize(queueTitle); if (connection.lPush(keys, values) > 0) { if (timeout != -1l) { connection.expire(keys, timeout); } return Boolean.TRUE; } else { return Boolean.FALSE; } } }); return result; } public boolean extExpireQueue(final String queueName, final long timeout) { boolean result = false; result = (Boolean) redisTemplate.execute(new RedisCallback<Object>() { @Override public Object doInRedis(RedisConnection connection) throws DataAccessException { byte[] keys = redisTemplate.getStringSerializer().serialize(queueName); if (timeout != -1l) { return connection.expire(keys, timeout); } else { return true; } } }); return result; } public boolean extRemoveQueueMsg(final String queueName, final String msg) { boolean result = false; Long back = (Long) redisTemplate.execute(new RedisCallback<Object>() { @Override public Object doInRedis(RedisConnection connection) throws DataAccessException { byte[] keys = redisTemplate.getStringSerializer().serialize(queueName); byte[] msgs = redisTemplate.getStringSerializer().serialize(msg); return connection.lRem(keys, 0l, msgs); } }); if (back.longValue() == 0l) { result = false; } else { result = true; } return result; } public List<String> extTraversalQueue(final String queueName) { List<String> result = null; List<byte[]> valueList = (List<byte[]>) redisTemplate.execute(new RedisCallback<List<byte[]>>() { @Override public List<byte[]> doInRedis(RedisConnection connection) throws DataAccessException { byte[] keys = redisTemplate.getStringSerializer().serialize(queueName); List<byte[]> valueList = connection.lRange(keys, 0l, -1l); return valueList; } }); if (valueList != null && valueList.size() > 0) { result = new ArrayList<String>(); for (int i = 0; i < valueList.size(); i++) { byte[] valBytes = valueList.get(i); result.add(new String(valBytes)); } } return result; } public boolean extTraversalQueueMsg(final String queueName, final String msg) { boolean result = false; Boolean back = (Boolean) redisTemplate.execute(new RedisCallback<Object>() { @Override public Object doInRedis(RedisConnection connection) throws DataAccessException { byte[] keys = redisTemplate.getStringSerializer().serialize(queueName); List<byte[]> valueList = connection.lRange(keys, 0l, -1l); Boolean find = Boolean.FALSE; if (valueList != null && valueList.size() > 0) { for (int i = 0; i < valueList.size(); i++) { byte[] valBytes = valueList.get(i); String matchKey = new String(valBytes); if (matchKey.equals(msg)) { find = Boolean.TRUE; break; } } } return find; } }); if (!back.booleanValue()) { result = false; } else { result = true; } return result; } public boolean extHMapSave(final String key, final String field, final String value) { boolean result = false; Boolean back = Boolean.FALSE; try { back = (Boolean) redisTemplate.execute(new RedisCallback<Boolean>() { @Override public Boolean doInRedis(RedisConnection connection) throws DataAccessException { connection.hSet( redisTemplate.getStringSerializer().serialize( key), redisTemplate.getStringSerializer().serialize( field), redisTemplate.getStringSerializer().serialize( value)); return Boolean.TRUE; } }); } catch (Exception ex) { back = Boolean.FALSE; } if (!back.booleanValue()) { result = false; } else { result = true; } return result; } public String extHMapGet(final String key, final String field) { return redisTemplate.execute(new RedisCallback<String>() { @Override public String doInRedis(RedisConnection connection) throws DataAccessException { byte[] valBytes = connection.hGet( redisTemplate.getStringSerializer().serialize( key), redisTemplate.getStringSerializer().serialize( field)); if (valBytes == null || valBytes.length == 0) { return null; } else { return new String(valBytes); } } }); } } 四、使用redis做快取
//redis @RequestMapping("queryUserList") public MsgDataBody<List<SysUser>> queryUserList(){ MsgDataBody<List<SysUser>> msgBody = new MsgDataBody<List<SysUser>>(); // MsgBody msgBody=new MsgBody(); msgBody.setCode(Constant.Error.getCode()); msgBody.setMsg("獲取資料失敗"); SysUser sysUser=new SysUser(); List<SysUser> list =new ArrayList<>(); try{ if(redisFactory.getByObj("data")!=null){ JSONArray jsonArray = JSONArray.fromObject(redisFactory.getByObj("data"));//將json字串轉為json物件 list = (List<SysUser>)JSONArray.toCollection(jsonArray,SysUser.class) ;//將 json 物件轉為list 陣列 System.out.println("iam cache 111"); }else { QueryWrapper<SysUser> wrapper = new QueryWrapper<SysUser>(); // wrapper.eq("id","1"); list=iSysUserService.selectList(wrapper); redisFactory.saveByObj("data",60*15,list);//60.15資料在redis存活的時間 System.out.println("iam query111"); } msgBody.setData(list); msgBody.setCode(Constant.Success.getCode()); msgBody.setMsg("獲取資料成功"); }catch (RuntimeException e){ msgBody.setCode(Constant.Error.getCode()); } return msgBody; }
五、注意(其實這個和主題沒啥關係)
上面使用JSONArray.fromObject要引入import net.sf.json.JSONArray, 而不是import com.alibaba.fastjson.JSONArray,idea每次導包時候都是預設引用import com.alibaba.fastjson.JSONArray出問題。