模拟异步调用
import com.springdemo2.service.helloService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.concurrent.Callable;
@RestController
public class HelloController2 {
private static final Logger logger = LoggerFactory.getLogger(HelloController.class);
@Autowired
private helloService hello;
@GetMapping("/helloworld")
public String helloWorldController() {
logger.info(Thread.currentThread().getName() + " 进入helloWorldController方法");
String say = hello.sayHello();
logger.info("请求完成");
return say;
}
/**
* 异步调用restful
* 当controller返回值是Callable的时候,springmvc就会启动一个线程将Callable交给TaskExecutor去处理
* 然后DispatcherServlet还有所有的spring拦截器都退出主线程,然后把response保持打开的状态
* 当Callable执行结束之后,springmvc就会重新启动分配一个request请求,然后DispatcherServlet就重新
* 调用和处理Callable异步执行的返回结果, 然后返回视图
*
* @return
*/
@GetMapping("/hello1")
public Callable<String> helloController() {
logger.info(Thread.currentThread().getName() + " 进入helloController方法");
Callable<String> callable = new Callable<String>() {
@Override
public String call() throws Exception {
logger.info(Thread.currentThread().getName() + " 进入call方法");
// 从这里写耗时任务的代码
String say = hello.sayHello();
//
logger.info(Thread.currentThread().getName() + " 从helloService方法返回");
return say;
}
};
logger.info(Thread.currentThread().getName() + " 从helloController方法返回");
return callable;
}
}
模拟耗时请求
import org.springframework.stereotype.Component;
@Component
public class helloService {
public String sayHello(){
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "aa";
}
}
日志
helloController调用新线程处理任务,而helloWorldController为当前线程处理,阻塞当前线程
2019-03-18 20:13:56.171 INFO 7495 --- [io-8080-exec-10] c.s.contorller.HelloController : http-nio-8080-exec-10 进入helloController方法
2019-03-18 20:13:56.171 INFO 7495 --- [io-8080-exec-10] c.s.contorller.HelloController : http-nio-8080-exec-10 从helloController方法返回
2019-03-18 20:13:56.172 INFO 7495 --- [ task-9] c.s.contorller.HelloController : task-9 进入call方法
2019-03-18 20:13:57.222 INFO 7495 --- [nio-8080-exec-1] c.s.contorller.HelloController : http-nio-8080-exec-1 进入helloController方法
2019-03-18 20:13:57.222 INFO 7495 --- [nio-8080-exec-1] c.s.contorller.HelloController : http-nio-8080-exec-1 从helloController方法返回
2019-03-18 20:13:57.223 INFO 7495 --- [ task-10] c.s.contorller.HelloController : task-10 进入call方法
2019-03-18 20:13:58.084 INFO 7495 --- [nio-8080-exec-2] c.s.contorller.HelloController : http-nio-8080-exec-2 进入helloController方法
2019-03-18 20:13:58.084 INFO 7495 --- [nio-8080-exec-2] c.s.contorller.HelloController : http-nio-8080-exec-2 从helloController方法返回
2019-03-18 20:13:58.084 INFO 7495 --- [ task-11] c.s.contorller.HelloController : task-11 进入call方法
2019-03-18 20:14:06.176 INFO 7495 --- [ task-9] c.s.contorller.HelloController : task-9 从helloService方法返回
2019-03-18 20:14:07.223 INFO 7495 --- [ task-10] c.s.contorller.HelloController : task-10 从helloService方法返回
2019-03-18 20:14:08.087 INFO 7495 --- [ task-11] c.s.contorller.HelloController : task-11 从helloService方法返回
2019-03-18 20:14:20.996 INFO 7495 --- [nio-8080-exec-7] c.s.contorller.HelloController : http-nio-8080-exec-7 进入helloWorldController方法
2019-03-18 20:14:22.051 INFO 7495 --- [nio-8080-exec-8] c.s.contorller.HelloController : http-nio-8080-exec-8 进入helloWorldController方法
2019-03-18 20:14:22.836 INFO 7495 --- [nio-8080-exec-9] c.s.contorller.HelloController : http-nio-8080-exec-9 进入helloWorldController方法
2019-03-18 20:16:56.858 INFO 7499 --- [nio-8080-exec-1] c.s.contorller.HelloController : http-nio-8080-exec-1请求完成
2019-03-18 20:16:57.424 INFO 7499 --- [nio-8080-exec-2] c.s.contorller.HelloController : http-nio-8080-exec-2请求完成
2019-03-18 20:16:58.058 INFO 7499 --- [nio-8080-exec-3] c.s.contorller.HelloController : http-nio-8080-exec-3请求完成