面向接口编程——整合多缓存实例

  在企业级JavaWeb框架中,面对业务的复杂性和变化性,往往一种企业级功能需要开发多套技术以便灵活使用,本文通过Redis和Ehcache的整合,来介绍面向接口编程的方便性。

  • 第一步根据缓存的共性,抽象出接口类:

 

 1 public interface ICacheManager {
 2     
 3     <T extends Object> T get(String cacheName, Object key);
 4 
 5     void put(String cacheName, Object key, Object value);
 6 
 7     void remove(String cacheName, Object key);
 8 
 9     void removeAll(String cacheName);
10     
11 }
  • 第二步分别对Redis和Ehcache做具体实现:
 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 3     xmlns:context="http://www.springframework.org/schema/context" xmlns="http://www.springframework.org/schema/beans"
 4     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
 5                         http://www.springframework.org/schema/context  http://www.springframework.org/schema/context/spring-context-4.0.xsd">
 6 
 7     <description>Jedis Configuration</description>
 8 
 9     <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
10         <!-- 最大连接数 -->
11         <property name="maxTotal" value="${redis.pool.maxTotal}"/>
12         <!-- 最大空闲 -->
13         <property name="maxIdle" value="${redis.pool.maxIdle}"/>
14         <!-- 每次最大连接数 -->
15         <property name="numTestsPerEvictionRun" value="${redis.pool.numTestsPerEvictionRun}"/>
16         <!-- 释放扫描的扫描间隔 -->
17         <property name="timeBetweenEvictionRunsMillis" value="${redis.pool.timeBetweenEvictionRunsMillis}"/>
18         <!-- 连接的最小空闲时间 -->
19         <property name="minEvictableIdleTimeMillis" value="${redis.pool.minEvictableIdleTimeMillis}"/>
20         <!-- 连接控歘按时间多久后释放,当空闲时间>该值且空闲连接>最大空闲连接数时直接释放 -->
21         <property name="softMinEvictableIdleTimeMillis" value="${redis.pool.softMinEvictableIdleTimeMillis}"/>
22         <!-- 获得链接时的最大等待毫秒数,小于0:阻塞不确定时间,默认-1 -->
23         <property name="maxWaitMillis" value="${redis.pool.maxWaitMillis}"/>
24         <!-- 在获得链接的时候检查有效性,默认false -->
25         <property name="testOnBorrow" value="${redis.pool.testOnBorrow}"/>
26         <!-- 在空闲时检查有效性,默认false -->
27         <property name="testWhileIdle" value="${redis.pool.testWhileIdle}"/>
28         <!-- 连接耗尽时是否阻塞,false报异常,true阻塞超时 默认:true-->
29         <property name="blockWhenExhausted" value="${redis.pool.blockWhenExhausted}"/>
30     </bean>
31     
32     <bean id="redisConnectionFactory"
33         class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
34         <constructor-arg index="0" ref="jedisPoolConfig" />
35         <property name="hostName" value="${redis.ip}" />
36         <property name="port" value="${redis.port}" />
37         <property name="password" value="${redis.password}" />
38         <property name="timeout" value="${redis.timeout}" />
39     </bean>
40 
41     <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
42         <property name="connectionFactory" ref="redisConnectionFactory" />
43     </bean>
44 
45     <bean id="redisCacheManager" class="org.springframework.data.redis.cache.RedisCacheManager">
46         <constructor-arg index="0" ref="redisTemplate" />
47     </bean>
48 </beans>

 

 1 public class RedisCacheManagerImpl implements ICacheManager {
 2 
 3     public final static RedisCacheManager redisCacheManager = SpringContextHolder.getBean("redisCacheManager");
 4 
 5     protected static CacheManager getCacheManager() {
 6         return redisCacheManager;
 7     }
 8 
 9     @Override
10     @SuppressWarnings("unchecked")
11     public <T extends Object> T get(String cacheName, Object key) {
12         Cache cache = getCacheManager().getCache(cacheName);
13         Cache.ValueWrapper valueWrapper = cache.get(cacheName + "." + key);
14         return (T) valueWrapper.get();
15     }
16 
17     @Override
18     public void put(String cacheName, Object key, Object value) {
19         Cache cache = getCacheManager().getCache(cacheName);
20         cache.put(cacheName + "." + key, value);
21     }
22 
23     @Override
24     public void remove(String cacheName, Object key) {
25         Cache cache = getCacheManager().getCache(cacheName);
26         cache.evict(cacheName + "." + key);
27     }
28 
29     @Override
30     public void removeAll(String cacheName) {
31         Cache cache = getCacheManager().getCache(cacheName);
32         cache.clear();
33     }
34 }

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <ehcache updateCheck="false" name="defaultCache">
 3 
 4     <!-- 
 5         磁盘存储:将缓存中暂时不使用的对象,转移到硬盘,类似于Windows系统的虚拟内存
 6         path:指定在硬盘上存储对象的路径
 7     -->
 8     <diskStore path="java.io.tmpdir/otc"/>
 9 
