==============Springboot的日志管理=============
springboot无需引入日志的包,springboot默认已经依赖了slf4j、logback、log4j等日志。我习惯用slf4j,下面就用slf4j做配置。
如果你导入了spring-boot-starter-web,这个会自动依赖上述日志。如下依赖:
0.日志测试类:
package daoTest; import org.junit.Test; import org.junit.runner.RunWith; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import cn.qlq.MySpringBootApplication; @RunWith(SpringRunner.class) @SpringBootTest(classes = MySpringBootApplication.class) public class PlainTest { private static final Logger logger = LoggerFactory.getLogger(PlainTest.class); @Test public void findAll() { logger.error("error , msg->{} ", "错误"); logger.info("info , msg->{} ", "信息"); } }
1.springboot默认的日志级别是debug
2.如果需要修改日志的相关配置可以修改applications.properties文件
############################################################
#
# 日志相关配置(默认集成的有slf4j,Logback等)
#
############################################################
#指定配置文件的位置,只能是xml或者groovy结尾
#logging.config=classpath:logback.xml
#默认的日志级别
logging.level.root=INFO
# mapper 接口所在的包设置为 debug
logging.level.cn.qlq.mapper=DEBUG
#生成日志文件的位置
logging.file=G:/springboot.log
#生成日志文件的目录,名称默认为spring.log
#logging.path=e:/
#指定日志的格式
#logging.pattern.console=%d{yyyy/MM/dd-HH:mm:ss} [%thread] %-5level %clr(%logger){cyan} %clr(%msg%n){green}
#logging.pattern.file=%d{yyyy/MM/dd-HH:mm} [%thread] %-5level %logger- %msg%n
解释:上面logging.level.root可以指定所以包默认的日志级别,logging.level.cn.qlq.mapper是对单独的子包设定日志级别,其级别可低于上面的root,也可以高于root
logging.file是指定文件日志的输出位置以及名称,logging.path是指定日志文件的位置,默认名称是spring.log(如果两者都配置以logging.file生效)
最后面是指定控制台和输出文件的日志格式。
logging.config是指定配置文件的位置,只能是xml或者groovy结尾。
关于日志级别等大致相同,参考:https://www.cnblogs.com/qlqwjy/p/9275415.html
==============Springboot整合Junit测试=============
Springboot中我们也可以像在普通的SSM环境中进行SpringJunit测试。
1.引入测试需要的模块
<!--springboot单元测试 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency>
2.建立测试目录,一般在src/test/java下面和src/test/resources目录下
mapper文件和配置文件要复制到src/test/resources目录下。
3.建立测试类进行测试
SpringBootTest的classes是springboot项目启动的运行类,也就是带有@SpringBootApplication的类。
package daoTest; import java.util.List; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import cn.qlq.MySpringBootApplication; import cn.qlq.bean.User; import cn.qlq.mapper.UserMapper; @RunWith(SpringRunner.class) @SpringBootTest(classes = MySpringBootApplication.class) public class PlainTest { @Autowired private UserMapper userMapper; @Test public void findAll() { List<User> findAll = userMapper.findAll(); System.out.println(findAll); } }
==============Springboot的AOP整合=============
springboot整合Aop非常简单,只用引入AOP模块的依赖即可。然后就可以使用注解AOP。
<!-- 引入 spring aop 依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency>
1.AOP的第一种切入方式:基于切点表达式进行拦截
如下记录servcice层的所有方法的执行时间的AOP写法
package cn.qlq.aspect; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; /** * 记录service层执行时间的AOP切面 * * @author QiaoLiQiang * @time 2019年2月21日下午9:20:15 */ @Aspect @Component public class LogServiceTakeTime { private final static Logger log = LoggerFactory.getLogger(LogServiceTakeTime.class); @Pointcut("execution(* cn.qlq.service..*.*(..))") public void performance() { } /** * 环绕通知记录时间 * * @param joinPoint * @return * @throws Throwable */ @Around("performance()") public Object doLog(ProceedingJoinPoint joinPoint) throws Throwable { // 记录起始时间 long begin = System.currentTimeMillis(); Object result = ""; /** 执行目标方法 */ try { result = joinPoint.proceed(); } catch (Exception e) { log.error("日志记录发生错误, errorMessage: {}", e.getMessage()); } finally { /** 记录操作时间 */ long took = (System.currentTimeMillis() - begin) / 1000; log.info("Service执行时间为: {}秒", took); } return result; } /** * 前置通知 * * @param joinPoint * @throws Throwable */ @Before("performance()") public void doBefore(JoinPoint joinPoint) throws Throwable { // 接收到请求,记录请求内容 log.info("doBefore"); } }
2.第二种切入方式:基于注解
(1)编写注解
package cn.qlq.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * 自定义注解 * * @author QiaoLiQiang * @time 2019年2月21日下午9:45:17 */ @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface MyLogAnnotation { String operateDescription();// 记录日志的操作类型,不写默认值就是一个必须填的注解 }
(2)编写切面进行拦截:一般在环绕通知中处理足够了
package cn.qlq.aspect; import java.lang.reflect.Method; import java.sql.SQLException; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.reflect.MethodSignature; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import cn.qlq.annotation.MyLogAnnotation; /** * @Author: qlq * @Description 日志记录切面(拦截自定义注解进行日志记录) * @Date: 11:46 2018/5/14 */ @Component @Aspect public class MyLogAspect { private final static Logger log = LoggerFactory.getLogger(MyLogAspect.class); /** * 环绕通知处理 * * @param pjp * @return * @throws Throwable */ @Around("@annotation(cn.qlq.annotation.MyLogAnnotation)") public Object aroundAdvice(ProceedingJoinPoint pjp) throws Throwable { // 1.方法执行前的处理,相当于前置通知 // 获取方法签名 MethodSignature methodSignature = (MethodSignature) pjp.getSignature(); // 获取方法 Method method = methodSignature.getMethod(); // 获取方法上面的注解 MyLogAnnotation logAnno = method.getAnnotation(MyLogAnnotation.class); // 获取到类名 String targetName = pjp.getTarget().getClass().getName(); // 获取到方法名字 String methodName = method.getName(); // 获取操作描述的属性值 String operateDescription = logAnno.operateDescription(); Object result = null; try { // 让代理方法执行 result = pjp.proceed(); // 2.相当于后置通知(方法成功执行之后走这里) } catch (SQLException e) { // 3.相当于异常通知部分 } finally { // 4.相当于最终通知 log.info("class->{},methodName->{},operateDescription->{}", targetName, methodName, operateDescription); } return result; } }
(3)测试:
结果:
关于AOP在之前也研究过了,在这里就只研究其使用,具体的使用方法参考:https://www.cnblogs.com/qlqwjy/p/8729280.html https://www.cnblogs.com/qlqwjy/p/8747476.html