目录
一、项目中为什么要进行日志处理
- 程序出现错误时、快速定位位置
- sout/serr本身时IO操作,会影响系统性能,日志的打印级别可以控制。
Spring Boot 默认打印日志的级别是INFO级别。
优先级从高到低分别是ERROR、WARN、INFO、DEBUG
二、日志需要记录的内容
- 请求URL
- 服务IP
- 调用方法
- 请求参数
- 返回内容
- 等
三、使用
在关键结点打印日志难免会疏漏且不易管理,故本次使用的时springboot AOP来创建日志切面;在前端和服务器之间创建个切面、对拦截到的流进行处理。
3.1 项目引入aop切面的依赖
<!--AOP--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency>
web依赖包中自带了spring-boot-starter-logging依赖,所以若导入了web包,可以不用单独添加logging依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
3.2
@Aspect @Component public class LogAspect { /** * 日志记录器 */ private final Logger logger =LoggerFactory.getLogger(this.getClass()); /** * 这个切面会横切com.example.demo包下控制器的请求 */ @Pointcut("execution(* com.example.demo..*.*(..))") public void aspect(){ } /** * doBefore()在切面前执行 */ @Before("aspect()") public void doBefore(JoinPoint joinPoint) { logger.info("-------------doBefore------------"); ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest request = attributes.getRequest(); String url = request.getRequestURL().toString(); String ip = request.getRemoteAddr(); String classMethod = joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName(); Object[] args = joinPoint.getArgs(); RequestLog requestLog = new RequestLog(url, ip, classMethod, args); logger.info("Request : {}", requestLog); } /** * doAfter()在切面后执行 */ @After("aspect()") public void doAfter(){ logger.info("-------------doAfter------------"); } /** * 该方法返回 * @param result 返回的内容 */ @AfterReturning(returning = "result",pointcut = "aspect()") public void doAfterReturn(Object result){ logger.info("Result : {}",result); } /** * 日志对象 */ private class RequestLog { private String url; private String ip; private String classMethod; private Object[] args; public RequestLog(String url, String ip, String classMethod, Object[] args) { this.url = url; this.ip = ip; this.classMethod = classMethod; this.args = args; } @Override public String toString() { return "{" + "url='路径" + url + '\'' + ", ip='" + ip + '\'' + ", classMethod='" + classMethod + '\'' + ", args=" + Arrays.toString(args) + '}'; } } }
@Before:标识一个前置增强方法。
@After:final增强,不管是抛出异常或者正常退出都会执行。
@AfterReturning:后置增强,方法正常退出时执行。
@AfterThrowing:异常抛出增强,方法执行抛出异常后执行。@Aspect 该类是切面
@Component 注册组件、实现bean注入
@Pointcut("execution(* com.example.demo..*.*(..))")
声明该方法是一个切点
execution(),表达式的主体
第一个“*”符号,表示返回值类型任意;
"com.example.demo",AOP所切的服务的包名
包名后面的“.”,表示当前包及子包
第二个“*”,表示类名,*即所有类
.*(…),表示任何方法名,括号表示参数,两个点表示任何参数类型
测试接口
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@GetMapping("/{username}/{password}")
@ResponseBody
public String loginTest(@PathVariable String password, @PathVariable String username){
logger.info("----正在执行--loginTest------");
return username+password;
}
访问该接口查看日志
当修改日志打印级别高于info后再访问测试接口,对应日志则不会打印。一般是通过不同环境选择不同的配置文件。
logging: level: root: warn
以上便是本篇使用内容