10     <!-- 默认缓存配置. -->
11     <defaultCache maxEntriesLocalHeap="100" eternal="false" timeToIdleSeconds="300" timeToLiveSeconds="600"
12                   overflowToDisk="true" maxEntriesLocalDisk="100000"/>
13     
14 </ehcache>

 


1
public class EhCacheManagerImpl implements ICacheManager { 2 3 public final static CacheManager cacheManager = SpringContextHolder.getBean("cacheManager"); 4 5 protected static CacheManager getCacheManager() { 6 return cacheManager; 7 } 8 9 /** 10 * 获得一个Cache,没有则创建一个。 11 * @param cacheName 12 * @return 13 */ 14 private static synchronized Cache getCache(String cacheName) { 15 Cache cache = getCacheManager().getCache(cacheName); 16 if (cache == null) { 17 getCacheManager().addCache(cacheName); 18 cache = getCacheManager().getCache(cacheName); 19 cache.getCacheConfiguration().setEternal(true); 20 } 21 return cache; 22 } 23 24 @Override 25 @SuppressWarnings("unchecked") 26 public <T extends Object> T get(String cacheName, Object key) { 27 Element element = getCache(cacheName).get(key); 28 return element == null ? null : (T) element.getObjectValue(); 29 } 30 31 @Override 32 public void put(String cacheName, Object key, Object value) { 33 Element element = new Element(key, value); 34 getCache(cacheName).put(element); 35 } 36 37 @Override 38 public void remove(String cacheName, Object key) { 39 getCache(cacheName).remove(key); 40 } 41 42 @Override 43 public void removeAll(String cacheName) { 44 Cache cache = getCacheManager().getCache(cacheName); 45 cache.removeAll(true); 46 } 47 }
  • 第三步:创建枚举类和工厂类用于生成对应的缓存类
 1 public enum CacheEnum{
 2     
 3     ehcache("ehCacheManagerImpl", "ehcache 实现"),
 4     redis("redisCacheManagerImpl", "redis 实现");
 5 
 6     private String cacheType;
 7     
 8     private String cacheDesc;
 9 
10     CacheEnum(String cacheType, String cacheDesc) {
11         this.cacheType = cacheType;
12         this.cacheDesc = cacheDesc;
13     }
14 
15     public String getCacheType() {
16         return cacheType;
17     }
18 
19     public String getCacheDesc() {
20         return cacheDesc;
21     }
22 }
 1 public final class CacheFactory {
 2     
 3     /**
 4      * 获取默认缓存对象
 5      * @return
 6      */
 7     public static ICacheManager getCache(){
 8         return getCache(CacheEnum.ehcache);
 9     }
10     
11     /**
12      * 根据类型获取缓存对象
13      * @param cacheType
14      * @return
15      */
16     public static ICacheManager getCache(CacheEnum cacheType){
17         if(cacheType == null)
18             cacheType = CacheEnum.ehcache;
19         return SpringContextHolder.getBean(cacheType.getCacheType());
20     }
21 }

