最近使用了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
("/asyncLogin3" ) @ResponseBody public WebAsyncTask<String> webLogin () { Callable<String> callable = new Callable<String>() { public String call () throws Exception { 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
近期评论