使用WebAsyncTask與Callable實現非同步Http介面
阿新 • • 發佈:2018-12-21
1.實現一個介面
@RestController public class LocalController { private static final Log log = LogFactory.getLog(MethodHandles.lookup().lookupClass()); @RequestMapping("/ac") public WebAsyncTask<String> asyncTest() { Callable<String> callable = () -> { Thread.sleep(1000); log.info("-----asyncTest-----"); return "success"; }; return new WebAsyncTask<>(callable); } }
非常簡單
2.我們可以自定義非同步的執行緒池,超時設定和Interceptor攔截器
@Configuration public class WebMvcConfig extends WebMvcConfigurerAdapter { /** * 攔截器 * @param registry */ @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new AsynInterceptor()).addPathPatterns("/**"); super.addInterceptors(registry); } /** * 非同步設定 * @param configurer */ @Override public void configureAsyncSupport(final AsyncSupportConfigurer configurer) { configurer.setDefaultTimeout(60 * 1000L); configurer.registerCallableInterceptors(timeoutInterceptor()); configurer.setTaskExecutor(threadPoolTaskExecutor()); } /** * 超時攔截器 * @return */ @Bean public TimeoutCallableProcessingInterceptor timeoutInterceptor() { return new TimeoutCallableProcessingInterceptor(); } /** * 執行緒池 * @return */ @Bean public ThreadPoolTaskExecutor threadPoolTaskExecutor() { ThreadPoolTaskExecutor t = new ThreadPoolTaskExecutor(); t.setCorePoolSize(10); t.setMaxPoolSize(50); t.setThreadNamePrefix("YJH"); return t; } }
攔截器程式碼
public class AsynInterceptor extends HandlerInterceptorAdapter { private static final Log log = LogFactory.getLog(MethodHandles.lookup().lookupClass()); @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { log.info("preHandle"); return super.preHandle(request, response, handler); } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { log.info("postHandle"); super.postHandle(request, response, handler, modelAndView); } /** * 用於處理非同步請求,當Controller中有非同步請求方法的時候會觸發該方法時, * 非同步請求先支援preHandle、然後執行afterConcurrentHandlingStarted。 * 非同步執行緒完成之後執行preHandle、postHandle、afterCompletion。 * @param request * @param response * @param handler * @throws Exception */ @Override public void afterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { log.info("afterConcurrentHandlingStarted"); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { log.info("afterCompletion"); } }
會發現,非同步請求先支援preHandle、然後執行afterConcurrentHandlingStarted。非同步執行緒完成之後執行preHandle、postHandle、afterCompletion。
3.實現一個Filter
@Slf4j
@Order(2)
@WebFilter(urlPatterns = {"/*"}, filterName = "allFilter", asyncSupported = true)
public class AllFilter implements Filter {
@Override
public void init(FilterConfig arg0) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
try {
log.info("before doFilter");
chain.doFilter(request, response);
} finally {
// 判斷是否非同步
if (isAsyncStarted((HttpServletRequest) request) || request.isAsyncStarted()) {
log.info("AllFilter is async");
return;
}
log.info("finally doFilter");
}
}
@Override
public void destroy() {
}
protected boolean isAsyncStarted(HttpServletRequest request) {
return WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted();
}
}
asyncSupported = true一定要設定,否則會報錯。