熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java核心技術 >> 正文

謹防Java網絡編程“陷阱”

2013-11-23 18:56:04  來源: Java核心技術 

  大多數做過基於Web的Java編程的人都做過翻頁提交這種比較基本的工作這些網絡編程中不可缺少的步驟通常都很容易實現但不知你有沒有過這樣的經歷在一些特殊情況下翻頁出現了混亂明明下一頁應該是第卻翻到第明明只提交了一次卻發現在購物車裡提交了兩次結果千萬別以為是自己眼花了或者是遭病毒襲擊了這些就是我們編程中容易碰到的陷阱下面我們就這兩個問題分別進行討論
  
  翻頁中的陷阱
  
  翻頁有兩種常用的實現方式基於session的翻頁和基於hidden的翻頁
  
  將頁號信息保存在session中
  
  這是最常使用的方法這種方法的初衷是利用session在頁面之間傳遞信息即將頁號信息保存在session變量中這樣上下翻頁時只需從session中取出當前頁號並進行相應的處理當有不同的查詢頁面指向同一個結果頁面時可在不同的查詢頁面內將session內的頁號值重置可較好地實現復用
  
  很多人習慣采用如下實現方法
  
  假設有兩個查詢頁面timejsp和placejsp分別以時間和地點為查詢條件結果指向同一個顯示頁面resultjsp在timejsp和placejsp中均有這樣的語句
  
  
  

  <%page.setPageNum(1);%>
  
  
  
  在resultjsp中有這樣的語句
  
  下一頁<%page.nextPage();%>
  上一頁<%page.previousPage();%>
  
  
  
  在類page中有這樣的代碼
  
  private int pageNum;
  public void setPageNum(int i){
   pageNum = i;
  }
  public void previousPage(){
   pageNum ;
  }
  public void nextPage(){
   pageNum ++;
  }
  
  現在來看一看陷阱是怎麼產生的
  
  當以時間為查詢條件時下翻到第將此窗口命名為窗口此時重新打開一個窗口(Ctrl+N方式)以地點為查詢條件下翻到第將此窗口命名為窗口到目前為止一切正常但請注意當再回到窗口並向下翻時問題便出現了——原本應該是第現在顯示的卻是第
  
  為什麼呢?原因很簡單兩個窗口共享一個session值當窗口切換回窗口窗口引用的pageNum值已被窗口改變了
  
  由此可以發現session在不同頁面之間共享信息固然很有用但必須小心使用否則會制造出一些隱藏很深的錯誤
  
  通過URL再次傳遞頁號信息
  
  先來看一下具體的實現方法例子仍基於上述情況首先在timejsp和placejsp中刪除對JavaBean的調用分別在兩個文件的提交url後追加頁號信息例如在timejsp中加入代碼resultjsp?date=&&pageNum=在placejsp中加入代碼resultjsp?place=bj&&pageNum=
  
  其次在resultjsp中做如下設置將url中所有變量以hidden的形式重新寫入form中下面為其代碼實例
  
   
  
  這種方法看似愚笨讓人有多此一舉的感覺但事實上它卻是出現漏洞最少的一種方法這樣以來每個結果頁面都有自己獨立的頁號信息不存在干擾情況從而避開了陷阱
  
  
  重復提交中的陷阱
  
  
  當我們進行網上購物時在選擇了滿意的商品後就要進行提交操作如果網速較慢或有其它因素影響就會遲遲不出結果於是我們常常回退或停止然後再次提交這次很快有了響應但奇怪的是明明只提交一次購物車中的商品卻是雙份的產生原因是這樣的當因為遲遲不響應而回退時在服務器端有兩種可能一種是提交已經得到了處理數據庫中已有了相應記錄但結果頁面沒有顯示出來另一種是提交還未得到處理這種沒有任何問題
  
  針對這個現象解決辦法是引入同步機制(SynId)指導思想就是為每一個頁面編號並在客戶端和服務器端各產生一個副本每次通過比較兩端的編號是否一致達到同步的目的首先由服務器產生這個編號發送到客戶端這樣這個編號在服務器和客戶端各有一個副本當客戶提交頁面時服務器首先比較兩個編號是否一致如果一致則處理提交並產生一個新的編號返回給客戶端此時如果客戶回退並再次提交客戶端是舊編號服務器端是新編號顯然不一致因此服務器將判定這是一次重復提交不予受理
  
  實現過程如下(如圖所示)
  
  圖 同步機制實現過程
  
  
  當用戶首次購物時發出購物請求完成步驟——在服務器端產生一個同步環保存在session中客戶在購物頁面完成步驟——將同步環保存在客戶端的hidden中客戶選購完畢提交請求步驟啟動——服務器比較session中的同步環和客戶提交的是否一致如果一致服務器處理請求完成步驟然後進行步驟——產生一個新的同步環並將結果頁面返回給客戶如果此時客戶尚未看到結果頁面進行了回退或停止重新提交操作用戶提交頁面的同步環顯然不同於服務器session中的同步環於是服務器會判定這是一個重復提交的頁面不予受理
  
  對於同步環的產生保存比較最好生成一個新同步助手類SynHelper完成相應的操作調用它的Jsp文件只需以JavaBean的形式引用即可下面描述作為類SynHelper所需的基本方法
  
  private String generateSynId(){
   return LongtoString(SystemcurrentTimeMillis());
  }
  protected void saveSynId(HttpServletRequest request){
   HttpSession session = requestgetSession();
   sessionsetAttribute(SYN_IDgenerateSynId());
  }
  protected boolean compareSynId(HttpServletRequest request){
   try{
   HttpSession session = requestgetSession();
   String serverSynId = sessiongetAttribute(SYN_ID);
   String clientSynId = requestgetParameter(CLIENT_SYN_ID);
   Return (serverSynIdequals(clientSynId));
  }catch(Exception e){
   return false;
  }
  }
  
  對於客戶端jsp在收到服務器的同步環後必須將其保存在hidden中具體實現如下
  
    value=<%=session.getAttribute(“SYN_ID”)%>>
  
  
  

From:http://tw.wingwit.com/Article/program/Java/hx/201311/25998.html
  • 上一篇文章:

  • 下一篇文章:
  • 推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.