spring 异步请求 异步请求-拦截器 其他

最近使用了spring的异步请求,特此记录一下。

顾名思义,当一个请求到达服务端,服务器会有一个对应的servlet线程进行处理,异步请求的特点在于,servet线程在拿到真正的返回对象,sping可以释放此servlet,用于处理其他请求,提高并发量。再有真正的响应时,spring再将结果返回前端。直接看代码。

异步之Callable

1
2
3
4
5
6
7
8
9
10
("/asyncLogin1")
@ResponseBody
public Callable<String> (){
return new Callable<String>() {
@Override
public String call() throws Exception {
return "callable";
}
};
}

异步之DeferedResult

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
("/asyncLogin2")
@ResponseBody
public DeferredResult<String> asyncLogin() {
DeferredResult<String> deferredResult = new DeferredResult<String>(29000l);
deferredResult.onTimeout(new Runnable(){
@Override
public void run() {
log.info("time out");
}

});

new Thread(new Runnable(){

@Override
public void run() {
try {
Thread.currentThread().sleep(1000l);
} catch (InterruptedException e) {
e.printStackTrace();
}
deferredResult.setResult("DeferredResult");
}

}).start();
return deferredResult;
}

异步之WebAsyncTask

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47

* async-1使用callable方式,如想设置超时,设置错误处理,可以使用其wrapper类WebAsyncTask
*
* @return
*/
("/asyncLogin3")
@ResponseBody
public WebAsyncTask<String> webLogin() {
Callable<String> callable = new Callable<String>() {
public String call() throws Exception {
// Thread.currentThread().sleep(5000l);
return "WebAsyncTask";
}
};

ThreadPoolTaskExecutor myTask = new ThreadPoolTaskExecutor();
myTask.setCorePoolSize(30);
myTask.setMaxPoolSize(30);
myTask.setThreadNamePrefix("WebAsyncTask-");
myTask.initialize();

WebAsyncTask task = new WebAsyncTask<String>(3000l,callable);
task.onCompletion(new Runnable(){

@Override
public void run() {
log.info("onCompletion");
}

});
task.onError(new Callable<String>() {
@Override
public String call() throws Exception {
System.out.println("=========onError......");
return "error";
}
});
task.onTimeout(new Callable<String>() {
@Override
public String call() throws Exception {
System.out.println("============onTimeout......");
return "time....out";
}
});
return task;

}

异步请求-拦截器

异步请求,会两次进入拦截器,一次是请求到达,第一次进入拦截器,拦截器的preHandle()方法被调用,当controller返回一个异步对象时,拦截器的afterConcurrentHandlingStarted()被触发;当异步请求返回真正的结果时,spring会分配一个请求,用于和返回对象关联,于是拦截器的preHandle()被第二次触发,当异步请求的结果真正返回给前端后,拦截器的afterCompletion()方法被触发。
第一次和第二次preHandle()被触发的不同在于:dispatcher Type不一样,分别对应”REQUEST” or “ASYNC”.

1
2
3
4
5
6
7
8
9
10
public class LogInterceptor extends HandlerInterceptorAdapter    {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
System.out.println("=========pre拦截==========");
System.out.println("============request============="+request.getDispatcherType());
return true;
}

}

以下图片可以详细解释拦截器的处理方式:

可以参考
https://www.logicbig.com/tutorials/spring-framework/spring-web-mvc/async-intercept.html ,对此有更细致的解释。

其他

发现一个可以免费存取图片的网站:https://sm.ms/
以及一个教程网站:https://www.logicbig.com/tutorials