1. 程式人生 > >Java緩存類的實際應用場景

Java緩存類的實際應用場景

不同的 all import none 管理 string xml配置 textutils rri

不要著迷於技術,應把註意力放到問題上。

  一個普通的後臺管理系統,一定會有參數配置。參數配置數據表和其他的數據表是不同的,它的操作基本都是查的操作。參數配置的這些數據信息是貫穿在整個項目中,那麽把他們放到哪裏可以方便類或者jsp的調用?

spring的配置文件有支持緩存類,它的配置如下:

 <!-- 啟用用戶的緩存功能 -->  
    <bean id="userCache" class="org.springframework.security.core.userdetails.cache.EhCacheBasedUserCache">  
        <
property name="cache" ref="userEhCache" /> </bean> <bean id="userEhCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean"> <property name="cacheName" value="userCache" /> <property name="cacheManager" ref="ehcacheManager" /> </
bean> <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager" p:cache-manager-ref="ehcacheManager"/> <bean id="ehcacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" p:config-location="classpath:config/ehcache.xml"/>

  

然後在我們自己的緩存類中加入相應的註解即可:

package cn.wangze.service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import cn.wangze.domain.SysMenu;
import cn.wangze.domain.SysParam;
import cn.wangze.utils.AuthUtils;

@Service
public class SysCacheService{
    
    //具體需要緩存的數據視自己業務而定
    /**
     * 項目中菜單的數據很少變動,所以我們把菜單數據也放到緩存裏面
     * */
    @Autowired
    private SysMenuService<SysMenu> sysMenuService;
    
    /**
     * 註入系統參數的service
     * */
    @Autowired
    private SysParamService<SysParam> SysParamService;
        
    /**
     * 創建Map對象保存系統參數的數據,方便調用
     */
    private Map<String,String> sysParamMap;
    
    /**
     * 通過調用這個方法可以取到緩存的菜單數據
     */
    @Cacheable(value="sysCache",key="methodName")
    public List<SysMenu> queryMenuList(){
        List <SysMenu> list = sysMenuService.queryList();
        if(list == null || list.size() == 0) return null;
        AuthUtils.clear();
        for(int i=0;i<list.size();i++){
            SysMenu m = list.get(i);
            AuthUtils.addAuth(m.getId(), m.getUrl());
        }
        return list;
    }
    
    /**
     * 清除緩存中的某些數據,如果參數type為querySysParamList則全部清空
     * */
    @CacheEvict(value="sysCache",key="#p0")
    public void removeCatch(String type){
        if(type.equals("querySysParamList")){
            this.sysParamMap = null;
        }
    }
    
    /**
     * 清除緩存中的全部數據
     * */
    @CacheEvict(value="sysCache",allEntries=true)
    public void removeAll(){
        this.sysParamMap = null;
    }
    
    /**
     * 查看緩存中全部數據
     * */
    @Cacheable(value="sysCache",key="methodName")
    public List<SysParam> querySysParamList(){
        return SysParamService.queryList(null);
    }
    
    /**
     * 輸入保存的key值,拿到對應的value。這個方法會經常用到。
     * */
    public String getSysParam(String key){
        if(this.sysParamMap == null){
            this.sysParamMap = new HashMap<String,String>();
            for(SysParam param: querySysParamList()){
                sysParamMap.put(param.getKey(), param.getValue());
            }
        }
        return this.sysParamMap.get(key);
    }

}

  我們的緩存類SysCacheService就算寫好了。可以看到第一次我們調用queryMenuList或者getSysParam方法時,如果map為空會從數據庫中拿,如果map內部有數據存在,會直接從map拿數據。數據是以鍵值對的形式保存的。當我們想調用裏面的數據時,只需要在操作類中註入SysCacheService,然後調用對應的方法。

舉個例子,我的數據結構是這樣的:

技術分享

這是我的項目中的參數配置表,因為以前是oracle數據庫,後來我把數據導入到mysql數據庫裏面時發現字段命名為"key"和"value"的話,查詢sql語句會報錯,所以換成了"keyaa"和"valueaa"。

MyController類想用一下系統配置的sms_url的值:

public String getSmsUrl(){
    String sms_url =sysCacheService.getParam("sms_url");
    return sms_url ;
}

在MyController類中註入SysCacheService對象sysCacheService,並調用它的方法,傳入參數"sms_url"就ok了。

後來,我想了想有沒有更好的辦法,把緩存放到一個類似工具類的靜態類裏面呢,這樣就不用每次用到緩存數據都得註入一個SysCacheService了。方法如下:

1.在配置文件中添加一個servlet上下文的監聽器,當servlet加載時,把SysCacheService放到靜態類裏面

2.在靜態類中聲明方法,代理SysCacheService的方法調用

  xml配置文件增加一個listener:

<!-- 監聽器,用於將緩存SysCacheService類封裝成靜態類 -->
    <listener>
        <listener-class>
            cn.wangze.listener.MyContextListener
        </listener-class>
    </listener>
MyContextListener代碼如下:
package cn.wangze.listener;

import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

import org.springframework.web.context.support.WebApplicationContextUtils;

import cn.wangze.Constants;
import cn.wangze.service.SysCacheService;

public class MyContextListener implements ServletContextListener{

    @Override
    public void contextDestroyed(ServletContextEvent arg0) {
    }

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        
        ServletContext sc =  sce.getServletContext();
        SysCacheService sysCacheService = WebApplicationContextUtils.getWebApplicationContext(sc).getBean(SysCacheService.class);
        Constants.setSysCacheService(sysCacheService);
    }
}

靜態類的代碼如下:

package cn.wangze;

import cn.wangze.service.SysCacheService;


public class Constants {
    private static SysCacheService sysCacheService;
    public static SysCacheService getSysCacheService(){
        return sysCacheService;
    }
    
    public static void setSysCacheService(SysCacheService sysCacheService){
        Constants.sysCacheService = sysCacheService;
    }
    
    public static String getParam(String key){
        return sysCacheService.getSysParam(key);
    }
}

  這樣,我們每次用到緩存數據時候,只需要引入Constants靜態類,並直接用類名+方法名調用數據就行了。

Java緩存類的實際應用場景