Javaweb Servlet基础学习记录(6)—异步处理

 在Servlet的原始版本中,假设浏览器同时有多个请求发送到服务器,web服务器在处理第一个请求时,若处理占用时间较长,则其他请求在这第一个请求被处理的时间段内无法进行任何操作。

 被阻塞的Servlet请求过程:

Java 异步上传 javaweb异步提交_servlet


 Servlet3.0有了新特性异步处理,所谓异步处理就是指数据发送方发送数据给数据接收方后,不必等待数据接收方作出响应,可以继续发送下一个数据的通信方式,Servlet 3.0版本提供了相关异步处理的功能,具体实现方式如下:

  • 需要使用注解在对应Servlet配置asyncSupported=true,表示当前Servlet支持异步。
  • 通过Request对象的startAsync(Request, Response)方法获取异步上下文对象。
  • 通过异步上下文对象调用start(new Runnable(){})方法开始异步处理,Runnable类的run()方法提供具体异步的逻辑代码。

 Servlet异步处理流程:

Java 异步上传 javaweb异步提交_Java 异步上传_02


 演示:

package com;

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 implementation class AsyncDemoServlet
 */
@WebServlet(urlPatterns = "/AsyncDemoServlet", asyncSupported = true)
public class AsyncDemoServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	/**
	 * @see HttpServlet#HttpServlet()
	 */
	public AsyncDemoServlet() {
		super();
		// TODO Auto-generated constructor stub
	}

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		response.setContentType("text/html; charset=UTF-8");

		PrintWriter out = response.getWriter();
		out.print("<p>进入servlet时间" + new Date().toLocaleString() + "</p>");

		AsyncContext asctx = request.startAsync();
		new Thread(new Executor(asctx)).start();

		out.print("<p>退出servlet时间" + new Date().toLocaleString() + "</p>");
		out.flush();
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}

class Executor implements Runnable {

	private AsyncContext ctx = null;

	public Executor(AsyncContext asCtx) {
		ctx = asCtx;
	}

	@Override
	public void run() {
		try {
			Thread.sleep(10000);
			PrintWriter out = ctx.getResponse().getWriter();
			out.print("<p>子线程执行完毕" + new Date().toLocaleString() + "</p>");
			out.flush();
			ctx.complete();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

}

其中:
(1)在”WebServlet“注释中配置属性支持异步操作:@WebServlet(urlPatterns = "/AsyncDemoServlet", asyncSupported = true)
(2)创建子线程构建耗时操作:

class Executor implements Runnable {

	private AsyncContext ctx = null;
    //借助构造方法进行传参
	public Executor(AsyncContext asCtx) {
		ctx = asCtx;
	}

	@Override
	//线程真正的操作在run方法中
	public void run() {
		try {
		    //模拟耗时操作
			Thread.sleep(10000);  //睡10秒
			PrintWriter out = ctx.getResponse().getWriter();
			out.print("<p>子线程执行完毕" + new Date().toLocaleString() + "</p>");
			out.flush();
			ctx.complete();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

}

(3)主线程:

protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		response.setContentType("text/html; charset=UTF-8");

		PrintWriter out = response.getWriter();  //记录进入时间
		out.print("<p>进入servlet时间" + new Date().toLocaleString() + "</p>");

		AsyncContext asctx = request.startAsync();
		new Thread(new Executor(asctx)).start();  //启动线程

		out.print("<p>退出servlet时间" + new Date().toLocaleString() + "</p>");
		out.flush();
	}

运行

Java 异步上传 javaweb异步提交_java_03


仍在执行请求

Java 异步上传 javaweb异步提交_web_04


进入与退出时间基本一致,主线程不会产生线程阻塞

  • Servlet是运行在Servlet容器中的Java类,它能处理Web客户的HTTP请求,并产生HTTP响应;
  • Servlet技术具有高效、方便、功能强大、可移植性好等特点;
  • Servlet接口规定了必须由Servlet类实现并且由Servlet引擎识别和管理的方法集;
  • Servlet API包含两个软件包: javax.servlet包和javax.servlet.http包;
  • 简单地扩展GenericServlet和实现service()方法就可以编写一个基本的 Servlet,但若要实现一个在Web中处理HTTP的Servlet,则需要继承HttpServlet类;
  • Servlet生命周期是指Servlet实例从创建到响应客户请求直至销毁的过程;
  • Servlet的生命周期按照七种状态间的转换,可分为四个阶段:加载和实例化、初始化、处理请求、终止服务;
  • Servlet既可使用注解@WebServlet进行配置,也可在web.xml文件中配置;
  • 在Servlet中可以通过两种主要方式完成对新URL地址的转向:重定向和请求转发;
  • Servlet 3.0较之前版本,新增了注解支持、可插性支持、动态配置和异步处理等新特性。