簡單rides和Memory切換快取框架(一)
阿新 • • 發佈:2018-12-12
(一) 內容簡介,父類以及子類結構,重點在於通過@Service實現類,判斷型別來new出不同的快取實現類
首先要寫一個快取介面CacheService,來統一規定快取的必要操作.
public interface CacheService { //當前快取的型別 String getType(); //清空快取內容 void clear(); void putString(String key, String value); void putString(String key, String value, int seconds); String getString(String key); void putObject(String key, Object value) throws IOException; void putObject(String key, Object value, int seconds) throws IOException; <T> T getObject(String key, Class<T> clazz) throws IOException; <T> List<T> getList(String key, Class<T> clazz) throws IOException; <T> PageInfo<T> getPageList(String key, Class<T> clazz) throws IOException; }
接下來寫@service實現類,看類的呼叫過程,每次都會判斷一下使用了哪個型別的快取,當然這兩個快取也都實現了CacheService介面,只要以此按照自己的方法實現就行了
import java.io.IOException; import java.util.HashMap; import java.util.List; import java.util.Map; import org.springframework.stereotype.Service; import org.springframework.web.context.request.RequestAttributes; import org.springframework.web.context.request.RequestContextHolder; import com.github.pagehelper.PageInfo; import com.w3china.mingjing3.dydata.DataSourceContextHolder; import com.w3china.mingjing3.model.SiteSettings; import com.w3china.mingjing3.web.Constants; import com.w3china.mingjing3.web.service.CacheService; @Service public class CacheServiceImpl implements CacheService { private Map<String, CacheService> cacheMap = new HashMap<>(); private CacheService getCacheService() { //從上下文中取得配置 String attribute = (String) RequestContextHolder.currentRequestAttributes().getAttribute(Constants.SETTINGS, RequestAttributes.SCOPE_REQUEST); if (!cacheMap.containsKey(attribute)) { //根據內容判斷快取型別 if ("redis".equalsIgnoreCase(attribute)){ cacheMap.put(attribute, new RedisCacheService()); } else { cacheMap.put(attribute, new MemoryCacheService()); } } return cacheMap.get(attribute); } public String getType() { return ""; } public void clear() { // do noting. } @Override public String getString(String key) { return getCacheService().getString(key); } @Override public void putString(String key, String value) { putString(key, value, 60); } @Override public void putString(String key, String value, int seconds) { getCacheService().putString(key, value, seconds); } @Override public <T> T getObject(String key, Class<T> clazz) throws IOException { return getCacheService().getObject(key, clazz); } @Override public <T> List<T> getList(String key, Class<T> clazz) throws IOException { return getCacheService().getList(key, clazz); } @Override public <T> PageInfo<T> getPageList(String key, Class<T> clazz) throws IOException { return getCacheService().getPageList(key, clazz); } @Override public void putObject(String key, Object value) throws IOException { putObject(key, value, 60); } @Override public void putObject(String key, Object value, int seconds) throws IOException { getCacheService().putObject(key, value, seconds); } }
舉例放一個RedisCacheService類吧,這裡面用了一下序列化 (還有一個MemoryCacheService類裡面用的是Map實現了類似Rides效果,也打算另寫一篇文章) (還有Redis初始化配置,我打算單獨寫一篇.)
import java.io.IOException; import java.time.Duration; import java.util.List; import java.util.concurrent.TimeUnit; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.connection.RedisPassword; import org.springframework.data.redis.connection.RedisStandaloneConfiguration; import org.springframework.data.redis.connection.jedis.JedisClientConfiguration; import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; import org.springframework.data.redis.core.StringRedisTemplate; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.ObjectMapper; import com.github.pagehelper.PageInfo; import com.w3china.mingjing3.model.SiteSettings; import com.w3china.mingjing3.web.service.CacheService; import redis.clients.jedis.JedisPoolConfig; public class RedisCacheService implements CacheService { private static final Logger logger = LoggerFactory.getLogger(RedisCacheService.class); private StringRedisTemplate redisTemplate; //通過構造方法配置Redis 略,會單寫一篇文章記錄一下 private ObjectMapper om; private ObjectMapper getObjectMapper() { if (om == null) { om = new ObjectMapper(); om.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); } return om; } @Override public String getType() { return "redis"; } @Override public void clear() { // do nothing. } @Override public String getString(String key) { if (redisTemplate.hasKey(key)) { return redisTemplate.opsForValue().get(key); } return null; } @Override public void putString(String key, String value) { putString(key, value, 60); } @Override public void putString(String key, String value, int seconds) { if (value != null) { redisTemplate.opsForValue().set(key, value, seconds, TimeUnit.SECONDS); } } @Override public <T> T getObject(String key, Class<T> clazz) throws IOException { String val = getString(key); if (val == null) return null; return getObjectMapper().readValue(val, clazz); } @Override public <T> List<T> getList(String key, Class<T> clazz) throws IOException { ObjectMapper om = getObjectMapper(); String val = getString(key); if (val == null) return null; JavaType javaType1 = om.getTypeFactory().constructParametricType(List.class, clazz); return getObjectMapper().readValue(val, javaType1); } @Override public <T> PageInfo<T> getPageList(String key, Class<T> clazz) throws IOException { ObjectMapper om = getObjectMapper(); String val = getString(key); if (val == null) return null; JavaType javaType1 = om.getTypeFactory().constructParametricType(PageInfo.class, clazz); return getObjectMapper().readValue(val, javaType1); } @Override public void putObject(String key, Object value) throws IOException { putObject(key, value, 60); } @Override public void putObject(String key, Object value, int seconds) throws IOException { String val = getObjectMapper().writeValueAsString(value); putString(key, val, seconds); } }