大多數做過基於Web的Java編程的人都做過
翻頁
提交
這種比較基本的工作
這些網絡編程中不可缺少的步驟
通常都很容易實現
但不知你有沒有過這樣的經歷
在一些特殊情況下
翻頁出現了混亂
明明下一頁應該是第
頁
卻翻到第
頁
明明只提交了一次
卻發現在購物車裡提交了兩次結果
千萬別以為是自己眼花了
或者是遭病毒襲擊了
這些就是我們編程中容易碰到的
陷阱
下面我們就這兩個問題分別進行討論
翻頁中的
陷阱
翻頁有兩種常用的實現方式
基於session的翻頁和基於hidden的翻頁
將頁號信息保存在session中
這是最常使用的方法
這種方法的初衷是利用session在頁面之間傳遞信息
即將頁號信息保存在session變量中
這樣
上下翻頁時
只需從session中取出當前頁號
並進行相應的處理
當有不同的查詢頁面指向同一個結果頁面時
可在不同的查詢頁面內將session內的頁號值重置
可較好地實現復用
很多人習慣采用如下實現方法
假設有兩個查詢頁面time
jsp和place
jsp
分別以時間和地點為查詢條件
結果指向同一個顯示頁面result
jsp
在time
jsp和place
jsp中均有這樣的語句
<%page.setPageNum(1);%>
在result
jsp中有這樣的語句
下一頁
<%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再次傳遞頁號信息
先來看一下具體的實現方法
例子仍基於上述情況
首先
在time
jsp和place
jsp中
刪除對JavaBean的調用
分別在兩個文件的提交url後追加頁號信息
例如
在time
jsp中
加入代碼result
jsp?date=
&&pageNum=
在place
jsp中
加入代碼result
jsp?place=
bj
&&pageNum=
其次
在result
jsp中做如下設置
將url中所有變量以hidden的形式重新寫入form中
下面為其代碼實例
這種方法看似愚笨
讓人有多此一舉的感覺
但事實上它卻是出現漏洞最少的一種方法
這樣以來
每個結果頁面都有自己獨立的頁號信息
不存在干擾情況
從而避開了
陷阱
重復提交中的
陷阱
當我們進行網上購物時
在選擇了滿意的商品後
就要進行提交操作
如果網速較慢或有其它因素影響
就會遲遲不出結果
於是我們常常回退或停止
然後再次提交
這次很快有了響應
但奇怪的是
明明只提交一次
購物車中的商品卻是雙份的
產生原因是這樣的
當因為遲遲不響應而回退時
在服務器端有兩種可能
一種是提交已經得到了處理
數據庫中已有了相應記錄
但結果頁面沒有顯示出來
另一種是提交還未得到處理
這種沒有任何問題
針對這個現象
解決辦法是引入同步機制(SynId)
指導思想就是
為每一個頁面編號
並在客戶端和服務器端各產生一個副本
每次通過比較兩端的編號是否一致
達到同步的目的
首先
由服務器產生這個編號
發送到客戶端
這樣這個編號在服務器和客戶端各有一個副本
當客戶提交頁面時
服務器首先比較兩個編號是否一致
如果一致
則處理提交
並產生一個新的編號
返回給客戶端
此時如果客戶回退並再次提交
客戶端是舊編號
服務器端是新編號
顯然不一致
因此服務器將判定這是一次重復提交
不予受理
實現過程如下(如圖所示)
圖 同步機制實現過程
當用戶首次購物時
發出購物請求
完成步驟
——在服務器端產生一個同步環
保存在session中
客戶在購物頁面完成步驟
——將同步環保存在客戶端的hidden中
客戶選購完畢
提交請求
步驟
啟動——服務器比較session中的同步環和客戶提交的是否一致
如果一致
服務器處理請求
完成步驟
然後進行步驟
——產生一個新的同步環
並將結果頁面返回給客戶
如果此時客戶尚未看到結果頁面
進行了回退或停止重新提交操作
用戶提交頁面的同步環顯然不同於服務器session中的同步環
於是服務器會判定
這是一個重復提交的頁面
不予受理
對於同步環的產生
保存
比較
最好生成一個新
同步助手
類SynHelper
完成相應的操作
調用它的Jsp文件只需以JavaBean的形式引用即可
下面描述作為類SynHelper所需的基本方法
private String generateSynId(){
return Long
toString(System
currentTimeMillis());
}
protected void saveSynId(HttpServletRequest request){
HttpSession session = request
getSession();
session
setAttribute(SYN_ID
generateSynId());
}
protected boolean compareSynId(HttpServletRequest request){
try{
HttpSession session = request
getSession();
String serverSynId = session
getAttribute(SYN_ID);
String clientSynId = request
getParameter(
CLIENT_SYN_ID
);
Return (serverSynId
equals(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