二、启动任务</p>start.jsp是web.xml部署描述符中声明的欢迎页面,web.xml的内容是:% b2 ?/ v4 F, ?* ]; x; Q
《?xml version=“1.0” encoding=“GB2312”?》
, p& d, f4 ~# ^《!DOCTYPE web-app+ m6 c% P/ H( l4 b, ]
PUBLIC “-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN”
* h6 ]; I$ t9 h$ g4 \5 f“http://java.sun.com/dtd/web-app_2_3.dtd”》
4 k! k$ K' q# Y2 l1 i! [& \' _& [《web-app》4 w! _. L/ E2 Q: I: c
《welcome-file-list》
F& j9 _. | X; L$ W6 T4 K; Q: W/ I《welcome-file》start.jsp《/welcome-file》" t8 h) X, p1 ~; Q. N
《/welcome-file-list》
. S" k5 `" v9 S8 ]《/web-app》
' v L* C+ F4 _3 ^9 Y7 Xstart.jsp启动一个专用的线程来运行“繁重的任务”,然后把HTTP请求传递给status.jsp。. k# k# a; P5 B, ~7 `, J
start.jsp页面利用《jsp:useBean》标记创建一个TaskBean的实例,将scope属性定义为session使得对于来自同一浏览器的HTTP请求,其他页面也能提取到同一个Bean对象。start.jsp通过调用session.removeAttribute(“task”)确保《jsp:useBean》创建了一个新的Bean对象,而不是提取一个旧对象(例如,同一个用户会话中更早的JSP页面所创建的Bean对象)。& R1 b, `5 g$ D# ]$ C
下面是start.jsp页面的代码清单:
* I7 \: n! E# e5 P+ c+ j U《% session.removeAttribute(“task”); %》3 b9 }$ Z7 B* W4 a6 l/ X. h8 a+ {
《jsp:useBean id=“task” scope=“session”7 v7 I. a% J8 g5 Q
class=“test.barBean.TaskBean”/》
" K1 {% o& l' {- Z《% task.setRunning(true); %》$ D7 b% n- Z& Q) S% i
《% new Thread(task).start(); %》
5 |; U3 _% ^' P4 @, k8 B2 P《jsp:forward page=“status.jsp”/》4 F( k# u9 e2 i9 c5 o9 ?
start.jsp创建并设置好TaskBean对象之后,接着创建一个Thread,并将Bean对象作为一个Runnable实例传入。调用start()方法时新创建的线程将执行TaskBean对象的run()方法。
# K+ y& Q" r- P. N/ z' Q. ~5 w7 f现在有两个线程在并发执行:执行JSP页面的线程(称之为“JSP线程”),由JSP页面创建的线程(称之为“任务线程”)。接下来,start.jsp利用调用status.jsp,status.jsp显示出进度条以及任务的执行情况。注意status.jsp和start.jsp在同一个JSP线程中运行。
* U( _+ u! V: j2 Ystart.jsp在创建线程之前就把TaskBean的running标记设置成了true,这样,即使当JSP线程已开始执行status.jsp而任务线程的run()方法尚未启动,也能够确保用户会得到“任务已开始运行”的状态报告。8 v0 \$ t% `- ^7 }/ I! Y' X
将running标记设置成true、启动任务线程这两行代码可以移入TaskBean构成一个新的方法,然后由JSP页面调用这个新方法。一般而言,JSP页面应当尽量少用Java代码,即我们应当尽可能地把Java代码放入Java类。不过本例中我们不遵从这一规则,把new Thread(task).start()直接放入start.jsp突出表明JSP线程创建并启动了任务线程。
3 y$ R& T1 g- |# U! n在JSP页面中操作多线程必须谨慎,注意JSP线程和其它线程实际上是并发执行的,就象在桌面应用程序中,我们用一个线程来处理GUI事件,另外再用一个或多个线程来处理后台任务。不过在JSP环境中,考虑到多个用户同时请求某一个页面的情况,同一个JSP页面可能会在多个线程中同时运行;另外,有时同一个用户可能会向同一个页面发出多个请求,虽然这些请求来自同一个用户,它们也会导致服务器同时运行一个JSP页面的多个线程。 |