首页 > 编程语言 > Spring中注解方式的异步请求
2021
08-08

Spring中注解方式的异步请求

一、Servlet3.0异步请求

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

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1、设置支持异步处理asyncSupported = true
        //2、开启异步模式
        System.out.println("主线程开始:" + Thread.currentThread() + "==>" + System.currentTimeMillis());
        AsyncContext startAsync = req.startAsync();
        //3、业务逻辑进行异步处理,开始异步处理
        startAsync.start(new Runnable() {
            @Override
            public void run() {
                try {
                    System.out.println("副线程开始:" + Thread.currentThread() + "==>" + System.currentTimeMillis());
                    sayHello();
                    //获取到异步的上下文
                    AsyncContext asyncContext = req.getAsyncContext();
                    startAsync.complete();
                    ServletResponse response = asyncContext.getResponse();
                    response.getWriter().write("hello async!");
                    System.out.println("副线程结束:" + Thread.currentThread() + "==>" + System.currentTimeMillis());
                } catch (Exception e) {
                    e.printStackTrace();
                }

            }
        });
        System.out.println("主线程结束:" + Thread.currentThread() + "==>" + System.currentTimeMillis());
    }

    public void sayHello() throws Exception {
        System.out.println(Thread.currentThread() + "processing...");
        Thread.sleep(3000);
    }
}

打印结果:

在这里插入图片描述

二、SpringMVC的异步请求

返回Callable

@Controller
public class AsyncController {

    @ResponseBody
    @RequestMapping("/async01")
    public Callable<String> async01(){
        System.out.println("主线程开始:" + Thread.currentThread() + "==>" + System.currentTimeMillis());

        Callable<String> callable = new Callable<String>() {

            public String call() throws Exception {
                System.out.println("副线程开始:" + Thread.currentThread() + "==>" + System.currentTimeMillis());
                Thread.sleep(2000);
                System.out.println("副线程开始:" + Thread.currentThread() + "==>" + System.currentTimeMillis());

                return "async01";
            }
        };

        System.out.println("主线程结束:" + Thread.currentThread() + "==>" + System.currentTimeMillis());
        return callable;

    }
}
  • 控制器返回Callable
  • Spring进行异步处理,将Callable提交给TaskExecutor,使用一个隔离的线程进行执行
  • DispatcherServlet和所有的Filter退出Web容器的线程,但是response保持打开状态
  • Callable返回结果,SpreingMVC将请求重新派发给容器,恢复之前的处理,Callable返回值就是目标方法的返回值
  • 根据Callable返回的结果,SpringMVC继续进行视图渲染流程等(从收到请求到视图渲染)

输出结果:

在这里插入图片描述

返回DeferredResult

模拟一个消息中间件

public class DeferredResultQueue {

    private static Queue<DeferredResult<Object>> queue = new ConcurrentLinkedDeque<DeferredResult<Object>>();
    

    public static void save(DeferredResult<Object> deferredResult){
        queue.add(deferredResult);
    }
    
    public static DeferredResult<Object> get(){
        return queue.poll();
    }
}

/createOrder请求会暂时保存DeferredResultQueue中,/create请求会获取DeferredResultQueue中的请求,进行业务逻辑的处理并返回结果

@Controller
public class AsyncController {

    @ResponseBody
    @RequestMapping("/createOrder")
    public DeferredResult<Object> createOrder(){
        DeferredResult<Object> deferredResult = new DeferredResult<Object>((long)3000,"create fail");

        DeferredResultQueue.save(deferredResult);

        return deferredResult;
    }


    @ResponseBody
    @RequestMapping("/create")
    public String create(){

        String order = UUID.randomUUID().toString();
        DeferredResult<Object> deferredResult = DeferredResultQueue.get();
        deferredResult.setResult(order);
        return "success:" + order;
    }
}

到此这篇关于Spring中注解方式的异步请求的文章就介绍到这了,更多相关注解方式的异步请求内容请搜索自学编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持自学编程网!

编程技巧