每个请求来到Web容器,Web容器会为其分配一个线程来专门负责该请求,直到完成处理前,该执行线程都不会被释放回容器。 执行线程会耗用系统资源,若有些请求需要长时间处理(例如长时间运算、等待某个资源),就会长时间占用执行线程。
若这类的请求很多,许多执行线程都被长时间占用,而在web容器内,可以使用的线程都是有限的,这对于系统就会是个负担,甚至造成应用程式的性能瓶颈。
基本上一些需长时间处理的请求,通常客户端也较不在乎请求后要有立即的回应。若可以,让这类请求先释放容器分配给该请求的执行线程,让容器可以有机会将执行线程资源分配给其它的请求,可以减轻系统负担。
很多项目在遇到需长时间处理的任务时,经常启一个新线程或者扔到线程池中,这样不耽误任务主线的流程,这个servlet的asynch特性其实发挥同样的作用
释放了容器所分配执行线程的请求,其回应将被延后,直到处理完成(例如长时间运算完成、所需资源已获得)再行对客户端的回应,如果超过浏览器的链接时长,会将servlet中的内容返回,而asyncContext中的内容则不能返回,服务器抛出java.lang.IllegalStateException错误
在Servlet 3.0中,提供了AsyncContext,对异步执行的上下文提供支持。在ServletRequest上提供了 startAsync( )方法,用于启动异步工作线程。而且AsynchContext还提供了Timeout等设置。
你可以透过AsyncContext的getRequest() 、 getResponse()方法取得Request、Response对象,此次对客户端的响应将暂缓至调用AsyncContext的complete()方法或dispatch()为止,前者表示回应完成,后者表示将响应调派给指定的URL 。
若要能调用ServletRequest的startAsync()使用AsyncContext,则此Servlet 必须能支援非同步处理,如果使用@WebServlet来标注,则可以设定其asyncSupported为true 。 例如:
@WebServlet(urlPatterns = "/some.do", asyncSupported = true )
public class AsyncServlet extends HttpServlet
...
- 1
- 2
- 3
如果使用web.xml设定Servlet,则可以设定标签为true :
...
<servlet>
<servlet-name>AsyncServlet</servlet-name>
<servlet-class>com.pkgname.AsyncServlet</servlet-class>
<async-supported>true</async-supported>
</servlet>
...
- 1
- 2
- 3
- 4
- 5
- 6
- 7
如果Servlet将会异步处理,若其前端有过滤器,则过滤器亦需标示其支援异步处理,如果使用@WebFilter ,同样是可以设定其asyncSupported为true 。 例如:
@WebFilter(urlPatterns = "/some.do", asyncSupported = true )
public class AsyncFilter implements Filter{
...
- 1
- 2
- 3
如果使用web.xml设定过滤器,则可以设定标签为true :
...
<filter>
< filter -name>AsyncFilter</ filter -name>
< filter -class>com.pkgname.AsyncFilter</ filter -class>
<async-supported>true</async-supported>
</ filter >
...
- 1
- 2
- 3
- 4
- 5
- 6
- 7
注意:
使用异步处理方式,web容器的请求处理线程释放了,可以服务其他的请求处理。但是该Request的处理并没有结束,在使用AsyncContext的complete或者dispatch完成后,这个request的处理才结束。
简单的示例:
- 1
- 2
package com.ss;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.servlet.AsyncContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
// import com.cndatacom.thread.BusinessHandleThread;
/**
* 异步处理Servlet
* @author
*/
/**
* asyncSupported属性默认是false,如果需要开启支持异步处理功能,需要设置为true
*/
@WebServlet(name = "AsyncServlet", urlPatterns = "/AsyncServlet2", asyncSupported = true)
public class AsyncServlet2 extends HttpServlet {
/**
*
*/
private static final long serialVersionUID = -2749650094193187229L;
@Override
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
response.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
PrintWriter out = response.getWriter();
Date date = new Date(System.currentTimeMillis());
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss Z");
out.println("Servlet begin --" + sdf.format(date) + "<br>");// 响应输出到客户端
// 进入异步模式,调用业务处理线程进行业务处理
// Servlet不会被阻塞,而是直接往下执行
// 业务处理完成后的回应由AsyncContext管理
AsyncContext asyncContext = request.startAsync();
BusinessWorkerThread businessHandleThread = new BusinessWorkerThread(
asyncContext);
Thread thread = new Thread(businessHandleThread);
thread.start();
//asyncContext.start(businessHandleThread);//也可以用这种方法启动异步线程
date = new Date(System.currentTimeMillis());
out.println("Servlet end --" + sdf.format(date) + "<br>");
out.flush();
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
------
- 1
- 2
package com.ss;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.servlet.AsyncContext;
import javax.servlet.ServletResponse;
/**
* 业务处理线程
*
* @author
*/
public class BusinessWorkerThread implements Runnable {
// 异步操作的上下文对象,通过构造方法传进来
private AsyncContext asyncContext;
public BusinessWorkerThread(AsyncContext asyncContext) {
this.asyncContext = asyncContext;
}
@Override
public void run() {
try {
// do some work...
Thread.sleep(8000); // 和browser的timeout时间相关。如果browser上timeout是30s,则大于30时,网络已经断开。这是就会异常。
ServletResponse response = asyncContext.getResponse();
PrintWriter out = response.getWriter();
Date date = new Date(System.currentTimeMillis());
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss Z");
out.println("business worker finished --"+ sdf.format(date));// 响应输出到客户端
// 告诉启动异步处理的Servlet异步处理已完成,Servlet就会提交请求响应
asyncContext.complete();
} catch (Exception e) {
e.printStackTrace();
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
输出: 在浏览器中,输出的内容按照后面的时间显示在页面上。
- 1
- 2
Servlet begin --22:33:57 +0800
Servlet end --22:33:57 +0800
business worker finished --22:34:05 +0800
- 1
- 2
- 3
注意: 使用浏览器访问,因为各个浏览器的http请求超时设置不同,比如我的chrome是30秒。AsyncContext中对应的工作线程的持续时间需要小于浏览器的http超时时间。
AsyncListener
AsyncContext还可以设置一个Listener,对4个事件进行处理:
示例:
package com.ss;
import java.io.IOException;
import javax.servlet.AsyncContext;
import javax.servlet.AsyncEvent;
import javax.servlet.AsyncListener;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class AsyncServletTest
*/
@WebServlet(asyncSupported = true, urlPatterns = { "/AsyncTest" })
public class AsyncServletTest extends HttpServlet {
String param = "";
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public AsyncServletTest() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
* response)
*/
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// 1 start async
final AsyncContext ctx = req.startAsync();
param = ctx.getRequest().getParameter("seq");
System.out.println("getRequest request seq: " + param);
// 2 set the timeout
ctx.setTimeout(0);
// 3 add listener
ctx.addListener(new AsyncListener() {
@Override
public void onTimeout(AsyncEvent arg0) throws IOException {
System.out.println("onTimeout...");
}
@Override
public void onStartAsync(AsyncEvent arg0) throws IOException {
System.out.println("onStartAsync...");
}
@Override
public void onError(AsyncEvent arg0) throws IOException {
System.out.println("onError...");
}
@Override
public void onComplete(AsyncEvent arg0) throws IOException {
System.out.println("onComplete...");
}
});
// 4 run a thread
ctx.start(new Runnable() {
@Override
public void run() {
String seq = ctx.getRequest().getParameter("seq");
System.out.println(">>>>>now respone: " + seq);
int n = 0;
try {
// hold until receive exit
while (!param.equals("exit")) {
n++;
if (n % 100000000 == 0) {
System.out.println(seq + ": ..." + n);
//
}
}
ctx.getResponse().getWriter().write(seq+" -- "+n);
} catch (IOException e) {
e.printStackTrace();
}
ctx.complete();
}
});
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
System.out.println("doPost...");
}
}
相关推荐
Tomcat简单的说就是一个运行JAVA的网络服务器,底层是Socket的一个程序,它也是JSP和Serlvet的一个容器。如果你学过html,css,你会知道你写的页面只能自己访问,别人不能远程访问你写的页面,Tomcat就是提供能够让...
- **Tomcat**:作为Servlet容器运行应用。 - **MVC模式**:Model-View-Controller架构设计,用于分离业务逻辑、数据和用户界面。 - **HTML/CSS/JavaScript**:用于构建前端页面。 - **Ajax**:实现异步通信,...
Apache Tomcat V6.0 Tomcat是一个免费的开源的Serlvet容器,它是Apache基金会的Jakarta项目中的一个核心项目,由Apache,Sun和其它一些公司及个人共同开发而成。由于有了Sun的参与和支持,最新的Servlet和Jsp规范总...
Tomcat是一个免费的开源的Serlvet容器,它是Apache基金会的Jakarta项目中的一个核心项目,由Apache,Sun和其它一些公司及个人共同开发而成。由于有了Sun的参与和支持,最新的Servlet和Jsp规范总能在Tomcat中得到体现...
Tomcat是一个免费的开源的Serlvet容器,它是Apache基金会的Jakarta项目中的一个核心项目,由Apache,Sun和其它一些公司及个人共同开发而成。由于有了Sun的参与和支持,最新的Servlet和Jsp规范总能在Tomcat中得到体现...
Tomcat是一个免费的开源的Serlvet容器,它是Apache基金会的Jakarta项目中的一个核心项目,由Apache,Sun和其它一些公司及个人共同开发而成。由于有了Sun的参与和支持,最新的Servlet和Jsp规范总能在Tomcat中得到体现...
总的来说,Jakarta Tomcat 5.0.30是一款高效且可靠的Web服务器,它的轻量级特性使得它成为中小型项目的理想选择。通过深入理解其内部结构和配置,开发者能够更好地利用Tomcat构建和部署Java Web应用,从而提高开发...
Apache Tomcat是一个免费的开源的Serlvet容器,它是Apache基金会的Jakarta项目中的一个核心项目,由Apache,Sun和其它一些公司及个人共同开发而成。由于有了Sun的参与和支持,最新的Servlet和Jsp规范总能在Tomcat中...
在实现这些功能时,开发者可能使用了工具如Eclipse或IntelliJ IDEA作为集成开发环境,Tomcat或Jetty作为Servlet容器,MySQL或Oracle作为后台数据库。他们可能还介绍了如何使用MVC(Model-View-Controller)设计模式...
Tomcat是一个免费的开源的Serlvet容器,它是Apache基金会的Jakarta项目中的一个核心项目,由Apache,Sun和其它一些公司及个人共同开发而成。由于有了Sun的参与和支持,最新的Servlet和Jsp规范总能在Tomcat中得到体现...
serlvet-api.jar。使用tomcat开发时,需要引入的jar包。
Tomcat 是一个免费的开源的 Serlvet 容器,它是 Apache 基金会的 Jakarta 项目中的一个核心项目,由 Apache,Sun 和其它一些公司及个人共同开发而成。由于有了 Sun的参与和支持,最新的 Servlet 和 Jsp 规范总能在 ...
总的来说,"jsp+serlvet BBS系统"是一个典型的Web应用开发实例,它涵盖了Web开发的多个关键领域,对于学习和理解Java Web技术,尤其是JSP和Servlet的结合使用,具有很高的实践价值。通过深入研究这个项目,开发者...
3. **启动Tomcat**: 进入Tomcat的`bin`目录,运行`startup.bat`脚本来启动Tomcat。 4. **访问测试**: 浏览器访问`http://localhost:8080/`,如果看到Tomcat的默认欢迎页面,则表示安装成功。 #### 五、Web项目的...
首先,Servlet的基本工作流程是:客户端发送HTTP请求到服务器,服务器接收到请求后,通过Servlet容器(如Tomcat)调用相应的Servlet实例进行处理。Servlet根据请求内容执行业务逻辑,然后生成响应,最后由服务器将...
Tomcat是一个免费的开源的Serlvet容器,它是Apache基金会的Jakarta项目中的一个核心项目,由Apache,Sun和其它一些公司及个人共同开发而成。由于有了Sun的参与和支持,最新的Servlet和Jsp规范总能在Tomcat中得到体现...
java serlvet 高校学生画像平台系统是一套完善的java web信息管理系统 系统采用serlvet+dao+bean 模式开发本系统,对理解JSP java编程开发语言有帮助,系统具有完整的源代 码和数据库,系统主要采用B/S模式开发。...
**7. 用户界面与交互设计** 用户界面应直观易用,提供清晰的操作指南和反馈信息。在仓库管理系统中,可能包括库存查询、入库出库操作、订单管理等功能模块,每个模块都需要良好的用户体验设计,使工作人员能快速熟悉...
在"serlvet_1_web_"这个主题中,我们主要探讨的是Servlet的基本概念、工作原理以及如何进行入门级别的编程实践。 Servlet是一种Java类,它扩展了服务器的功能,使得我们可以编写代码来动态生成Web内容。Servlet...