作用: 在方法上加上@Async()注解就能使该方法变为异步方法,就会开启新的线程去执行
注意: 适用于非controller层
Async注解定义:
package com.future.common.annotation; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Retention; import java.lang.annotation.Target; @Retention(RUNTIME) @Target(METHOD) public @interface Async {}
拦截器代码:
package com.future.common.interceptor; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import com.future.common.annotation.Async; import com.jfinal.aop.Interceptor; import com.jfinal.aop.Invocation; public class AsyncInterceptor implements Interceptor { private static ExecutorService cachedPool = Executors.newCachedThreadPool(); @Override public void intercept(Invocation inv) { if (inv.getMethod().getAnnotation(Async.class) != null) { //无返回值方法 if (inv.getMethod().getReturnType().equals(Void.TYPE)) { cachedPool.submit(() -> { inv.invoke(); }); //需要返回值方法 } else { @SuppressWarnings("unchecked") Future<Object> future = cachedPool.submit(() -> { inv.invoke(); return ((Future<Object>) inv.getReturnValue()).get(); }); inv.setReturnValue(future); } return; } else { inv.invoke(); } } }
无返回值方法使用:
@Async() public void validateUser(String usernameOrPhone, String password) { SysUser user = this.sysUserDao.findUserByUsernameOrPhone(usernameOrPhone); if (user == null) { throw new AuthenticationException("不存在用户名为[" + usernameOrPhone + "]的用户!"); } if("0".equals(user.getSfyxdl()) || StrKit.isBlank(user.getSfyxdl())){ throw new AuthenticationException("该员工不允许登录系统!"); } String passwordDb = user.getPassword(); if (passwordDb == null || !passwordDb.equals(SecureUtil.md5(password))) { throw new AuthenticationException("密码错误!"); } }
有返回值方法使用:
注意返回值要是Futrue类型的
@Async() public Future<SysUser> findUserById(String userid) { if(StrKit.isBlank(userid)){ throw new AppException("用户信息为空!"); } return CompletableFuture.completedFuture(this.sysUserDao.findById(userid)); }
调用者获取返回值:
Future<SysUser> user = this.sysUserService.findUserById(userid); SysUser u = user.get();
关注我的公众号,免费获取Java + Jfinal学习视频
如果是为了让客户端尽快得到响应, inv.invoke() 后面应该还要添加一句:
inv.getController().renderNull();
因为在新原线程响应客户端以后, response 已经有 render 动作向其输出信息了,如果异步线程中再次对 response 输出信息会出问题