亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > JSP > 正文

詳細解析JSP編程中進度條的設計實例

2024-09-05 00:20:23
字體:
來源:轉載
供稿:網友
  許多web應用、企業應用涉及到長時間的操作,例如復雜的數據庫查詢或繁重的xml處理等,雖然這些任務主要由數據庫系統或中間件完成,但任務執行的結果仍舊要借助jsp才能發送給用戶。本文介紹了一種通過改進前端表現層來改善用戶感覺、減輕服務器負載的辦法。

  當jsp調用一個必須長時間運行的操作,且該操作的結果不能(在服務器端)緩沖,用戶每次請求該頁面時都必須長時間等待。很多時候,用戶會失去耐心,接著嘗試點擊瀏覽器的刷新按鈕,最終失望地離開。

  本文介紹的技術是把繁重的計算任務分離開來,由一個獨立的線程運行,從而解決上述問題。當用戶調用jsp頁面時,jsp頁面會立即返回,并提示用戶任務已經啟動且正在執行;jsp頁面自動刷新自己,報告在獨立線程中運行的繁重計算任務的當前進度,直至任務完成。

  一、模擬任務

  首先我們設計一個taskbean類,它實現java.lang.runnable接口,其run()方法在一個由jsp頁面(start.jsp)啟動的獨立線程中運行。終止run()方法執行由另一個jsp頁面stop.jsp負責。taskbean類還實現了java.io.serializable接口,這樣jsp頁面就可以將它作為javabean調用:

  
package test.barbean; import java.io.serializable; public class taskbean implements runnable, serializable{ private int counter; private int sum; private boolean started; private boolean running; private int sleep; public taskbean(){ counter = 0; sum = 0; started = false; running = false; sleep = 100; } }


  taskbean包含的“繁重任務”是計算1+2+3…+100的值,不過它不通過100*(100+1)/2=5050公式計算,而是由run()方法調用work()方法100次完成計算。work()方法的代碼如下所示,其中調用thread.sleep()是為了確保任務總耗時約10秒。

  
protected void work(){ try{ thread.sleep(sleep); counter++; sum += counter; } catch (interruptedexception e){ setrunning(false); } }


  status.jsp頁面通過調用下面的getpercent()方法獲得任務的完成狀況:

  
public synchronized int getpercent(){ return counter; }


  如果任務已經啟動,isstarted()方法將返回true:

  
public synchronized boolean isstarted(){ return started; }


  如果任務已經完成,iscompleted()方法將返回true:

  
public synchronized boolean iscompleted(){ return counter == 100; }


  如果任務正在運行,isrunning()方法將返回true:

  
public synchronized boolean isrunning(){ return running; }


  setrunning()方法由start.jsp或stop.jsp調用,當running參數是true時。setrunning()方法還要將任務標記為“已經啟動”。調用setrunning(false)表示要求run()方法停止執行。

  
public synchronized void setrunning(boolean running){ this.running = running; if (running) started = true; }


  任務執行完畢后,調用getresult()方法返回計算結果;如果任務尚未執行完畢,它返回null:

  
public synchronized object getresult(){ if (iscompleted()) return new integer(sum); else return null; }


  當running標記為true、completed標記為false時,run()方法調用work()。在實際應用中,run()方法也許要執行復雜的sql查詢、解析大型xml文檔,或者調用消耗大量cpu時間的ejb方法。注意“繁重的任務”可能要在遠程服務器上執行。報告結果的jsp頁面有兩種選擇:或者等待任務結束,或者使用一個進度條。

  
public void run() { try { setrunning(true); while (isrunning() && !iscompleted()) work(); } finally { setrunning(false); } }


  二、啟動任務

  start.jsp是web.xml部署描述符中聲明的歡迎頁面,web.xml的內容是:

  
<?xml version="1.0" encoding="gb2312"?> <!doctype web-app public "-//sun microsystems, inc.//dtd web application 2.3//en" "http://java.sun.com/dtd/web-app_2_3.dtd"> <web-app> <welcome-file-list> <welcome-file>start.jsp</welcome-file> </welcome-file-list> </web-app>


  start.jsp啟動一個專用的線程來運行“繁重的任務”,然后把http請求傳遞給status.jsp。

  start.jsp頁面利用標記創建一個taskbean的實例,將scope屬性定義為session使得對于來自同一瀏覽器的http請求,其他頁面也能提取到同一個bean對象。start.jsp通過調用session.removeattribute("task")確保創建了一個新的bean對象,而不是提取一個舊對象(例如,同一個用戶會話中更早的jsp頁面所創建的bean對象)。

  下面是start.jsp頁面的代碼清單:

  
