异步处理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()得到的实例为空,会在异步线程中报空指针异常。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值