zoukankan      html  css  js  c++  java
  • 23、spring注解学习——servlet3.0异步和spring的异步

    servlet3.0异步: 

    加上asyncSupported=true使支持异步

    package com.atguigu.servlet;
    
    import java.io.IOException;
    
    import javax.servlet.AsyncContext;
    import javax.servlet.ServletException;
    import javax.servlet.ServletResponse;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    @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();
                        startAsync.complete();
                        //获取到异步上下文
                        AsyncContext asyncContext = req.getAsyncContext();
                        //4、获取响应
                        ServletResponse response = asyncContext.getResponse();
                        response.getWriter().write("hello async...");
                        System.out.println("副线程结束。。。"+Thread.currentThread()+"==>"+System.currentTimeMillis());
                    } catch (Exception e) {
                    }
                }
            });        
            System.out.println("主线程结束。。。"+Thread.currentThread()+"==>"+System.currentTimeMillis());
        }
    
        public void sayHello() throws Exception{
            System.out.println(Thread.currentThread()+" processing...");
            Thread.sleep(3000);
        }
    }

    执行结果如下:

     如上截图可以看出servlet3.0的异步和servlet用的是同一个线程池

    springmvc的异步(spring会给副线程再建一个线程池)

    package com.atguigu.controller;
    
    import java.util.UUID;
    import java.util.concurrent.Callable;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.ResponseBody;
    import org.springframework.web.context.request.async.DeferredResult;
    
    import com.atguigu.service.DeferredResultQueue;
    
    
    @Controller
    public class AsyncController {
        
        
        @ResponseBody
        @RequestMapping("/createOrder")
        public DeferredResult<Object> createOrder(){
            DeferredResult<Object> deferredResult = new DeferredResult<>((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;
        }
        
        /**
         * 1、控制器返回Callable
         * 2、Spring异步处理,将Callable 提交到 TaskExecutor 使用一个隔离的线程进行执行
         * 3、DispatcherServlet和所有的Filter退出web容器的线程,但是response 保持打开状态;
         * 4、Callable返回结果,SpringMVC将请求重新派发给容器,恢复之前的处理;
         * 5、根据Callable返回的结果。SpringMVC继续进行视图渲染流程等(从收请求-视图渲染)。
         * 
         * preHandle.../springmvc-annotation/async01
            主线程开始...Thread[http-bio-8081-exec-3,5,main]==>1513932494700
            主线程结束...Thread[http-bio-8081-exec-3,5,main]==>1513932494700
            =========DispatcherServlet及所有的Filter退出线程============================
            
            ================等待Callable执行==========
            副线程开始...Thread[MvcAsync1,5,main]==>1513932494707
            副线程开始...Thread[MvcAsync1,5,main]==>1513932496708
            ================Callable执行完成==========
            
            ================再次收到之前重发过来的请求========
            preHandle.../springmvc-annotation/async01
            postHandle...(Callable的之前的返回值就是目标方法的返回值)
            afterCompletion...
            
            异步的拦截器:
                1)、原生API的AsyncListener
                2)、SpringMVC:实现AsyncHandlerInterceptor;
         * @return
         */
        @ResponseBody
        @RequestMapping("/async01")
        public Callable<String> async01(){
            System.out.println("主线程开始..."+Thread.currentThread()+"==>"+System.currentTimeMillis());
            
            Callable<String> callable = new Callable<String>() {
                @Override
                public String call() throws Exception {
                    System.out.println("副线程开始..."+Thread.currentThread()+"==>"+System.currentTimeMillis());
                    Thread.sleep(2000);
                    System.out.println("副线程开始..."+Thread.currentThread()+"==>"+System.currentTimeMillis());
                    return "Callable<String> async01()";
                }
            };
            
            System.out.println("主线程结束..."+Thread.currentThread()+"==>"+System.currentTimeMillis());
            return callable;
        }
    
    }

    执行结果如下:

    发现拦截器的preHandle执行了两次(原因即为:spring主线程结束后会再次访问该路径,从而继续执行副线程,如最后的图)

     

  • 相关阅读:
    javascript:让表单 文本框 只读,不可编辑的方法
    javascript从url中获取请求参数
    jQuery 效果函数,jquery文档操作,jQuery属性操作方法,jQuerycss操作函数,jQuery参考手册-事件,jQuery选择器
    IIS中添加MIME类型
    谷歌工作方法流程相关4本书
    发财、升职带来的幸福感很快会消失,量化研究幸福的5+3本书
    棉纺织品的历史就是工业革命和资本主义的历史:5星|《棉花帝国:一部资本主义全球史》(上)
    (严重剧透)被川岛芳子包养的民国老军医:3.5星|麦家《人生海海》
    3星|《医疗创业与投资启示录》:相关资料汇编
    3星|秦朔《文明寻思录第三辑》:时事点评文集,观点多事实少
  • 原文地址:https://www.cnblogs.com/lyh233/p/12469683.html
Copyright © 2011-2022 走看看