<% session.removeattribute("task"); %> <jsp:usebean id="task" scope="session" class="test.barbean.taskbean"/> <% task.setrunning(true); %> <% new thread(task).start(); %> <jsp:forward page="status.jsp"/>

  start.jsp創建并設置好taskbean對象之后,接著創建一個thread,并將bean對象作為一個runnable實例傳入。調用start()方法時新創建的線程將執行taskbean對象的run()方法。

  現在有兩個線程在并發執行:執行jsp頁面的線程(稱之為“jsp線程”),由jsp頁面創建的線程(稱之為“任務線程”)。接下來,start.jsp利用調用status.jsp,status.jsp顯示出進度條以及任務的執行情況。注意status.jsp和start.jsp在同一個jsp線程中運行。

  start.jsp在創建線程之前就把taskbean的running標記設置成了true,這樣,即使當jsp線程已開始執行status.jsp而任務線程的run()方法尚未啟動,也能夠確保用戶會得到“任務已開始運行”的狀態報告。

  將running標記設置成true、啟動任務線程這兩行代碼可以移入taskbean構成一個新的方法,然后由jsp頁面調用這個新方法。一般而言,jsp頁面應當盡量少用java代碼,即我們應當盡可能地把java代碼放入java類。不過本例中我們不遵從這一規則,把new thread(task).start()直接放入start.jsp突出表明jsp線程創建并啟動了任務線程。

  在jsp頁面中操作多線程必須謹慎,注意jsp線程和其它線程實際上是并發執行的,就象在桌面應用程序中,我們用一個線程來處理gui事件,另外再用一個或多個線程來處理后臺任務。

  不過在jsp環境中,考慮到多個用戶同時請求某一個頁面的情況,同一個jsp頁面可能會在多個線程中同時運行;另外,有時同一個用戶可能會向同一個頁面發出多個請求,雖然這些請求來自同一個用戶,它們也會導致服務器同時運行一個jsp頁面的多個線程。

  三、任務進度

  status.jsp頁面利用一個html進度條向用戶顯示任務的執行情況。首先,status.jsp利用標記獲得start.jsp頁面創建的bean對象:

<jsp:usebean id="task" scope="session" class="test.barbean.taskbean"/>

  為了及時反映任務執行進度,status.jsp會自動刷新。javascript代碼settimeout("location=′status.jsp′", 1000)將每隔1000毫秒刷新頁面,重新請求status.jsp,不需要用戶干預。   

<html> <head> <title>jsp進度條</title> <% if (task.isrunning()) { %> <script language="javascript"> settimeout("location=′status.jsp′", 1000); </script> <% } %> </head> <body>

  進度條實際上是一個html表格,包含10個單元,即每個單元代表任務總體的10%進度。   

<h1 align="center">jsp進度條</h1> <h2 align="center">

  結果:   

<%= task.getresult() %><br> <% int percent = task.getpercent();%> <%= percent %>% </h2> <table width="60%" align="center" border=1 cellpadding=0 cellspacing=2> <tr> <% for (int i = 10; i <= percent; i += 10){ %> <td width="10%" bgcolor="#000080"> </td> <% } %> <% for (int i = 100; i > percent; i -= 10){ %> <td width="10%"> </td> <%} %> </tr> </table>

  任務執行情況分下面幾種狀態:正在執行,已完成,尚未開始,已停止:  

<table width="100%" border=0 cellpadding=0 cellspacing=0> <tr> <td align="center"> <% if (task.isrunning()) { %>

  正在執行   

<% } else { %> <% if (task.iscompleted()) { %>

  完成   

<% } else if (!task.isstarted()){ %>

  尚未開始   

<% } else { %>

  已停止   

<% } %> <% } %> </td> </tr>

  頁面底部提供了一個按鈕,用戶可以用它來停止或重新啟動任務:  

