1.AOP的日志拦截类中,抛出异常:
2.代码如下:
package com.jimulian.iwuxi.common.aop; import com.alibaba.fastjson.JSON; import com.jimulian.iwuxi.common.annotation.OptLogAno; import com.jimulian.iwuxi.mapper.OptLogMapper; import com.jimulian.iwuxi.pojo.OptLog; import com.jimulian.iwuxi.pojo.User; import com.jimulian.iwuxi.pojo.module.WeChatUserBean; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.aspectj.lang.reflect.MethodSignature; 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 javax.servlet.http.HttpServletRequest; import java.lang.reflect.Method; import java.util.Date; /** * @author zhangcw * @version 1.0 * @date 2019/9/18 11:55 */ @Aspect @Component public class OptLogAspect { @Autowired private OptLogMapper optLogMapper; @Pointcut("@annotation(com.jimulian.iwuxi.common.annotation.OptLogAno)") public void logPointCut(){ } @AfterReturning("logPointCut()") public void saveOptLog(JoinPoint joinPoint) { OptLog optLog =new OptLog(); //从切面织入点处通过反射机制获取织入点处的方法 MethodSignature signature = (MethodSignature) joinPoint.getSignature(); //获取切入点所在的方法 Method method = signature.getMethod(); //获取操作 OptLogAno optLogAno = method.getAnnotation(OptLogAno.class); if (optLogAno != null) { String module = optLogAno.module(); String methods = optLogAno.methods(); optLog.setModule(module); optLog.setMethods(methods); } HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()) .getRequest(); User user = (User) request.getSession().getAttribute("user_access"); if(user!=null){ optLog.setUsername(user.getUsername()); optLog.setCommite(1); } WeChatUserBean weChatUserBean = (WeChatUserBean) request.getAttribute("user"); if(weChatUserBean!=null){ optLog.setWechatuser(weChatUserBean.getName()); optLog.setCommite(2); } optLog.setDate(new Date()); // 获取访问真实IP String ipAddress = request.getRemoteAddr(); optLog.setIp(ipAddress); //获取请求路径 String actionUrl = request.getRequestURI(); optLog.setActionurl(actionUrl); //接受客户端的数据 Object[] args = joinPoint.getArgs(); //将参数所在的数组转换成json String params = JSON.toJSONString(args); optLog.setContent(params); if(optLog.getWechatuser()!=null ||optLog.getUsername()!=null){ optLogMapper.insert(optLog); } } }
3.经过查询分析其主要原因:对方法的参数使用JSON.toJSONString(args[index])转换时,有异常抛出【如果参数类型是请求和响应的http,使用JSON.toJSONString()转换会抛异常】 解决方法:将不能进行序列化的入参过滤掉,只要留下我们需要记录的入参参数记录到日志中即可 如下图:
4.完成代码如下:
package com.jimulian.iwuxi.common.aop; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.jimulian.iwuxi.common.annotation.OptLogAno; import com.jimulian.iwuxi.mapper.OptLogMapper; import com.jimulian.iwuxi.pojo.OptLog; import com.jimulian.iwuxi.pojo.User; import com.jimulian.iwuxi.pojo.module.WeChatUserBean; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.aspectj.lang.reflect.MethodSignature; 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; import java.util.Date; /** * @author zhangcw * @version 1.0 * @date 2019/9/18 11:55 */ @Aspect @Component public class OptLogAspect { @Autowired private OptLogMapper optLogMapper; @Pointcut("@annotation(com.jimulian.iwuxi.common.annotation.OptLogAno)") public void logPointCut(){ } @AfterReturning("logPointCut()") public void saveOptLog(JoinPoint joinPoint) { OptLog optLog =new OptLog(); //从切面织入点处通过反射机制获取织入点处的方法 MethodSignature signature = (MethodSignature) joinPoint.getSignature(); //获取切入点所在的方法 Method method = signature.getMethod(); //获取操作 OptLogAno optLogAno = method.getAnnotation(OptLogAno.class); if (optLogAno != null) { String module = optLogAno.module(); String methods = optLogAno.methods(); optLog.setModule(module); optLog.setMethods(methods); } HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()) .getRequest(); User user = (User) request.getSession().getAttribute("user_access"); if(user!=null){ optLog.setUsername(user.getUsername()); optLog.setCommite(1); } WeChatUserBean weChatUserBean = (WeChatUserBean) request.getAttribute("user"); if(weChatUserBean!=null){ optLog.setWechatuser(weChatUserBean.getName()); optLog.setCommite(2); } optLog.setDate(new Date()); // 获取访问真实IP String ipAddress = request.getRemoteAddr(); optLog.setIp(ipAddress); //获取请求路径 String actionUrl = request.getRequestURI(); optLog.setActionurl(actionUrl); //接受客户端的数据 /* Object[] args = joinPoint.getArgs(); //将参数所在的数组转换成json String params = JSON.toJSONString(args);*/ Object[] args = joinPoint.getArgs(); Object[] arguments = new Object[args.length]; for (int i = 0; i < args.length; i++) { if (args[i] instanceof ServletRequest || args[i] instanceof ServletResponse || args[i] instanceof MultipartFile) { //ServletRequest不能序列化,从入参里排除,否则报异常:java.lang.IllegalStateException: It is illegal to call this method if the current request is not in asynchronous mode (i.e. isAsyncStarted() returns false) //ServletResponse不能序列化 从入参里排除,否则报异常:java.lang.IllegalStateException: getOutputStream() has already been called for this response continue; } arguments[i] = args[i]; } String paramter = ""; if (arguments != null) { try { paramter = JSONObject.toJSONString(arguments); } catch (Exception e) { paramter = arguments.toString(); } } optLog.setContent(paramter); if(optLog.getWechatuser()!=null ||optLog.getUsername()!=null){ optLogMapper.insert(optLog); } } }
5.加入以上代码之后不报错了 如下图: