Spring:spring-web中DeferredResult的实现原理

19 篇文章 0 订阅
该文章通过一个模拟示例展示了如何在Spring-Web中使用DeferredResult实现异步Servlet处理。关键在于使用AsyncContext启动异步操作,并在结果准备好后通过设置request属性和调用asyncContext.dispatch()来通知容器获取结果。这种方式允许结果在当前线程或新线程中生成,提高了服务响应效率。
摘要由CSDN通过智能技术生成

        spring-web中DeferredResult是采用异步servlet实现的,以下是通过servlet的代码模拟DeferredResult的实现。

import java.io.IOException;
import java.util.concurrent.Executors;

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;

@WebServlet(value = "/testComplete", asyncSupported = true)
public class IssueServlet extends HttpServlet {

	private static final long serialVersionUID = -2504425408734161943L;

	private static final String CTX_RESULT = "CTX_RESULT";

	// true: sync; false: async
	private boolean syncHandling = true;

	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doPost(request, response);
	}

	@Override
	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		String result = (String) request.getAttribute(CTX_RESULT);

		if (result != null) {
			response.getWriter().write(result);

			return;
		}

		AsyncContext asyncContext = request.startAsync();

		boolean isAsyncStarted01 = request.isAsyncStarted();
		System.out.println("isAsyncStarted01:" + isAsyncStarted01);

		// set return result mock DeferredResult.setResult(...);
		setResult(request, asyncContext);

		boolean isAsyncStarted02 = request.isAsyncStarted();
		System.out.println("isAsyncStarted02:" + isAsyncStarted02);

		if (isAsyncStarted02) {

			return;
		} else {
			String ctxPath = request.getContextPath();
			String url = request.getRequestURI();

			System.out.println(ctxPath + "," + url);

			request.getRequestDispatcher(ctxPath + url).forward(request, response);
		}
	}

	public void setResult(HttpServletRequest request, AsyncContext asyncContext) {
		// (1) set result before doPost return,
		if (syncHandling) {
			// make result
			String ret = "this is a test";

			request.setAttribute(CTX_RESULT, ret);

			asyncContext.dispatch();   // 
		} else {
			// (2) set result after doPost return,
			Executors.newSingleThreadExecutor().execute(new Runnable() {

				public void run() {
					try {
						Thread.sleep(5); // mock time-consuming
					} catch (InterruptedException e) {
					}

					// make result
					String ret = "this is a test";

					request.setAttribute(CTX_RESULT, ret);

					asyncContext.dispatch();
				}
			});
		}
	}

}

      其中,setResult(...)是模拟DeferredResult.setResult(...)的操作,主要是将生成的结果存入request中。

      生成的结果存入request中的操作可以是在当前线程中完成,也可以在其它线程中完成,但最重要的是要在结果存入request后调用asyncContext.dispatch()。

asyncContext.dispatch()主要有2个作用:

  1. 通知servlet容器,结果已存入request中,可以去获取结果了
  2. 通知servlet容器,再次调用当前url就可以获取到结果

 于是,servlet容器会再次调用此url的servlet的doPost方法获取结果。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值