<tr> <td align="center"> <br> <% if (task.isrunning()) { %> <form method="get" action="stop.jsp"> <input type="submit" value="停止"> </form> <% } else { %> <form method="get" action="start.jsp"> <input type="submit" value="開始"> </form> <% } %> </td> </tr> </table> </body></html>

  只要不停止任務,約10秒后瀏覽器將顯示出計算結果5050:

  四、停止任務

  stop.jsp頁面把running標記設置成false,從而停止當前的計算任務:  

<jsp:usebean id="task" scope="session" class="test.barbean.taskbean"/> <% task.setrunning(false); %> <jsp:forward page="status.jsp"/>

  注意最早的java版本提供了thread.stop方法,但jdk從1.2版開始已經不贊成使用thread.stop方法,所以我們不能直接調用thread.stop()。

  第一次運行本文程序的時候,你會看到任務的啟動有點延遲;同樣地,第一次點擊“停止”按鈕時也可以看到任務并沒有立即停止運行(特別是如果機器配置較低的話,延遲的感覺更加明顯),這些延遲都是由于編譯jsp頁面導致的。編譯好jsp頁面之后,應答速度就要快多了。

  五、實際應用

  進度條不僅使得用戶界面更加友好,而且對服務器的性能也有好處,因為進度條會不斷地告訴用戶當前的執行進度,用戶不會再頻繁地停止并重新啟動(刷新)當前的任務。另一方面,創建單獨的線程來執行后臺任務也會消耗不少資源,必要時可考慮通過一個線程池來實現thread對象的重用。另外,頻繁地刷新進度頁面也增加了網絡通信開銷,所以務必保持進度頁面簡潔短小。

  在實際應用中,后臺執行的繁重任務可能不允許停止,或者它不能提供詳細的執行進度數據。例如,查找或更新關系數據庫時,sql命令執行期間不允許中途停止??不過如果用戶表示他想要停止或中止任務,程序可以在sql命令執行完畢后回退事務。

  解析xml文檔的時候,我們沒有辦法獲知已解析內容精確的百分比。如果用dom解析xml文檔,直到解析完成后才得到整個文檔樹;如果用sax,雖然可以知道當前解析的內容,但通常不能確定還有多少內容需要解析。在這些場合,任務的執行進度只能靠估計得到。

  估計一個任務需要多少執行時間通常是很困難的,因為它涉及到許多因素,即使用實際測試的辦法也無法得到可靠的結論,因為服務器的負載隨時都在變化之中。一種簡單的辦法是測量任務每次執行所需時間,然后根據最后幾次執行的平均時間估算。

  如果要提高估計時間的精確度,應當考慮實現一種針對應用特點的算法,綜合考慮多種因素,例如要執行的sql語句類型、要解析的xml模式的復雜程度,等等。

  結束語:本文例子顯示出用jsp、java、html和javascript構造進度條是相當容易的,真正困難的是如何將它用到實際應用之中,特別是獲得后臺任務的進度信息,但這個問題沒有通用的答案,每一種后臺執行的任務都有它自己的特點,必須按照具體情況具體分析。



