异常:java.lang.IllegalStateException: It is illegal to call this method if the current request is not in asynchronous mode (i.e. isAsyncStarted() returns false)
package cn.bainuo.gene.aspect;
import cn.bainuo.gene.common.utils.RedisUserUtil;
import cn.bainuo.gene.security.domain.User;
import cn.bainuo.gene.security.domain.vo.UserInfoVo;
import cn.bainuo.gene.security.service.LoginService;
import cn.bainuo.gene.utils.utils.HttpRequestUtil;
import cn.bainuo.gene.utils.utils.StringUtils;
import cn.bainuo.gene.utils.utils.SystemControllerLog;
import cn.bainuo.gene.utils.utils.SystemServiceLog;
import com.alibaba.fastjson.JSON;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
@Aspect
@Component
@SuppressWarnings("all")
public class SystemLogAspect {
Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
private LoginService loginService;
@Autowired
private RedisUserUtil redisUserUtil;
@Pointcut("@annotation(cn.bainuo.gene.utils.utils.SystemServiceLog)")
public void serviceAspect(){
}
@Pointcut("@annotation(cn.bainuo.gene.utils.utils.SystemControllerLog)")
public void controllerAspect(){
}
@Before("controllerAspect()")
public void doBefore(JoinPoint joinPoint) {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
String token =(String)request.getAttribute("token");
String userName="";
if(StringUtils.isNotBlank(token)) {
//读取session中的用户,注意:proai项目中读取redis缓存用户数据异常.
// UserInfoVo user = redisUserUtil.getCurrentUser(token);
User userInfoVo = loginService.getUserInfo(token);
userName=userInfoVo.getUserName();
}
//请求的IP
String ip = request.getRemoteAddr();
String params = "";
Object[] arguments = new Object[joinPoint.getArgs().length];
if (joinPoint.getArgs() != null && joinPoint.getArgs().length > 0) {
for (int i = 0; i < joinPoint.getArgs().length; i++) {
//这里出现参数不能转换问题,想了半天最后发现里面有request对象不能被序列化
//最后把这些对象过滤了。
// params += JSON.toJSON(joinPoint.getArgs()[i]) + ";";
if (joinPoint.getArgs()[i] instanceof ServletRequest || joinPoint.getArgs()[i] instanceof ServletResponse || joinPoint.getArgs()[i] instanceof MultipartFile) {
//HttpServletRequest不能序列化,从入参里排除,否则报异常:java.lang.IllegalStateException:
// It is illegal to call this method if the current request is not in asynchronous mode
// (i.e. isAsyncStarted() returns false)
continue;
}
arguments[i] = joinPoint.getArgs()[i];
}
}
if (arguments != null && arguments.length > 0) {
try {
//这里有个很严重的问题,因为JSON序列化有问题,所以这里会报错,改为Google 的Gson类来转换即可
params = JSON.toJSONString(arguments);
} catch (Exception e) {
params = arguments.toString();
}
}
try {
//*========控制台输出=========*//
logger.info("=====前置通知开始=====");
logger.info("请求方法:" + (joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()"));
logger.info("方法描述:" + getControllerMethodDescription(joinPoint));
logger.info("请求人:" + userName);
logger.info("请求IP:" + ip);
logger.info("请求参数:" + params);
logger.info("=====前置通知结束=====");
} catch (Exception e) {
//记录本地异常日志
logger.error("==前置通知异常==");
logger.error("异常信息:{}", e.getMessage());
}
}
@AfterThrowing(pointcut = "serviceAspect()",throwing = "e")
public void doAfterThrowing(JoinPoint joinPoint, Throwable e){
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
String token =(String)request.getAttribute("token");
String userName="";
if(StringUtils.isNotBlank(token)) {
//读取session中的用户 注意:proai项目中读取redis缓存用户数据异常.
// UserInfoVo user = redisUserUtil.getCurrentUser(token);
User userInfoVo = loginService.getUserInfo(token);
userName=userInfoVo.getUserName();
}
//获取请求ip
String ip = HttpRequestUtil.getHost(request);
//获取用户请求方法的参数并序列化为JSON格式字符串
String params = "";
Object[] arguments = new Object[joinPoint.getArgs().length];
if (joinPoint.getArgs() != null && joinPoint.getArgs().length > 0) {
for (int i = 0; i < joinPoint.getArgs().length; i++) {
// params += JSON.toJSON(joinPoint.getArgs()[i]) + ";";
if (joinPoint.getArgs()[i] instanceof ServletRequest || joinPoint.getArgs()[i] instanceof ServletResponse || joinPoint.getArgs()[i] instanceof MultipartFile) {
//HttpServletRequest不能序列化,从入参里排除,否则报异常:java.lang.IllegalStateException:
// It is illegal to call this method if the current request is not in asynchronous mode
// (i.e. isAsyncStarted() returns false)
continue;
}
arguments[i] = joinPoint.getArgs()[i];
}
}
if (arguments != null && arguments.length > 0) {
try {
params = JSON.toJSONString(arguments);
} catch (Exception e1) {
params = arguments.toString();
}
}
try {
StackTraceElement s= e.getStackTrace()[0];
/*========控制台输出=========*/
logger.info("=====异常通知开始=====");
logger.info("异常代码类/方法/行数:" +joinPoint.getTarget().getClass().getName()+"/"+s.getMethodName()+"/"+s.getLineNumber());
/*logger.info("异常方法:" + (joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()"));*/
logger.info("方法描述:" + getServiceMethodDescription(joinPoint));
logger.info("请求人:" + userName);
// logger.info("请求IP:" + ip);
logger.info("请求参数:" + params);
logger.info("=====异常通知结束=====");
} catch (Exception ex) {
//记录本地异常日志
logger.error("==异常通知异常==");
logger.error("异常信息:{}", ex.getMessage());
}
}
public static String getServiceMethodDescription(JoinPoint joinPoint)throws Exception{
String targetName = joinPoint.getTarget().getClass().getName();
String methodName = joinPoint.getSignature().getName();
Object[] arguments = joinPoint.getArgs();
Class targetClass = Class.forName(targetName);
Method[] methods = targetClass.getMethods();
String description = "";
for (Method method:methods) {
if (method.getName().equals(methodName)){
Class[] clazzs = method.getParameterTypes();
if (clazzs.length==arguments.length){
description = method.getAnnotation(SystemServiceLog.class).description();
break;
}
}
}
return description;
}
public static String getControllerMethodDescription(JoinPoint joinPoint) throws Exception {
String targetName = joinPoint.getTarget().getClass().getName();
String methodName = joinPoint.getSignature().getName();
Object[] arguments = joinPoint.getArgs();
Class targetClass = Class.forName(targetName);
Method[] methods = targetClass.getMethods();
String description = "";
for (Method method : methods) {
if (method.getName().equals(methodName)) {
Class[] clazzs = method.getParameterTypes();
if (clazzs.length == arguments.length) {
description = method.getAnnotation(SystemControllerLog. class).description();
break;
}
}
}
return description;
}
}
最初的观察并没有发现明显的问题,因为paramter本身就是String类型; 后进行debug后,定位出问题所在位置: paramter = JSON.toJSONString(args); 在执行后报错:java.lang.IllegalStateException: It is illegal to call this method if the current request is not in asynchronous mode (i.e. isAsyncStarted() returns false)
上网查询资料后发现,是因为使用 Object[] args = joinPoint.getArgs(); 获取入参的时候,args还包含了一些其他的内容,比如ServletRequest等,而这些入参并不能进行序列化,所以JSON.toJSONString时报错,只能注释这行代码了,重新改造一下,在上面的代码中已经实现了。
if (joinPoint.getArgs() != null && joinPoint.getArgs().length > 0) {
for (int i = 0; i < joinPoint.getArgs().length; i++) {
//这里出现参数不能转换问题,想了半天最后发现里面有request对象不能被序列化
//最后把这些对象过滤了。
// params += JSON.toJSON(joinPoint.getArgs()[i]) + ";";
arguments[i] = joinPoint.getArgs()[i];
}
}