目的:
通过自定义注解,在需要监控接口调用输出日志的类或方法上,加上自定义注解,实现无侵入式接口监控。
实现:
idea结构
1、导入pom
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.4</version>
</dependency>
2、自定义注解
ApiLog
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface ApiLog {
String value() default "";
}
3、切面监控
ApiLogAspect
/**
* @Author xpf
* @Date 2024/6/28 14:11
* @Version 1.0
*/
@Aspect
@Component
@Slf4j
public class ApiLogAspect {
@Pointcut("@within(com.xpf.annotion.ApiLog)")
public void pointcut() {
}
@Around("pointcut()")
public Object around(ProceedingJoinPoint point){
Object result = null;
long start = System.currentTimeMillis();
// 获取请求URL
String url = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest().getRequestURL().toString();
String param = getParam(point);
try {
// 获取响应
result = point.proceed();
// 保存日志
System.out.println("正常日志:"+point+","+start+","+param+","+JSONObject.toJSONString(result)+","+url);
// saveLog(point, start, param, JSONObject.toJSONString(result), url, 0);
} catch (Throwable e) {
//请在controller中做好拦截
log.error("对外暴露接口非受检异常:" + e.getMessage(), e);
System.out.println("异常日志:"+ point + start + param + e.getMessage() + url );
// saveLog(point, start, param,e.getMessage(), url,1);
throw new RuntimeException("服务器异常");
}
return result;
}
private static String getParam(ProceedingJoinPoint joinPoint) {
try {
Object[] args = joinPoint.getArgs();
if (args != null && args.length > 0) {
Map<String, Object> map = new HashMap<>();
for (Object arg : args) {
if (arg instanceof HttpServletRequest) {
HttpServletRequest request = (HttpServletRequest) arg;
map.put("parameterMap", request.getParameterMap());
} else if (arg instanceof HttpServletResponse) {
continue;
} else {
map.put("body", arg);
}
}
return JSONObject.toJSONString(map);
}
} catch (Exception e) {
log.error("获取入参异常:" + e.getMessage(),e);
}
return "";
}
}
4、启动类注解扫描 @EnableAspectJAutoProxy
@EnableAspectJAutoProxy
@ComponentScan(basePackages={"com.xpf.*"})
@SpringBootApplication
public class MySpringTestApplication {
public static void main(String[] args) {
SpringApplication.run(MySpringTestApplication.class, args);
}
}
5、模拟监控controller
HelloController
@RestController
@ApiLog
public class HelloController {
@GetMapping("/hello")
public Map<String,Object> getHello(@RequestBody Map hashmap){
HashMap map = new HashMap();
map.put("key","hello!");
map.put("aaa", null);
return map;
}
}