异步处理Servlet接收到的请求

在Servlet组件接收到的每个请求都会产生一个线程来处理请求并返回响应,当客户端的请求处理是一项比较耗时的过程,当有大量用户请求此Servlet时,Web容器中就会产生大量的线程,导致Web容器性能急剧下降。为了解决这一问题,Servlet提供了对请求的异步处理支持。

异步处理请求的过程为:当Servlet接收到请求之后,首先需要对请求携带的数据进行一些预处理;接着,Servlet线程将请求转交给一个异步线程来执行业务处理,线程本身则返回至容器并可以处理其它客户端的请求,此时Servlet并没有差生响应数据,异步处理完业务以后,可以直接生成响应数据,或者将请求继续转发给其它Servlet。这样,Servlet线程不再是一直处于阻塞状态以等待业务逻辑的处理,而是启动异步线程之后可以立即返回。

使用异步处理,必须要配置相应的部署文件,在web.xml中通过使用<async-supported>标签设置是否需要启用异步处理支持,true表示支持,false表示不支持。当然我们也可以用注解的方式来替代在web.xml中的配置。注解则需要使用asyncSupported属性来支持异步处理。

下面我们看一个小Demo来掩饰Servlet组件的异步处理特性:

package com.yl.servlet;

import java.io.IOException;
import java.io.PrintWriter;
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;
/**
 * Servlet组件异步处理请求特性的演示小程序
 *
 * @author LYYL
 *
 */
