==============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