一 创建自定义注解
import java.lang.annotation.Retention;
import java.lang.annotation.ElementType;
import java.lang.annotation.Target;
import java.lang.annotation.RetentionPolicy;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Log {
String value() default "";
}
二 解析注解
使用@Aspect注解使得该类成为切面类
import java.lang.reflect.Method;
import java.util.Date;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import javax.servlet.http.HttpServletRequest;
import com.prostate.common.service.LogService;
import com.prostate.system.domain.UserToken;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import com.prostate.common.annotation.Log;
import com.prostate.common.dao.LogDao;
import com.prostate.common.domain.LogDO;
import com.prostate.common.utils.HttpContextUtils;
import com.prostate.common.utils.IPUtils;
import com.prostate.common.utils.JSONUtils;
import com.prostate.common.utils.ShiroUtils;
import com.prostate.system.domain.UserDO;
@Aspect
@Component
public class LogAspect {
private static final Logger logger = LoggerFactory.getLogger(LogAspect.class);
@Autowired
LogService logService;
@Pointcut("@annotation(com.common.annotation.Log)")
public void logPointCut() {
}
@Around("logPointCut()")
public Object around(ProceedingJoinPoint point) throws Throwable {
long beginTime = System.currentTimeMillis();
// 执行方法
Object result = point.proceed();
// 执行时长(毫秒)
long time = System.currentTimeMillis() - beginTime;
//异步保存日志
saveLog(point, time);
return result;
}
void saveLog(ProceedingJoinPoint joinPoint, long time) throws InterruptedException {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
LogDO sysLog = new LogDO();
Log syslog = method.getAnnotation(Log.class);
if (syslog != null) {
// 注解上的描述
sysLog.setOperation(syslog.value());
}
// 请求的方法名
String className = joinPoint.getTarget().getClass().getName();
String methodName = signature.getName();
sysLog.setMethod(className + "." + methodName + "()");
// 请求的参数
Object[] args = joinPoint.getArgs();
try {
String params = JSONUtils.beanToJson(args[0]).substring(0, 4999);
sysLog.setParams(params);
} catch (Exception e) {
}
// 获取request
HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
// 设置IP地址
sysLog.setIp(IPUtils.getIpAddr(request));
// 用户名
UserDO currUser = ShiroUtils.getUser();
if (null == currUser) {
if (null != sysLog.getParams()) {
sysLog.setUserId(-1L);
sysLog.setUsername(sysLog.getParams());
} else {
sysLog.setUserId(-1L);
sysLog.setUsername("获取用户信息为空");
}
} else {
sysLog.setUserId(ShiroUtils.getUserId());
sysLog.setUsername(ShiroUtils.getUser().getUsername());
}
sysLog.setTime((int) time);
// 系统当前时间
Date date = new Date();
sysLog.setGmtCreate(date);
// 保存系统日志
logService.save(sysLog);
}
}
通过@Pointcut指定切入点,这里指定Log注解,也就是被@Log修饰的方法,进入该切入点
① @Before 前置通知 在某连接点之前执行的通知
② @Around 环绕通知 在实现方法的前后执行的通知
③ @AfterReturning 后置通知 在某连接点正常完成执行的通知
④ @AfterThrowing 异常通知 在方法抛出异常退出执行的通知
⑤ @After 后置通知
@RequiresPermissions("base:scaleManager:edit")
@Log("编辑题目或选项")
@GetMapping("/edit/{id}")
String edit(Model model, @PathVariable("id") String id) {
ScaleDO scaleDO = scaleManagerService.get(id);
model.addAttribute("scaleDO", scaleDO);
ScaleDO scale = scaleManagerService.get(scaleDO.getParentId());
model.addAttribute("scale",scale);
return prefix+"/edit";
}
随便弄一个测试类就可测试了