//通过注解的方式配置,支持异步处理请求
@WebServlet(name="servlet", urlPatterns={"/asyncServlet"}, asyncSupported=true)
public class AsyncServlet extends HttpServlet{

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		processRequest(req, resp);
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		processRequest(req, resp);
	}

	protected void processRequest(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException{
		response.setContentType("text/html;charset=UTF-8");
		PrintWriter pw = response.getWriter();
		pw.println("进入Servlet的时间是:" + new Date() + ".");
		pw.flush();

		//在子线程中执行业务逻辑,并由其负责输出响应,主线程退出
		AsyncContext act = request.startAsync();
		//创建一个模拟业务逻辑执行的线程
		Executor ec = new Executor(act);
		Thread td = new Thread(ec);
		td.start();

		pw.println("<br>");
		pw.println("结束Servlet的时间是: " + new Date() + ".");
		pw.flush();
	}
	/**
	 * 内部类,模拟线程执行的业务逻辑
	 *
	 * @author LYYL
	 *
	 */
	public class Executor implements Runnable{
		private AsyncContext act = null;

		/**
		 * @param act
		 */
		public Executor(AsyncContext act) {
			this.act = act;
		}

		@Override
		public void run() {
			try {
				Thread.sleep(3000);
				PrintWriter pw = act.getResponse().getWriter();
				pw.println("<br>");
				pw.println("业务执行完的时间是: " + new Date() + ".");
				pw.flush();
				act.complete();
				pw.close();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

	}
}

最终效果,Servlet开始和结束时间基本一致,而异步线程结束的时间也就是该Servlet执行完业务逻辑的时间是我们设定的3秒之后,如图:

注意:在通过request得到AsyncContext实例的时候用的是startAsync()方法,而不是request.getAsyncContext(),如果你用的是request.getAsyncContext()得到的实例为空,会在异步线程中报空指针异常。

时间: 2024-10-12 07:44:08

异步处理Servlet接收到的请求的相关文章

Servlet处理原生Ajax请求

萌新小白人生中的第一篇博客,难免会有差错,还望各位大佬多多包涵. 1. Ajax技术简介      Ajax(Asynchronous JavaScript and XML,异步JavaScript和XML)时一种创建交互式网页应用的网页开发技术,它并不是一项新的技术,其产生的目的是用于实现页面的局部刷新.通过Ajax技术可以使之前的应用程序在每次提交时不用进行页面的整体刷新,从而提升操作的性能. 2. Servlet概念     Servlet(服务器端小程序)是使用java编写的服务器端小程

Spring+MVC Controller层接收App端请求的中文参数乱码问题。

在正文之前,说明下Filter的作用: 过滤器顾名思义就是进行过滤的,可以实现代码的定向执行和预处理.通俗点说法filter相当于加油站,request是条路,response是条路,目的地是servlet,这个加油站设在什么地方对什么数据操作可以由你来控制.备注:过滤器可以再请求和响应之前做一部分预处理,有效的过滤掉不需要的内容,而且过滤器可以被复用,节省了大量的复用代码,提高了java的代码执行效率 java的Controller层接收App的请求时,请求的参数是中文,服务器端接收到的是乱码

JSP---一个Servlet处理多个请求操作

1.Servlet public void excute(HttpServletRequest request, HttpServletResponse response) throws Exception { request.setCharacterEncoding("utf-8"); String operate = request.getParameter("operate"); if (operate == null || operate.equals(&q

Servlet(五):一个Servlet处理多个请求

一.为什么要使用一个Servlet来处理多个请求? 当浏览器发送了一次请求到服务器时,servlet容器会根据请求的url-pattern找到对应的Servlet类,执行对应的doPost或doGet方法,再将响应信息返回给浏览器,这种情况下,一个具体的Servlet类只能处理对应的web.xml中配置的url-pattern请求,一个Servlet类,一对配置信息.如果业务扩展,需要三个Servlet来处理请求,就需要再加上两个具体的Servlet类,两对配置信息,如果继续向上扩展,是不是会认

socket 错误之:OSError: [WinError 10057] 由于套接字没有连接并且(当使用一个 sendto 调用发送数据报套接字时)没有提供地址,发送或接收数据的请求没有被接受。

出错的代码 #server端 import socket import struct sk=socket.socket() sk.bind(('127.0.0.1',8080)) sk.listen() conn,addr=sk.accept() str_len1=struct.unpack('i',conn.recv(4))[0] print(sk.recv(str_len1)) str_len2=struct.unpack('i',conn.recv(4))[0] print(sk.recv

Java Servlet 接收上传文件

在Java中使用 Servlet 来接收用户上传的文件,需要用到两个apache包,分别是 commons-fileupload 和 commons-io 包: 如果直接在doPost中,使用request.getInputStream()获取ServletInputStream,这样获取到的Stream是不能直接写入文件的,比如上传一个txt文件,你会发现保存下来的txt文件不只有原本txt文件本身的内容,里面还有post请求的一些参数,比如参数分割符等: 下面就是一个使用fileupload

Java Servlet(九):转发请求与重定向请求区别

转发: <% pageContext.setAttribute("pageContextAttr", "pageContextAttribute"); request.setAttribute("requestAttr", "requestAttribute"); session.setAttribute("sessionAttr", "sessionAttribute"); ap

activemq 异步和同步接收

来点实在的代码,用例子来说明: 1.异步接收,主要设置messageListener.,然后编写onmessage方法,很简单 a.客户端发送5条消息 1 package ch02.chat; 2 3 import javax.jms.JMSException; 4 5 public class ClientTest3 { 6 7 public static void main(String[] args) throws JMSException { 8 // TODO Auto-generat

支付宝异步通知notify_url接收不了问题解决(转)

此处return_url可以成功跳转回网站页面但notify_url却接收不到支付宝的异步通知.已保证notify_url是一个外网可以访问的网址 1.网站用的是ssh框架,当支付宝发通知到我这个action再返回一个jsp会不会有问题?2.网址设置了登录检测机制,会不会造成支付宝页面跳转而接收不了success?3.到目前为止没有收到过一条来自支付宝的异步通知,会不会存在服务器配置的问题. 图中A和B要怎么检测? 你提到网址设置了登录检测机制,会不会造成支付宝页面跳转而接收不了success.