Spring Boot 入门(五):集成 AOP 进行日志管理
本篇文章是接著 Spring boot 入門(mén)(四):集成 Shiro 實(shí)現(xiàn)登陸認(rèn)證和權(quán)限管理寫(xiě)的,按照前面幾篇博客的教程,可以搭建一個(gè)簡(jiǎn)單的項(xiàng)目,主要包含了 Pagehelper+MyBatis 分頁(yè)查詢,Generator 代碼自動(dòng)生成器,Shiro登錄及權(quán)限管理。本篇博客主要是集成 AOP 進(jìn)行日志管理
1.導(dǎo)入 jar 包
<!-- aop --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency> 復(fù)制代碼2.配置 Logback-spring 文件
關(guān)于 Logback-spring 的配置網(wǎng)上很多,隨便copy一份基本上就能使用,Logback-spring.xml 中主要配置了下列內(nèi)容
- (1).日志寫(xiě)道控制臺(tái)
- (2).日志寫(xiě)道本地文件中
- (3).日志級(jí)別
- (4).日志生成方式(按照日期滾動(dòng)生成,還是按照日期單獨(dú)生成)
- (5).日志來(lái)源的配置,一般直接配置到 Control
我也是直接在copy了一份,代碼如下
<?xml version="1.0" encoding="UTF-8"?> <configuration scan="true" scanPeriod="60 seconds" debug="false"><contextName>logback</contextName> <!--<!– 文件輸出格式 –><property name="PATTERN" value="%-12(%d{yyyy-MM-dd HH:mm:ss.SSS}) |-%-5level [%thread] %c [%L] -| %msg%n" /><!– test文件路徑 –><property name="TEST_FILE_PATH" value="c:/log" />--><!--輸出到控制臺(tái)--><appender name="console" class="ch.qos.logback.core.ConsoleAppender"><encoder><pattern>%d{HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern></encoder></appender><!--按天生成日志--><appender name="logFile" class="ch.qos.logback.core.rolling.RollingFileAppender"><Prudent>true</Prudent><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><FileNamePattern>applog/%d{yyyy-MM-dd}/%d{yyyy-MM-dd}.log</FileNamePattern></rollingPolicy><layout class="ch.qos.logback.classic.PatternLayout"><Pattern>%d{yyyy-MM-dd HH:mm:ss} -%msg%n</Pattern></layout></appender><logger name="com.tswc.edu" additivity="false"><appender-ref ref="console"/><appender-ref ref="logFile" /></logger><root level="error"><appender-ref ref="console"/><appender-ref ref="logFile" /></root></configuration>復(fù)制代碼這里用戶也可以配置多個(gè)級(jí)別使用于多個(gè)環(huán)境,對(duì)每個(gè)日志級(jí)別進(jìn)行配置不同的屬性,然后在 Application.xml 中選擇不同的級(jí)別環(huán)境。在實(shí)際項(xiàng)目開(kāi)發(fā)的過(guò)程中,一般配置2個(gè)環(huán)境,開(kāi)發(fā)環(huán)境,生產(chǎn)環(huán)境。在開(kāi)發(fā)環(huán)境中,只需要配置日志輸出到控制臺(tái),便于開(kāi)發(fā)人員調(diào)試。生成環(huán)境相反,需要配置日志輸出到文件,控制臺(tái)盡量不要輸出日志,這樣可以減少控制臺(tái)對(duì)虛擬機(jī)內(nèi)存的消耗,一旦產(chǎn)生 Bug ,用戶查詢?nèi)罩疚募纯?/p>
上述代碼中即配置了日志輸出到控制臺(tái),也配置了日志輸出到日志文件
3.配置日志級(jí)別
只需要在 Application.xml 中配置即可:
日志級(jí)別分為5個(gè)等級(jí),debug<info<warn<Error<Fatal,其中常用的級(jí)別為:debug和info- debug 級(jí)別最低,可以隨意的使用于任何覺(jué)得有利于在調(diào)試時(shí)更詳細(xì)的了解系統(tǒng)運(yùn)行狀態(tài)的東東;
- info 重要,輸出信息:用來(lái)反饋系統(tǒng)的當(dāng)前狀態(tài)給最終用戶的; 后三個(gè),警告、錯(cuò)誤、嚴(yán)重錯(cuò)誤,這三者應(yīng)該都在系統(tǒng)運(yùn)行時(shí)檢測(cè)到了一個(gè)不正常的狀態(tài)。
- warn, 可修復(fù),系統(tǒng)可繼續(xù)運(yùn)行下去;
- Error, 可修復(fù)性,但無(wú)法確定系統(tǒng)會(huì)正常的工作下去;
- Fatal, 相當(dāng)嚴(yán)重,可以肯定這種錯(cuò)誤已經(jīng)無(wú)法修復(fù),并且如果系統(tǒng)繼續(xù)運(yùn)行下去的話后果嚴(yán)重。
4.編寫(xiě)日志類
@Aspect @Component public class WebLogAspect {private static final Logger logger = LoggerFactory.getLogger(WebLogAspect.class);@Pointcut("execution( * com.tswc.edu.controller.*.*(..))")//兩個(gè)..代表所有子目錄,最后括號(hào)里的兩個(gè)..代表所有參數(shù)public void logPointCut() {}//切點(diǎn)@Pointcut("@annotation(com.tswc.edu.annotation.Log)")public void logPointCutLog() {}@Before("logPointCut()")public void doBefore(JoinPoint joinPoint) throws Throwable {// 接收到請(qǐng)求,記錄請(qǐng)求內(nèi)容ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();HttpServletRequest request = attributes.getRequest();// 記錄下請(qǐng)求內(nèi)容logger.info("請(qǐng)求地址 : " + request.getRequestURL().toString());//logger.info("方法描述 : " + );logger.info("HTTP METHOD : " + request.getMethod());// 獲取真實(shí)的ip地址//logger.info("IP : " + IPAddressUtil.getClientIpAddress(request));logger.info("CLASS_METHOD : " + joinPoint.getSignature().getDeclaringTypeName() + "."+ joinPoint.getSignature().getName());logger.info("參數(shù) : " + Arrays.toString(joinPoint.getArgs())); // loggger.info("參數(shù) : " + joinPoint.getArgs());}@AfterReturning(returning = "ret", pointcut = "logPointCut()")// returning的值和doAfterReturning的參數(shù)名一致public void doAfterReturning(Object ret) throws Throwable {// 處理完請(qǐng)求,返回內(nèi)容(返回值太復(fù)雜時(shí),打印的是物理存儲(chǔ)空間的地址)logger.debug("返回值 : " + ret);}@Around("logPointCut()")public Object doAround(ProceedingJoinPoint pjp) throws Throwable {long startTime = System.currentTimeMillis();Object ob = pjp.proceed();// ob 為方法的返回值logger.info("耗時(shí) : " + (System.currentTimeMillis() - startTime));return ob;}@Around("logPointCutLog()")public Object around(ProceedingJoinPoint point) throws Throwable {// 執(zhí)行方法Object result = point.proceed();// 獲得注解Log controllerLog = getAnnotationLog(point);if (controllerLog == null) {return null;}String action = controllerLog.value();logger.info("請(qǐng)求目的:"+action);return result;}/*** 是否存在注解,如果存在就獲取*/private static Log getAnnotationLog(JoinPoint joinPoint) throws Exception {Signature signature = joinPoint.getSignature();MethodSignature methodSignature = (MethodSignature) signature;Method method = methodSignature.getMethod();if (method != null) {//System.out.println("123:"+method.getAnnotation(Log.class).value());return method.getAnnotation(Log.class);}//System.out.println("1234:"+method.getAnnotation(Log.class).value());return null;} } 復(fù)制代碼這是個(gè)通用類,主要約定控制臺(tái)或者日志文件中日志的格式,關(guān)于此公共類,網(wǎng)上有大量的講解,這里就不詳細(xì)說(shuō)明了。
再次啟動(dòng)項(xiàng)目,控制臺(tái)將輸出日志,并將日志寫(xiě)入到文件中:
5.新增加部分
其中自定義日志文件可以不要,這里用戶自己定義了日志輸出的說(shuō)明部分 自定義了 @Log 注記的識(shí)別,并配置一些文件說(shuō)明,那么在請(qǐng)求到這個(gè)類的時(shí)候,日志中將輸出文章描述部分自定義配置文件的代碼:
- Log
- LogAspect
其中LogAspect中也可以寫(xiě)一些對(duì)日志進(jìn)行 CRUD 的業(yè)務(wù)邏輯操作,大多數(shù)情況下,此處可以將日志的保存邏輯寫(xiě)入到此類中。
6.問(wèn)題
本項(xiàng)目在啟動(dòng)的時(shí)候,報(bào)了一個(gè)關(guān)于日志的警告,沒(méi)有找到解決方案
項(xiàng)目中并沒(méi)有用到log4j,不知道為什么會(huì)警告,項(xiàng)目中缺少log4j的配置文件,如果有大神知道原因,歡迎留言
總結(jié)
以上是生活随笔為你收集整理的Spring Boot 入门(五):集成 AOP 进行日志管理的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 软考自查:数据库设计
- 下一篇: Spring Boot -Shiro配置