第四步:使用缓存类

  1 @Service
  2 public class DictContextService {
  3     private ICacheManager cacheManager = CacheFactory.getCache();
  4     @Autowired
  5     private DictionaryMapper dictionaryMapper;
  6     @Autowired
  7     private DictionaryItemMapper dictionaryItemMapper;
  8     @Autowired
  9     private JdbcTemplate jdbcTemplate;
 10     
 11     private final String DICTIONARYS_CACHE_KEY = "dictionarys_cache_key";
 12     private final String DICTIONARY_ITEMS_CACKE_KEY = "dictionary_items_cacke";
 13     
 14     /**
 15      * 获取    完整对应后的 有效字典
 16      * @return
 17      */
 18     public Map<String,Dictionary> getMapDictionary(){
 19         List<Dictionary> dictionarys = getValidDictionarys();
 20         Map<String, Dictionary> rltDictMap = new HashMap<String, Dictionary>();
 21         for (Dictionary dictionary : dictionarys) {
 22             if(dictionary.getDictType() == Constant.NUMBER_INTEGER_1 && 
 23                     dictionary.getIsCache() == Constant.NUMBER_INTEGER_1) { //(内部字典)开启缓存的字典
 24                 List<DictionaryItem> dictItems = getDictResponseItems(dictionary.getDictCode()); //获取字典对应的字典项
 25                 dictionary.setDictItems(dictItems);
 26                 rltDictMap.put(dictionary.getDictCode(), dictionary);
 27             }else{
 28                 rltDictMap.put(dictionary.getDictCode(), dictionary);
 29             }
 30         }
 31         return rltDictMap;
 32     }
 33     
 34     /**
 35      * 获取字典项(内部字典项、外部字典项)
 36      * @param dictionary
 37      * @return
 38      */
 39     public List<DictionaryItem> getDictItems(final Dictionary dictionary){
 40         Object[] params = new Object[] {dictionary.getDictCode()};
 41         String querySql = "select dict_item_id dictItemId, dict_code dictCode, item_code itemCode, "
 42                 + " item_name itemName from ct_dictionary_item a where a.DICT_CODE = ?";
 43         
 44         if(dictionary.getDictType() == Constant.NUMBER_INTEGER_2) {
 45             querySql = dictionary.gettSource();
 46             params = null;
 47             String tParam = dictionary.gettParams() == null ? "" : dictionary.gettParams();
 48             Object[] _param = tParam.split(",");
 49             if(_param.length > 0 && StringUtil.isNotEmpty(String.valueOf(_param[0]))) {
 50                 params = _param;
 51             }
 52         }
 53         
 54         List<DictionaryItem> rItemList = jdbcTemplate.query(querySql, params, new RowMapper<DictionaryItem>() {
 55             @Override
 56             public DictionaryItem mapRow(ResultSet rs, int rowNum) throws SQLException {
 57                 DictionaryItem dictItem = new DictionaryItem();
 58                 if(dictionary.getDictType() == Constant.NUMBER_INTEGER_1) {
 59                     dictItem.setDictItemId(rs.getString("dictItemId"));
 60                     dictItem.setDictCode(rs.getString("dictCode"));
 61                     dictItem.setItemCode(rs.getString("itemCode"));
 62                     dictItem.setItemName(rs.getString("itemName"));
 63                 }else {
 64                     dictItem.setDictCode(dictionary.getDictCode());
 65                     dictItem.setItemCode(rs.getString(dictionary.getfCode()));
 66                     dictItem.setItemName(rs.getString(dictionary.getfName()));
 67                 }
 68                 return dictItem;
 69             }
 70             
 71         });
 72         
 73         return rItemList;
 74         
 75     }
 76     
 77     /**
 78      * 获取    字典对应的字典项
 79      * @return
 80      */
 81     public List<DictionaryItem> getDictResponseItems(String dictCode){
 82         if(StringUtil.isEmpty(dictCode))
 83             return null;
 84         List<DictionaryItem> dictionaryItems = getValidDictionaryItems();
 85         List<DictionaryItem> rltItems = new ArrayList<DictionaryItem>();
 86         for (DictionaryItem dictionaryItem : dictionaryItems) {
 87             if(dictCode.equals(dictionaryItem.getDictCode())) {
 88                 rltItems.add(dictionaryItem);
 89             }
 90         }
 91         return rltItems;
 92     }
 93     
 94     /**
 95      * 获取    所有有效的字典
 96      * @return
 97      */
 98     public List<Dictionary> getValidDictionarys(){
 99         List<Dictionary> dictionarys = cacheManager.get(Dictionary.class.getName(), DICTIONARYS_CACHE_KEY);
100         if(dictionarys == null) {
101             dictionarys = dictionaryMapper.getValidDictionarys();
102             cacheManager.put(Dictionary.class.getName(), DICTIONARYS_CACHE_KEY, dictionarys);
103         }
104         return dictionarys;
105     }
106     
107     /**
108      * 获取    所有有效的字典项
109      * @return
110      */
111     public List<DictionaryItem> getValidDictionaryItems(){
112         List<DictionaryItem> dictionaryItems = cacheManager.get(DictionaryItem.class.getName(), DICTIONARY_ITEMS_CACKE_KEY);
113         if(dictionaryItems == null) {
114             dictionaryItems = dictionaryItemMapper.getValidDictionaryItems();
115             cacheManager.put(DictionaryItem.class.getName(), DICTIONARY_ITEMS_CACKE_KEY, dictionaryItems);
116         }
117         return dictionaryItems;
118     }
119 }

 

posted @ 2018-08-21 10:23  用心记录每一天  阅读(447)  评论(0编辑  收藏  举报