<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    當柳上原的風吹向天際的時候...

    真正的快樂來源于創造

      BlogJava :: 首頁 :: 聯系 :: 聚合  :: 管理
      368 Posts :: 1 Stories :: 201 Comments :: 0 Trackbacks
    對一個成規模的系統來說,緩存總是不可或缺的一個環節,甚至會成為系統成功的重要因素。

    從原理來講,緩存并不神秘,它本質上只是一個哈希表,內部包含許多提取關鍵字和緩存內容的鍵值對,當有讀操作(如search)新的查詢到來時,系統先到 這個哈希表中看看是否有同樣的關鍵字存在,是則取出對應的值返回,否則進行查詢,并把新的查詢條件和結果存儲進哈希表,以便下次提取;當有寫操作(如 add,delete,update)來臨時,原則上說現有緩存的內容都存在了不確定性,那么簡單的處理就是清空現有緩存。

    緩存器的位置可以放在具體要執行的CRUD方法之前,當然我個人是不提倡這種耦合子系統的做法,利用Java的動態代理機制,我們可以把數據庫訪問和緩存 兩部分分離開來,而Spring提供的ProxyFactoryBean和Interceptor正好給我們提供了現成的便利,使我們不需要再重復的發明 車輪。這樣做的最大好處是解耦子系統,因為耦合是導致系統癱瘓的重大因素,所以我們必須盡量避免,隨時提防.

    請看具體來說是怎么實現緩存的,下面是需要為之提供緩存服務的TmpServiceImpl類及其接口:
    TmpServiceImpl類:
    public class TmpServiceImpl extends BaseService implements IService{
      
    /**
       * 添加一個Tmp對象到數據庫
       * 
    @param args
       * 
    @return
       * 
    @throws Exception
       
    */
      
    public String add(String[] args) throws Exception{
        String name
    =args[0];
        
    int age=Integer.parseInt(args[1]);
        
    float salary=Float.parseFloat(args[2]);
        
        
    // 同名檢測
        if(hasSameName(name)){
          
    throw new BreakException("已經有和"+name+"同名的對象存在了.");
        }
        
        Tmp tmp
    =new Tmp(name,age,salary);
        dao.create(tmp);
        
        
    return tmp.toXML();
      }
      
      
    /**
       * 將TMP對象的信息組合成一個字符串返回
       * 
       * 說明:要修改此方法請與何楊商議,請勿自行修改!
       * 
    @param args
       * 
    @return
       * 
    @throws Exception
       
    */
      
    public String getInfoById(String[] args) throws Exception{
        String id
    =args[0];
        
        Tmp tmp
    =(Tmp)getObjById(id);
        
        
    if(tmp==null){
          
    throw new BreakException("找不到Id'"+id+"'對應的Tmp對象.");
        }
        
        StringBuilder sb
    =new StringBuilder();
        
        sb.append(
    "姓名:"+tmp.getName()+""r"n");
        sb.append(
    "年齡:"+tmp.getAge()+""r"n");
        sb.append(
    "薪水:"+tmp.getSalary()+""r"n");
        sb.append(
    "添加時間:"+tmp.getAddTime()+""r"n");
        sb.append(
    "更新時間:"+tmp.getRefreshTime()+""r"n");
        
        
    return sb.toString();
      }
      
      
    /**
       * 按ID取得一個Tmp對象
       * 
    @param args
       * 
    @return
       * 
    @throws Exception
       
    */
      
    public String getById(String[] args) throws Exception{
        String id
    =args[0];
        
        Tmp tmp
    =(Tmp)getObjById(id);
        
        
    if(tmp==null){
          
    throw new BreakException("找不到Id'"+id+"'對應的Tmp對象.");
        }
        
        
    return tmp.toXML();
      }
      
      
    /**
       * 按薪水來查詢Tmp對象
       * 
    @param args
       * 
    @return
       * 
    @throws Exception
       
    */
      
    public String searchBySalary(String[] args)throws Exception{
        
    float salary=Float.parseFloat(args[0]);
        
        StringBuilder sb 
    = new StringBuilder();
        sb.append(
    " from " + domainClass + " d where d.valid=true and ");
        sb.append(
    " d.salary >='"+salary+"" );
        sb.append(
    " order by id asc ");
        
        String hql
    =sb.toString();
        
    return convertListToXml(dao.search(hql));
      }
      
      
    /**
       * 按ID來更新一個Tmp對象
       * 
    @param args
       * 
    @return
       * 
    @throws Exception
       
    */
      
    public String update(String[] args)throws Exception{
        String id
    =args[0];
        String name
    =args[1];
        
    int age=Integer.parseInt(args[2]);
        
    float salary=Float.parseFloat(args[3]);
        
        Tmp tmp
    =(Tmp)getObjById(id);    
        
    if(tmp==null){
          
    throw new BreakException("找不到Id'"+id+"'對應的Tmp對象.");
        }
        
        tmp.setName(name);
        tmp.setAge(age);
        tmp.setSalary(salary);
        dao.update(tmp);
        
        
    return tmp.toXML();
      }
      
      
    /**
       * 刪除一個對象
       * 
    @param args
       * 
    @return
       * 
    @throws Exception
       
    */
      
    public String delete(String[] args) throws Exception{
        String id
    =args[0];
        
        Tmp tmp
    =(Tmp)getObjById(id);    
        
    if(tmp==null){
          
    throw new BreakException("找不到Id'"+id+"'對應的Tmp對象.");
        }
        
        dao.delete(tmp);
        
        
    return tmp.toXML();
      }
      
      
    /**
       * 分頁搜索
       * 
    @param args
       * 
    @return
       * 
    @throws Exception
       
    */
      
    public String pagedSearchBy(String[] args) throws Exception{
        
        
    int currentPage=Integer.parseInt(args[0]);  // 當前頁
        int pageSize=Integer.parseInt(args[1]);   // 頁面記錄數
        String name=args[2];            // 姓名
        String salaryFrom=args[3];          // 薪水起點
        String salaryTo=args[4];          // 薪水終點
        String ageFrom=args[5];           // 年齡起點
        String ageTo=args[6];           // 年齡終點
        
        
    // 組合Sql語句
        StringBuilder sb = new StringBuilder();
        sb.append(
    " from " + domainClass + " d where d.valid=true  ");
        
        
    if(StringUtils.isNotBlank(name)){
          sb.append(
    " and d.name like '%"+name+"%' " );
        }
        
        
    if(StringUtils.isNotBlank(salaryFrom)){
          sb.append(
    " and d.salary >='"+salaryFrom+"" );
        }
        
    if(StringUtils.isNotBlank(salaryTo)){
          sb.append(
    " and d.salary <'"+salaryTo+"" );
        }
        
        
    if(StringUtils.isNotBlank(ageFrom)){
          sb.append(
    " and d.age >='"+ageFrom+"" );
        }
        
    if(StringUtils.isNotBlank(ageTo)){
          sb.append(
    " and d.age <'"+ageTo+"" );
        }
        
        sb.append(
    " order by id asc ");   
        String hql
    =sb.toString();
        
        
    // 取得分頁查詢結果
        return getPagedSearchResultInXML(hql,currentPage,pageSize);
      }

      @Override
      
    public String search(String[] args) throws Exception {
        
    return null;
      }
    }

    IService接口:
    public interface IService{
      
    /**
       * 解析參數數組,組合成一個領域對象,然后添加到數據庫(寫方法)
       * 
       * 
    @param args
       * 
    @return
       * 
    @throws Exception
       
    */
      
    public String add(String[] args) throws Exception;
      
      
    /**
       * 解析參數數組,更新領域對象的一個或多個屬性,然后更新數據庫中的對應記錄
       * 
       * 
    @param args
       * 
    @return
       * 
    @throws Exception
       
    */
      
    public String update(String[] args)throws Exception;
      
      
    /**
       * 解析參數數組得到要刪除的領域對象的Id,然后根據它刪除數據庫中的對應記錄
       * 
       * 
    @param args
       * 
    @return
       * 
    @throws Exception
       
    */
      
    public String delete(String[] args) throws Exception;
      
      
    /**
       * 解析參數數組得到要取得的領域對象的Id,然后根據它渠道數據庫中的對應記錄
       * 
       * 
    @param args
       * 
    @return
       * 
    @throws Exception
       
    */
      
    public String getById(String[] args) throws Exception;
      
      
    /**
       * 按條件進行分頁查詢
       * 注意這里的條件最好寫全,最好根據數組內容走不同的分支,不要寫各種各樣的查詢函數,這樣不方便緩存的處理
       * 
       * 
    @param args
       * 
    @return
       * 
    @throws Exception
       
    */
      
    public String pagedSearchBy(String[] args) throws Exception;
      
      
    /**
       * 按條件進行查詢,除了不分頁要求和上面函數(pagedSearchBy)一致
       * 
       * 
    @param args
       * 
    @return
       * 
    @throws Exception
       
    */
      
    public String search(String[] args) throws Exception;
      
      
    /**
       * 按ID取得信息
       * 
       * 
    @param args
       * 
    @return
       * 
    @throws Exception
       
    */
      
    public String getInfoById(String[] args) throws Exception;
    }

    可以看出來,上面的服務類是直接走到數據庫操作記錄的,而我們需要在它的函數執行之前就讓緩存發揮左右,因此,我們需要引入 ProxyFactoryBean和Interepter的幫助,在TmpServiceImpl類的實際方法運行前檢索緩存。這需要進行一定的配置:
      <!-- Tmp對象服務實現類類方法攔截器(一) -->
        
    <bean id="tmpServiceMethodInterceptor" class="com.***.service.interceptor.ServiceMethodInterceptor"/>
        
        
    <!-- Tmp對象服務實現類(二) -->
        
    <bean id="TmpServiceImpl" class="com.***.service.TmpServiceImpl">
            
    <property name="domainClass">
                
    <value>Tmp</value>
            
    </property>
            
    <property name="dao">
                
    <ref bean="dao"/>
            
    </property>
            
    <property name="transactionTemplate">
                
    <ref bean="transactionTemplate"/>
            
    </property>
        
    </bean>
        
        
    <!-- 對外的TmpService,實際上是TmpServiceImpl的代理(三) -->
        
    <bean id="TmpService" class="org.springframework.aop.framework.ProxyFactoryBean">
            
    <property name="proxyInterfaces">
                
    <value>com.***.service.base.IService</value>
            
    </property>
            
    <property name="interceptorNames">
                
    <list>
                    
    <value>tmpServiceMethodInterceptor</value>
                
    </list>
            
    </property>
            
    <property name="target">
                
    <ref bean="TmpServiceImpl"/>
            
    </property>
        
    </bean>

    這樣就可以了,下面是com.***.service.interceptor.ServiceMethodInterceptor類的代碼,應該很好理解:
    public class ServiceMethodInterceptor implements MethodInterceptor{
        
    // 日志記錄器
        private    static Logger logger = Logger.getLogger(ServiceMethodInterceptor.class);
        
        
    // 作為緩存的哈希表
        private Map<String,Object> cacheMap=new Hashtable<String,Object>();

        @Override
        
    public Object invoke(MethodInvocation invocation) throws Throwable {
            String className
    =invocation.getClass().getName();
            String mothodName
    =invocation.getMethod().getName();
            logger.info(
    "類'"+className+"'的方法'"+mothodName+"'將得到調用!");
            
            
    if(mothodName.contains("add"|| mothodName.contains("update"|| mothodName.contains("delete") ){
                
    // 寫方法來了,這意味著數據變更了,緩存可能不可靠,為安全起見需要重新來過
                cacheMap.clear();
                
                Object result
    =invocation.proceed();
                logger.info(
    "類'"+className+"'的方法'"+mothodName+"'調用完畢!");
                
                
    return result;
            }
            
    else{
                
    // 來的是讀方法
                
                
    // 通過組合方法名和參數來得到key
                StringBuffer sb=new StringBuffer();
                sb.append(mothodName
    +";");
                
                Object[] arr
    =invocation.getArguments();
                String[] arr2
    =(String[])arr[0];// 這一步的轉化是很重要的
                for(Object obj:arr2){
                    sb.append(obj
    +",");
                }
                
                String key
    =sb.toString();
                
                
    // 拿Key查看緩存中是否有內容,有則直接返回即可
                if(cacheMap.containsKey(key)){
                    logger.info(
    "直接得到緩存中的結果!");
                    
    return cacheMap.get(key);
                }
                
    else{
                    Object result
    =invocation.proceed();
                    
                    cacheMap.put(key, result);
                    logger.info(
    "類'"+className+"'的方法'"+mothodName+"'調用完畢!");
                    
                    
    return result;
                }
            }
        }
    }

    之所以使用MethodInterceptor是因為在其中可以修改返回的結果,在上面出現的
    Object result=invocation.proceed();           
    return result;
    實際就是對TempServiceImpl函數執行的調用,result就是返回結果,它是可以改變的。因此,如果緩存中有對應內容,取出直接返回,沒有的話調用這兩句進行老實的數據庫操作即可。

    到這里,緩存已經可以使用了,當然,它還很不完善,在鍵的設計和簡化,如果數據過多時的硬盤暫存,數據過期,寫操作對緩存影響的精細化上都可以下一番工夫,這些我們日后再探討吧。
    posted on 2010-05-24 15:10 何楊 閱讀(636) 評論(0)  編輯  收藏

    只有注冊用戶登錄后才能發表評論。


    網站導航:
     
    主站蜘蛛池模板: 亚洲?V无码成人精品区日韩| 成人免费在线视频| 人人揉揉香蕉大免费不卡| 1000部拍拍拍18免费网站| 国产无遮挡又黄又爽免费视频 | jizz免费观看| 6080午夜一级毛片免费看6080夜福利 | 久久亚洲AV成人无码软件| 国产啪精品视频网站免费尤物| 亚洲综合免费视频| 亚洲国产一成久久精品国产成人综合 | 亚洲精品国产摄像头| 免费黄色毛片视频| 免费大片av手机看片高清| 亚洲午夜爱爱香蕉片| 亚洲色大成WWW亚洲女子| 国产色婷婷精品免费视频| 78成人精品电影在线播放日韩精品电影一区亚洲 | XXX2高清在线观看免费视频| 亚洲av日韩av永久在线观看| 在线观看免费国产视频| 边摸边吃奶边做爽免费视频网站 | 国产美女精品视频免费观看| 国产亚洲精品成人久久网站| 国产亚洲精久久久久久无码AV| 在线综合亚洲中文精品| 四虎影视精品永久免费| 2022免费国产精品福利在线| 国产精品国产午夜免费福利看| 亚洲成电影在线观看青青 | 色偷偷亚洲男人天堂| 国产精品亚洲精品日韩已方| 亚洲AⅤ男人的天堂在线观看| 国产免费久久精品99re丫y| 亚洲精品视频在线| 免费国产午夜高清在线视频 | 免费国产一级特黄久久| 国产成人免费ā片在线观看老同学 | 免费在线观看污网站| 免费黄色电影在线观看| 国产精品亚洲AV三区|