往期精彩推荐html
SpringBoot系列(一)idea新建Springboot项目java
springBoot系列(三)配置文件详解spring
SpringBoot系列(五)Mybatis整合完整详细版springboot
SpringBoot系列(六)集成thymeleaf详解版app
Springboot系列(七) 集成接口文档swagger,使用,测试框架
SpringBoot系列(八)分分钟学会Springboot多种解决跨域方式ide
SpringBoot系列(九)单,多文件上传的正确姿式spring-boot
SpringBoot系列(十)优雅的处理统一异常处理与统一结果返回
SpringBoot系列(十一)拦截器与拦截器链的配置与使用详解,你知道多少?
本文目录
在咱们运行项目的时候,你会发现控制台是有日志打印的,这个日志就是SpringBoot默认配置的日志框架处理的。SpringBoot默认是运用logback+slf4j处理日志,slf4j是抽象层,logback是实现层。
可是不一样的框架可能会有不一样日志处理方式,若是咱们在SpringBoot中集成了不一样的框架的话,是否是日志的输出也会混乱呢?很显然,若是你有一点经验的话,你会发现,只要你不修改SpringBoot的默认日志配置,它的日志输出格式是不会变得。这是由于,在SpringBoot管理日志的时候,它都将其余框架的日志经过一些中间包的形式将其余的日志抽象成了slf4j接口,而统一用logback的形式实现。
本文咱们来说讲怎么来配置日志格式以及运用AOP+自定义注解简化日志的记录。
SpringBoot中默认的日志输出级别是info,也就是说咱们日常在控制台输出的那些日志都是info级别以及更高级别的日志。咱们能够本身定义日志的输出级别,通常有如下几个级别:
trace,debug,info,warn,error //级别递增
trace 是追踪日志,debug是调式日志,info通常是自定义日志或者是信息日志,warn是警告日志,error则是错误日志。
可能这么说你也不知道这个级别有什么用,来看看这个代码:
@RestController public class TestLogController { Logger logger = LoggerFactory.getLogger(TestLogController.class); @GetMapping("/testLog") public void testLog(){ logger.trace("这是trace级别的日志"); logger.debug("这是debug级别的日志"); logger.info("这是正常自定义日志"); logger.warn("这是警告日志"); logger.error("这是错误日志"); } }
代码说明:(上面的Logger包这里是使用的org.slf4j.Logger)
首先咱们获取一个日志记录器Logger对象,而后分别在代码中记录不一样级别日志的输出。运行项目,而后访问接口。
你会发现前面的trace日志和debug日志是不会输出的,这你就知道了吧,不一样等级的日志有不一样的功效,只会在特定的状况下输出。这时候咱们也能够自定义日志级别了,在配置文件(yml)
logging: level: com: example: demolog: debug
配置说明:
这是什么意思呢?个人包名是com.example.demolog,因此说这个配置就是说配置日志所在包的输出级别,是否是很高级。这样就能输出debug日志了。若是你想输出trace日志你就将等级设置为trace就好了。
日志输出到控制台查看起来不是很方便,怎么办?不要紧,SpringBoot中还能将日志输出到指定的文件中,yml,添加以下配置。
logging: file: path: /spring/test/
这个配置是说将日志输出到指定的目录文件,而且会生成一个spring.log的日志文件用来记录日志(若是你本身指定了文件名,它就会按照你本身设定的名字生成文件。),运行项目你就能直接看到生成的日志所在,这个目录若是你写的和上面一致,那么你的日志文件就会在项目的运行根路径,好比D盘,而后在D盘生成你写的文件目录/spring/test/,最后在文件目录下面生成spring.log的日志文件。这个路径你也能够直接写绝对路径(直接指定这个文件在那个盘,那个文件夹)。
file下面还有一个配置就是name属性,
logging: file: name: test.log
这个是直接指定你的日志的文件名称,默认生成的位置是在项目所在的目录,你也能够本身写绝对路径配置日志文件的位置,可是必须要本身设定文件的名称。
file的name属性和path属性只能指定一个,若是两个同时指定的话,只有name属性会生效。
有时候你可能会以为这个日志的输出格式太难看了,想本身定义一个日志输出格式,彻底ojbk!SpringBoot说:知足你,本身想怎么玩就怎么玩!
logging: pattern: console: "%d{yyyy-MM-dd HH:mm:ss}----- 这是全栈学习笔记 [%thread] %-5level %logger{50} - %msg%n" file: "%d{yyyy-MM-dd HH:mm:ss}----- 这是全栈学习笔记 [%thread] %-5level %logger{50} - %msg%n" # d表示日期时间, # %thread表示线程名, # %‐5level:级别从左显示5个字符宽度 # %logger{50} 表示logger名字最长50个字符,不然按照句点分割。 # %msg:日志消息, # %n是换行符
上面的配置分别定义了控制台的日志输出格式与文件的日志输出格式,是否是很方便。输出的格式大概就是这样。
固然咱们还有一个更好的日志配置,利用xml文件进行配置,一步到位就是这么爽。
直接上xml文件的内容,建议将文件命名为logback-spring.xml
<?xml version="1.0" encoding="UTF-8"?> <!-- scan:当此属性设置为true时,配置文件若是发生改变,将会被从新加载,默认值为true。 scanPeriod:设置监测配置文件是否有修改的时间间隔,若是没有给出时间单位,默认单位是毫秒当scan为true时,此属性生效。默认的时间间隔为1分钟。 debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。 --> <configuration scan="false" scanPeriod="60 seconds" debug="false"> <!-- 定义日志的根目录 建议写绝对路径 若是不写默认在项目运行的根路径( D盘,C盘这种)--> <property name="LOG_HOME" value="D:/app/log" /> <!-- 定义日志文件名称 --> <property name="appName" value="testxml"></property> <!-- ch.qos.logback.core.ConsoleAppender 表示控制台输出 --> <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender"> <!-- 日志输出格式: %d表示日期时间, %thread表示线程名, %-5level:级别从左显示5个字符宽度 %logger{50} 表示logger名字最长50个字符,不然按照句点分割。 %msg:日志消息, %n是换行符 --> <layout class="ch.qos.logback.classic.PatternLayout"> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} --学习笔记--[%thread] %-5level %logger{50} - %msg%n</pattern> <!-- <springProfile name="dev">--> <!-- <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} == 学习笔记 == [%thread] -–> %-5level %logger{50} - %msg%n</pattern>--> <!-- </springProfile>--> <!-- <springProfile name="prod">--> <!-- <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} ==学习笔记==[%thread] %-5level %logger{50} - %msg%n</pattern>--> <!-- </springProfile>--> <!-- 若是将这个文件的名字改为logback-spring.xml 就可使用上面的功能, 上面的功能是说能够根据不一样的生产环境作不一样的日志打印 --> </layout> </appender> <!-- 滚动记录文件,先将日志记录到指定文件,当符合某个条件时,将日志记录到其余文件 --> <appender name="appLogAppender" class="ch.qos.logback.core.rolling.RollingFileAppender"> <!-- 指定日志文件的名称 --> <file>${LOG_HOME}/${appName}.log</file> <!-- 当发生滚动时,决定 RollingFileAppender 的行为,涉及文件移动和重命名 TimeBasedRollingPolicy: 最经常使用的滚动策略,它根据时间来制定滚动策略,既负责滚动也负责出发滚动。 --> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!-- 滚动时产生的文件的存放位置及文件名称 %d{yyyy-MM-dd}:按天进行日志滚动 %i:当文件大小超过maxFileSize时,按照i进行文件滚动 --> <fileNamePattern>${LOG_HOME}/${appName}-%d{yyyy-MM-dd}-%i.log</fileNamePattern> <!-- 可选节点,控制保留的归档文件的最大数量,超出数量就删除旧文件。假设设置天天滚动, 且maxHistory是365,则只保存最近365天的文件,删除以前的旧文件。注意,删除旧文件是, 那些为了归档而建立的目录也会被删除。 --> <MaxHistory>365</MaxHistory> <!-- 当日志文件超过maxFileSize指定的大小是,根据上面提到的%i进行日志文件滚动 注意此处配置SizeBasedTriggeringPolicy是没法实现按文件大小进行滚动的,必须配置timeBasedFileNamingAndTriggeringPolicy --> <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> <maxFileSize>100MB</maxFileSize> </timeBasedFileNamingAndTriggeringPolicy> </rollingPolicy> <!-- 日志输出格式: --> <layout class="ch.qos.logback.classic.PatternLayout"> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [ %thread ] - [ %-5level ] [ %logger{50} : %line ] - %msg%n</pattern> </layout> </appender> <!-- logger主要用于存放日志对象,也能够定义日志类型、级别 name:表示匹配的logger类型前缀,也就是包的前半部分 level:要记录的日志级别,包括 TRACE < DEBUG < INFO < WARN < ERROR additivity:做用在于children-logger是否使用 rootLogger配置的appender进行输出, false:表示只用当前logger的appender-ref,true: 表示当前logger的appender-ref和rootLogger的appender-ref都有效 --> <!-- hibernate logger --> <logger name="com.example.demolog" level="debug" ></logger> <!-- Spring framework logger --> <logger name="org.springframework" level="debug" additivity="false"></logger> <!-- root与logger是父子关系,没有特别定义则默认为root,任何一个类只会和一个logger对应, 要么是定义的logger,要么是root,判断的关键在于找到这个logger,而后判断这个logger的appender和level。 --> <root level="info"> <appender-ref ref="stdout" /> <appender-ref ref="appLogAppender" /> </root> </configuration>
上面的xml配置文件配置就不细说了,里面都有详细的注释说明。配置文件默认位置应该是直接放在resources下面,和yml,properties文件同级,固然你也能够本身配置文件位置的。
logging config: classpath:static/logback.xml
这样就将xml配置文件放在static路径下面时能自动识别了。也能够设置为绝对路径。
上面咱们建议将日志文件设置为logback-spring.xml,若是咱们的xml文件的名称是logback.xml,它就会直接被日志框架识别,若是你的xml文件是用logback-spring.xml命名,那么他会被SpringBoot来识别并解析日志配置,可使用SpringBoot的高级Profile功能。这个高级功能我在xml文件中有注释说明。往上看。你也能够去看Spring的官网,有详细的配置说明。
引入aop依赖:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency>
自定义注解,还不会注解的,看这里,注解详细介绍注解干货
@Documented @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface MyLog { String value() default ""; }
自定义切面类:
@Aspect @Component public class LogAspect { private Logger logger = LoggerFactory.getLogger(LogAspect.class); @Pointcut("@annotation(com.example.demolog.annotation.MyLog)") public void myPointCut(){ //签名,能够理解成这个切入点的一个名称 } @Before("myPointCut()") public void doBefore(JoinPoint joinPoint){ ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest request = attributes.getRequest(); //获取url,请求方法,ip地址,类名以及方法名,参数 logger.info("url={},method={},ip={},class_method={},args={}", request.getRequestURI(),request.getMethod(),request.getRemoteAddr(),joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName(),joinPoint.getArgs()); } @AfterReturning(pointcut = "myPointCut()") public void printLog(JoinPoint joinPoint){ MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); Method method = methodSignature.getMethod(); MyLog myLog = method.getAnnotation(MyLog.class); String value = null; if (myLog!=null){ value = myLog.value(); } logger.info(new Date()+"-----"+value); } }
上面配置完成以后再去controller的方法之上添加一个自定义的 @Mylog注解
@GetMapping("/testLog") @MyLog("测试一个日志") public void testLog(){ //和上面的一致 }
代码说明:
@Aspect:标明这是一个切面类
@Component:标明这是一个bean
@Pointcut("@annotation(com.example.demolog.annotation.MyLog)") 定义切入点为自定义的注解,也能够是一个类或者是一个包,包的写法以下:
@Pointcut("execution(public * com.example.demolog.*(..))")
上面的意思是切入点是 全部在com.example,demolog包下面的以public为修饰,不限制返回值(*),不限制参数不限制名称的类。
扩展知识:
而后咱们再来测试一下接口:localhost:8098/testLog
本期分享到此结束,总结一下下!
本文先讲解SpringBoot的默认日志配置,而后本身在配置文件配置日志的输出等级,输出格式,将日志输出到文件中,而后经过xml文件来配置日志。最后咱们引出了利用aop,简化日志的输出,而且统一日志的输出格式。若是你以为本文有用的话,点个赞吧!另外须要源码的看下面。