Springboot的日志管理&Springboot整合Junit測試&Springboot中AOP的使用


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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM