Application 2.3//EN"
"java.sun/dtd/web-app_2_3.dtd">
start.jsp
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"); %>
class="test.barBean.TaskBean"/>
<% task.setRunning(true); %>
<% new Thread(task).start(); %>
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对象:
class="test.barBean.TaskBean"/>
为了及时反映任务执行进度,status.jsp会自动刷新。javascript代码setTimeout("location='status.jsp'", 1000)将每隔1000毫秒刷新页面,重新请求status.jsp,不需要用户干预。
<% if (task.isRunning()) { %>
<% } %>
进度条实际上是一个HTML表格,包含10个单元——即每个单元代表任务总体的10%进度。
JSP进度条
结果: <%= task.getResult() %>
<% int percent = task.getPercent(); %>
<%= percent %>%
BORDER=1 CELLPADDING=0 CELLSPACING=2>
<% for (int i = 10; i <= percent; i += 10) { %>
&;nbsp; |
<% } %>
<% for (int i = 100; i > percent; i -= 10) { %>
&;nbsp; |
<% } %>
任务执行情况分下面几种状态:正在执行,已完成,尚未开始,已停止:
<% if (task.isRunning()) { %> 正在执行 <% } else { %> <% if (task.isCompleted()) { %> 完成 <% } else if (!task.isStarted()) { %> 尚未开始 <% } else { %> 已停止 <% } %> <% } %> |
页面底部提供了一个按钮,用户可以用它来停止或重新启动任务:
<% if (task.isRunning()) { %> <% } else { %> <% } %> |
只