發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
日韩激情视频在线| 精品亚洲男同gayvideo网站| 欧美成人精品三级在线观看| 在线视频欧美日韩精品| 精品视频偷偷看在线观看| 欧美专区中文字幕| 在线精品视频视频中文字幕| 法国裸体一区二区| 国产精品一区久久久| 2018日韩中文字幕| 欧美在线免费看| 精品国产一区二区三区久久久| 91精品国产自产在线观看永久| 国产不卡在线观看| 欧美多人爱爱视频网站| 欧美多人乱p欧美4p久久| 久久国产精品久久久| 亚洲深夜福利在线| 亚洲一级免费视频| 亚洲欧美精品伊人久久| 欧美超级乱淫片喷水| 欧美日韩视频免费播放| 欧美激情一级精品国产| 亚洲一区二区三区四区在线播放| 国产精品久久久久久久app| 欧美孕妇毛茸茸xxxx| 亚洲2020天天堂在线观看| 日韩高清不卡av| 日av在线播放中文不卡| 欧美午夜片欧美片在线观看| 国产精品黄视频| 成人欧美一区二区三区黑人| 国产精品久久久久久久久久久久久| 久久久精品免费视频| 国语自产偷拍精品视频偷| 欧美激情视频免费观看| 精品日韩中文字幕| 在线播放精品一区二区三区| 欧美亚洲国产精品| 日韩毛片在线观看| 欧洲午夜精品久久久| 日韩电影中文字幕在线观看| 久久亚洲精品一区| 亚洲bt天天射| 日本高清视频精品| 日韩视频免费大全中文字幕| 国产成人av网址| 亚洲网在线观看| 久久精品国产99国产精品澳门| 国产视频自拍一区| 91免费国产网站| 国产精品欧美在线| 欧美大片在线看| 亚洲美女喷白浆| 久久香蕉国产线看观看网| 欧美自拍视频在线观看| 国产亚洲精品久久久| 午夜精品一区二区三区在线视频| 欧美激情亚洲另类| 精品亚洲一区二区三区在线播放| 国产综合视频在线观看| 久久久久久国产精品久久| 色婷婷**av毛片一区| 国产97在线|亚洲| 国产乱人伦真实精品视频| 韩国视频理论视频久久| 欧美激情亚洲激情| 亚洲视频在线看| 成人免费直播live| 超薄丝袜一区二区| 欧美精品videos| 久久久久久美女| 亚洲最大成人免费视频| 亚洲精品日韩欧美| 欧美一级电影在线| 亚洲欧美成人在线| 国产成人精品免高潮费视频| 亚洲色图校园春色| 欧美日韩成人免费| 亚洲日韩中文字幕在线播放| 中文字幕自拍vr一区二区三区| 97精品欧美一区二区三区| 日韩高清免费观看| 国产精品久久久久久av下载红粉| 美日韩精品视频免费看| 国外成人在线播放| 日韩欧美大尺度| 亚洲欧美中文字幕| 中文字幕日韩欧美精品在线观看| 亚洲影院高清在线| 日韩精品免费在线| 日本亚洲精品在线观看| 亚洲综合中文字幕68页| 久久影视三级福利片| 久久精品国产96久久久香蕉| 亚洲色图欧美制服丝袜另类第一页| 日韩av在线免播放器| 日韩电影第一页| 蜜臀久久99精品久久久无需会员| 欧美国产精品日韩| 亚洲成年人影院在线| 午夜剧场成人观在线视频免费观看| 主播福利视频一区| 国产综合久久久久久| 欧美一级高清免费| 国产精品久久久久免费a∨| 国产精品白丝av嫩草影院| 久久色免费在线视频| 国产精品成人免费电影| 国产精品中文在线| 国产欧美亚洲视频| 亚洲第一级黄色片| 亚洲欧美另类中文字幕| 久久久在线视频| 国产午夜精品视频| 欧美日韩免费区域视频在线观看| 国产成人久久久精品一区| 中文字幕久久久| 中文字幕日韩精品在线| 欧美成人在线免费视频| 在线播放国产精品| 久久精品国产精品亚洲| 欧美在线亚洲一区| 日韩精品在线私人| 91在线免费观看网站| 国产激情综合五月久久| 国产精品免费久久久久久| xx视频.9999.com| 国产精品电影在线观看| 欧美成人免费小视频| 成人美女av在线直播| 亚洲精品v天堂中文字幕| 欧美激情一区二区三级高清视频| 日韩免费观看高清| 日韩av影片在线观看| 精品视频久久久久久久| 日韩电影中文字幕在线观看| 亚洲奶大毛多的老太婆| 亚洲国产精品久久久久久| 国产一区二区av| 久久夜色精品亚洲噜噜国产mv| 在线电影av不卡网址| 国产丝袜一区二区三区免费视频| 色综合五月天导航| 在线播放日韩欧美| 久久成人18免费网站| 国产69精品久久久久9| 欧美怡春院一区二区三区| 精品偷拍各种wc美女嘘嘘| 亚洲电影免费观看高清完整版在线观看| 亚洲xxxx视频| 91色中文字幕| 不卡av电影在线观看| 亚洲网站视频福利| 韩日欧美一区二区| 国产一区二区在线播放| 亚洲精品乱码久久久久久按摩观| 亚洲bt欧美bt日本bt| 一本色道久久88综合日韩精品| 亚洲人成电影网站色www| 日韩精品免费在线视频观看| 国产精品视频久| 最近2019中文字幕大全第二页| 国产91在线播放精品91|