一.前言
使用异步servlet主要原因就是因为,在service方法中业务逻辑如果碰到io操作时间比较长的操作,这样这个service方法就会长时间占用tomcat容器线程池中的线程,这样是不利于其他请求的处理的,当线程池中的线程处理任务时,任务由于长时间io操作,肯定会阻塞线程处理其他任务,引入异步servlet的目的就是将容器线程池和业务线程池分离开。在处理大io的业务操作的时候,把这个操作移动到业务线程池中进行,释放容器线程,使得容器线程处理其他任务,在业务逻辑执行完毕之后,然后在通知tomcat容器线程池来继续后面的操作,这个操作应该是把处理结果commit到客户端或者是dispatch到其他servlet上。原始模型在处理业务逻辑的过程中会一直占有容器线程池,而异步servlet模型,可以看出在业务线程池处理的过程中,有一段时间容器线程池中的那个线程是空闲的,这种设计大大提高了容器的处理请求的能力。
二.DeferredResult的主要原理

  1. Controller返回一个DeferredResult对象,并且把它保存在内在队列当中或者可以访问它的列表中。
  2. Spring MVC开始异步处理.
  3. DispatcherServlet与所有的Filter的Servlet容器线程退出,但Response仍然开放。
  4. application通过多线程返回DeferredResult中sets值.并且Spring MVC分发request给Servlet容器.
  5. DispatcherServlet再次被调用并且继续异步的处理产生的结果.

三.示例
1.申明两个方法接口,模拟用户登录接口

public interface DeferredResultServiceInter {
    TResult login();
    void login1(DeferredResult<TResult<User>> deferredResult);
}

2.接口实现类

@Service
public class DeferredResultServiceImpl implements DeferredResultServiceInter {
    @Override
    public TResult login() {
        TResult<User> result = new TResult<>();
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        User user = new User();
        user.setPassword("123");
        user.setUsername("456");
        result.setModel(user);
        return result;
    }

    @Override
    public void login1(DeferredResult<TResult<User>> deferredResult) {
        TResult<User> result = new TResult<>();
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        User user = new User();
        user.setPassword("123");
        user.setUsername("456");
        result.setModel(user);
        String jsonString = JSONObject.toJSONString(result);

        deferredResult.setResult(result);
    }
}

3.controller方法

@RestController
public class SynController {
    private Logger logger = LoggerFactory.getLogger(SynController.class);
    @Resource
    DeferredResultServiceInter deferredResultServiceInter;

    ExecutorService executors= Executors.newCachedThreadPool();

    @GetMapping("/login")
    @Log
    public TResult<User> login() {
        TResult login = deferredResultServiceInter.login();
        return login;
    }

    @GetMapping("/login1")
    @Log
    public Callable<TResult<User>> login1() {
        Callable<TResult<User>> result = (() -> {
            return deferredResultServiceInter.login();
        });
        return result;
    }

    @GetMapping("/login2")
    @Log
    public DeferredResult<TResult<User>> login2() {
        DeferredResult<TResult<User>> deferredResult = new DeferredResult<>(5000L, "---请求超时---");
        executors.submit(new Runnable() {
            @Override
            public void run() {
                System.out.println("=====异步线程开始===="+System.currentTimeMillis());
                deferredResultServiceInter.login1(deferredResult);
                System.out.println("=====异步线程结束===="+System.currentTimeMillis());
            }
        });
        return deferredResult;
    }
}

结果:
(1)调用/login

类名称:com.example.springbootTest.controller.SynController
方法名:login
执行时间:3000毫秒

(2)调用login1

类名称:com.example.springbootTest.controller.SynController
方法名:login1
执行时间:0毫秒

(3)调用login2

类名称:com.example.springbootTest.controller.SynController
方法名:login2
执行时间:0毫秒
异步线程开始====1542945731423
异步线程结束 1542945734425

三个结果都是

{“errorCode”:0,“model”:{“id”:0,“username”:“456”,“password”:“123”,“salt”:null},“list”:null}