自定义注解
/**
* @ClassName RouteLog
* @Description 路由日志记录自定义注解
* @Author 何小树
* @Date 2019/11/7 15:10
**/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface RouteLogAnnotation {
//是否保存日志文件
boolean saveLog() default false;
}
AOP
依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
日志实体类
@Getter
@Setter
public class RouteLog {
private static final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
private static final RouteLog routelog = new RouteLog();
private RouteLog() {}
public static RouteLog getInstance(){return routelog;}
private String uuid;
private String routeUrl;
private Long startTime;
private String ip;
private String parameter;
@Override
public String toString() {
return " 请求路径:"+this.routeUrl+" 请求ip:"+this.ip+
" 请求时间:"+ simpleDateFormat.format(new Date(this.startTime)) +
" 请求参数:"+ this.parameter ;
}
}
AOP实现
@Aspect
@Component
public class RouteLogAspect {
private RouteLog routeLog = RouteLog.getInstance();
@Pointcut("@annotation(com.annotation.RouteLogAnnotation)")
public void routeLog(){}
@Before(value = "routeLog()")
public Object doBefore(JoinPoint joinPoint){
Object res=null;
long time = System.currentTimeMillis();
try {
insertRouteLog(joinPoint);
time=System.currentTimeMillis()-time;
} catch (Throwable throwable) {
throwable.printStackTrace();
}finally {
System.out.println("执行结束");
}
return null;
}
private void insertRouteLog(JoinPoint joinPoint){
long startTime=System.currentTimeMillis();
PrintStream ps =null;
HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
MethodSignature signature = (MethodSignature)joinPoint.getSignature();
Object[] args = joinPoint.getArgs();//访问目标方法的参数 可动态改变参数值
RouteLogAnnotation annotation = signature.getMethod().getAnnotation(RouteLogAnnotation.class);
if (annotation!=null){
boolean saveLog = annotation.saveLog();//是否开启存储文件日志记录
String ip = StringUtil.getRemoteHost(request);
String uri = request.getRequestURI();
routeLog.setStartTime(startTime);
routeLog.setIp(ip);
routeLog.setUuid(StringUtil.getUUID());
routeLog.setRouteUrl(uri);
routeLog.setParameter(Arrays.toString(args));
System.out.println("日志记录:"+routeLog.toString());
try {
//如果开始存储请求路由日记记录
if (saveLog){
String now = DateUtil.NowDateYmd();
String routePath = FileUtil.getJarPath("routeLog")+now+".txt";
Path path = Paths.get(routePath);
if (!Files.exists(path)){
File file = new File(routePath);
boolean newFile = file.createNewFile();
System.out.println("日志存储路径:"+routePath);
if (newFile) System.out.println("日志文件创建成功");
}else {
FileOutputStream fo = new FileOutputStream(routePath,true);
ps = new PrintStream(fo);
System.setOut(ps);
System.out.println(routeLog.toString());
}
}
} catch (IOException e) {
e.printStackTrace();
}finally {
if(ps!=null)ps.close();
}
}
}
@AfterReturning(returning = "result", pointcut = "routeLog()")
public void doAfterReturning(Object result){
System.out.println("Result:"+result.toString());
}
}
路径方法
/**
* 项目jar 部署时,获取jar同级目录,用于图片存储等
* @param subdirectory
* @return
*/
public static String getJarPath(String subdirectory){
//获取跟目录---与jar包同级目录的upload目录下指定的子目录subdirectory
File upload = null;
try {
//本地测试时获取到的是"工程目录/target/upload/subdirectory
File path = new File(ResourceUtils.getURL("classpath:").getPath());
if(!path.exists()) path = new File("");
upload = new File(path.getAbsolutePath(),subdirectory);
if(!upload.exists()) upload.mkdirs();//如果不存在则创建目录
return upload + File.separator;
} catch (FileNotFoundException e) {
throw new RuntimeException("获取服务器路径发生错误!");
}
}
这只是个基础实现,切入点是自定义注解;就实现了 请求方法上有注解的才会进入日志记录。
这里是,实现存储存日志文件 ,也可以存储数据库,可以做很多扩展。
普通访问日志切面:
import cn.czc.kingdee.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
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.util.Objects;
/**
* @program: zyd
* @description: 访问日志切面
* @author: he
* @create: 2020-08-24 16:50
**/
@Slf4j
@Aspect
@Component
public class RouteLogAspect {
@Pointcut("execution(* cn.czc.kingdee.controller..*(..))")
public void routeLog(){}
@Before(value = "routeLog()")
public Object before(JoinPoint joinPoint){
HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
Object[] args = joinPoint.getArgs();
String ip = StringUtil.getIp(request);
String uri = request.getRequestURI();
log.info("访问ip:{} , api:{} ,请求参数: {}",ip,uri,args);
return null;
}
@AfterReturning(returning = "result", pointcut = "routeLog()")
public void doAfterReturning(Object result){
log.info("返回数据:{}",result.toString());
}
}