Servlet 3.0中支持异步的HTTP请求,本章基于Spring Boot 搭建一个基于Servlet 3.0异步HTTP服务,如果你对异步和同步还有疑问或者概念不清晰,请自行上网查阅相关资料。
- 在pom.xml中引入配置
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
- 建立Service层接口
public interface PiceaService {
//无返回参数方法
void task() throws Exception;
//有返回参数方法
String task2() throws Exception;
}
- 建立Service层实现
Service层接口与实现,跟其他正常同步请求一样,没有差别。
@Service
public class PiceaServiceImpl implements PiceaService {
@Override
public void task() throws Exception {
System.out.println("------------------------在看貂蝉,不要打扰--------------");
Thread.sleep(1000);
}
@Override
public String task2 () throws Exception {
int k = 1;
System.out.println("------------------------在看鱼,不要打扰--------------");
Thread.sleep(1000);
return (String.valueOf(k));
}
}
- 最重要的一步,建立Contoller层方法
在Contoller层,主要是利用了Servlet 3.0为异步处理提供的监听器,使用AsyncListener接口表示。此接口负责管理异步事件,它可以监控如下四种事件:
1). 异步线程开始时,调用AsyncListener的onStartAsync(AsyncEvent event)方法;
2). 异步线程出错时,调用AsyncListener的onError(AsyncEvent event)方法;
3). 异步线程执行超时,则调用AsyncListener的onTimeout(AsyncEvent event)方法;
4). 异步执行完毕时,调用AsyncListener的onComplete(AsyncEvent event)方法;
@RestController
public class PiceaServletContoller {
@Autowired
private PiceaService piceaService;
@RequestMapping("/task")
public void task(HttpServletRequest request,
HttpServletResponse response) throws Exception {
piceaService.task();
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
response.getWriter().println("这个是无返回的处理方法");
}
@RequestMapping("/asyncTask")
public void asyncTask(HttpServletRequest request,
HttpServletResponse response) throws Exception {
System.out.println("控制层线程:" + Thread.currentThread().getName());
AsyncContext asyncContext = request.startAsync();
asyncContext.addListener(new AsyncListener() {
@Override
public void onComplete(AsyncEvent asyncEvent) throws IOException {
// 异步执行完毕时
System.out.println("异步执行完毕");
}
@Override
public void onTimeout(AsyncEvent asyncEvent) throws IOException {
//异步线程执行超时
System.out.println("异步线程执行超时");
}
@Override
public void onError(AsyncEvent asyncEvent) throws IOException {
//异步线程出错时
System.out.println("异步线程出错");
}
@Override
public void onStartAsync(AsyncEvent asyncEvent) throws IOException {
//异步线程开始时
System.out.println("异步线程开始");
}
});
asyncContext.setTimeout(3000);
asyncContext.start(new Runnable() {
@Override
public void run() {
try {
System.out.println("异步执行线程:" + Thread.currentThread().getName());
String str = piceaService.task2();
Thread.sleep(1000);
asyncContext.getResponse().setCharacterEncoding("UTF-8");
asyncContext.getResponse().setContentType("text/html;charset=UTF-8");
asyncContext.getResponse().getWriter().println("这是【异步】的请求返回: " +str);
} catch (InterruptedException e) {
e.printStackTrace();
}catch (Exception e) {
e.printStackTrace();
}
//异步请求完成通知,所有任务完成了,才执行
asyncContext.complete();
}
});
}
}
- 测试结果及方法
浏览器中分别访问http://localhost:2001/task和http://localhost:2001/asyncTask测试结果。
在异步时,明显可以看到执行线程是不一样的。
Spring-boot-async-servlet.png
老板,欢迎下次再来!
其它注意
本文章样例:
工程名:spring-boot-async-servlet
GitHub:https://github.com/zzyjb/SpringBootLearning
网友评论