Adults times have changed, not in the manual method to add a comment to each of the (Springboot integrate log4j logging system, and achieve the realization by aop monitor service execution time through the log)

1.SpringBoot integrate log4j logging system

We all know that programmers knock code is very cool, they put their minds to fill the gap ideas into code line by line to knock them out, but! ! ! Every time looking BUG really painful, then the log records in the program is necessary, and today I'm going to teach you how to integrate log4j logging system in SpringBoot.

1. First comes the SpringBoot log system removed
<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
2. Add Log dependent frame
<dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.21</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.21</version>
        </dependency>
3. Add log4j.properties
#把指定级别以上的日志信息输出到指定的一个或者多个位置
log4j.rootLogger=DEBUG,stdout,file
#表示Logger会在父Logger的appender里输出,默认为true
log4j.additivity.org.apache=true
#表示日志在控制台上输出 (1)org.apache.log4j.ConsoleAppender(控制台)
#(2)org.apache.log4j.FileAppender(文件)
#(3)org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件)
#(4)org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件)
#(5)org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方)
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
#日志级别是INFO级别的,除了DEBUG以外都会输出
log4j.appender.stdout.threshold=INFO
# 日志的输出格式:(1)org.apache.log4j.HTMLLayout(以HTML表格形式布局)
#(2)org.apache.log4j.PatternLayout(可以灵活地指定布局模式)
#(3)org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串)
#(4)org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等等信息)
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
# 日志的具体输出格式:格式化符号说明:
#
#%p:输出日志信息的优先级,即DEBUG,INFO,WARN,ERROR,FATAL。
#%d:输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,如:%d{yyyy/MM/dd HH:mm:ss,SSS}。
#%r:输出自应用程序启动到输出该log信息耗费的毫秒数。
#%t:输出产生该日志事件的线程名。
#%l:输出日志事件的发生位置,相当于%c.%M(%F:%L)的组合,包括类全名、方法、文件名以及在代码中的行数。例如:test.TestLog4j.main(TestLog4j.java:10)。
#%c:输出日志信息所属的类目,通常就是所在类的全名。
#%M:输出产生日志信息的方法名。
#%F:输出日志消息产生时所在的文件名称。
#%L::输出代码中的行号。
#%m::输出代码中指定的具体日志信息。
#%n:输出一个回车换行符,Windows平台为"rn",Unix平台为"n"。
#%x:输出和当前线程相关联的NDC(嵌套诊断环境),尤其用到像java servlets这样的多客户多线程的应用中。
#%%:输出一个"%"字符。
log4j.appender.stdout.layout.ConversionPattern=%-5p %c{1}:%L - %m%n

log4j.appender.file=org.apache.log4j.DailyRollingFileAppender
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.DatePattern='.'yyyy-MM-dd-HH-mm
log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
log4j.appender.file.Threshold=INFO
log4j.appender.file.append=true
log4j.appender.file.File=/workspaces/logs/foodie-api/imooc.log

2. To achieve monitor service execution time achieved by the log aop

What is 1.aop

Spring Framework AOP is thought aspect-oriented programming, using AOP called "cross" technique, the multi-functional business processes involve general extraction and individually packaged to form a separate section, at the right time these facets transverse cut to business processes specified location.
For example, in a business system, user login is the basis of function, all related to the user's business processes require users to log in the system. If the user login function code written to each business process, will result in code redundancy, maintenance is very troublesome, when the need to modify the user login function, you need to modify each user login code business processes, this approach clearly undesirable. Good practice is to extracted user login feature, to form an independent module, when the service user login process, the system automatically cut into the log function business processes.

2. Use Aop in the project, add aop dependency
<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
3. Create a class section

To put a cut into class categories, two steps,
① using @Component annotation on the aspect class category is added to the vessel IOC
② @Aspect annotation used in making the aspect class class

4.AOP support notification

1, pre-notification @Before: Advice to be executed before a join point, unless it throws an exception, otherwise the notice can not stop the flow of execution before the connection point.
2, after advice @AfterReturning: notification is executed after a connection point, the method is typically performed when a match is returned (can be bound after advice return value)
3, rear abnormality notification @AfterThrowing: in the process thrown notification performed when abnormal exit.
4, the rear final notification @After: a notification when the point of attachment to withdraw (whether normal or exceptional return).
5, around advice @Around: enclosing a connection point of the notification, and the like as a method call. This is the most powerful kind of advice. Around advice can perform custom behavior before and after the method call, it will choose whether to continue with the connection point or directly back to its own return value or throwing an exception execution.

5. pointcut expression

When the need for a defined entry point include the name and signature of any argument, there is an entry point expression, such as the execution (public * com.example.aop ... (... ))
format pointcut expression: execution ([Visibility ] return type [declared type] method name (parameter) [exception]).
where [] is the optional, additional supports the use of wildcards:

  1. *: Matches all characters
  2. ...: typically used to match a plurality of packets, a plurality of parameters
  3. +: Represents a class and its subclasses
    4) operators are: &&, || ,!
6. listening service implemented by the code execution time is achieved by log aop
package com.test.aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class ServiceLogAspect {
    final static Logger log = LoggerFactory.getLogger(ServiceLogAspect.class);

    /**
     * AOP通知:
     * 1. 前置通知:在方法调用之前执行
     * 2. 后置通知:在方法正常调用之后执行
     * 3. 环绕通知:在方法调用之前和之后,都分别可以执行的通知
     * 4. 异常通知:如果在方法调用过程中发生异常,则通知
     * 5. 最终通知:在方法调用之后执行
     */

    /**
     * 切面表达式:
     * execution 代表所要执行的表达式主体
     * 第一处 * 代表方法返回类型 *代表所有类型
     * 第二处 包名代表aop监控的类所在的包
     * 第三处 .. 代表该包以及其子包下的所有类方法
     * 第四处 * 代表类名,*代表所有类
     * 第五处 *(..) *代表类中的方法名,(..)表示方法中的任何参数
     *
     * @param joinPoint
     * @return
     * @throws Throwable
     */


    @Around("execution(* com.imooc.service.impl..*.*(..))")
    public Object recordTimeLog(ProceedingJoinPoint joinPoint) throws Throwable {
        log.info("====== 开始执行 {}.{} ======",
                joinPoint.getTarget().getClass(),
                joinPoint.getSignature().getName());

        // 记录开始时间
        long begin = System.currentTimeMillis();

        // 执行目标 service
        Object result = joinPoint.proceed();

        // 记录结束时间
        long end = System.currentTimeMillis();
        long takeTime = end - begin;

        if (takeTime > 3000) {
            log.error("====== 执行结束,耗时:{} 毫秒 ======", takeTime);
        } else if (takeTime > 2000) {
            log.warn("====== 执行结束,耗时:{} 毫秒 ======", takeTime);
        } else {
            log.info("====== 执行结束,耗时:{} 毫秒 ======", takeTime);
        }

        return result;
    }
}

Published 27 original articles · won praise 5 · Views 505

Guess you like

Origin blog.csdn.net/qq_38446413/article/details/105141382