目录

一:java Web项目中的日志系统

二:日志系统的分类

三:springboot整合slf4j

1.添加mavne支持

2.配置xml以及制定yml

3.代码测试

4.日志记录

四:使用Aop的方法记录日志,并且异步方法执行日记记录

1.定义一个异步线程池

2.在日志的插入上生成为异步方法

3.环绕通知封装日志对象

4.说明


一:java Web项目中的日志系统

定位到问题的发生点、发生时间、发生原因等。在互联网项目生产环境中,有很多异常或者错误是不可复现但是极其严重的。同时一些用户日志可以帮助我们分析用户习惯兴趣等。因此,一个合理的日志框架的设计尤为重要的,(以下包括以后内容都是个人扯扯,有问题希望能提出)。

  在一个系统中,日志一般分为2中类型:系统日志和操作日志。其中各种分类以及用途如下:

  系统日志:用来记录系统行为用来快速定位问题等。

      系统行为:用来记录系统运行的链路日志。

      异常日志:异常发生定位。

     错误日志:错误发生定位。

操作日志:用来记录用户的行为,以便分析用户的行为、兴趣等(在互联网项目中尤为重要)。

说了这么多了,我们直接来个思维导图的便于理解一下吧。



 

二:日志系统的分类

   在java中我们或多或少的遇到了许多了日志框架:log4j,log4j2,slf4j等等。

  一般日志框架简单的分为2类:

  日志门面:commons-logging,slf4j

  日志实现:log4j,log4j2,logback

  毋庸置疑,一旦在项目中引入多个日志框架一定会引起冲突的,实际上在解决日志系统的冲突上使用了一种解决手段:日志系统桥接器。日志系统桥接器使用了日志门面,强行劫持 其他日志框架到门面框架的实现上。 

三:springboot整合slf4j

                                                         

JAVA 熟悉业务代码日报怎么写 java系统业务日志设计_spring

1.添加mavne支持

<!-- 日志工具类 -->
		<dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
           
        </dependency>

2.配置xml以及制定yml

<?xml version="1.0" encoding="UTF-8"?>
<configuration>

	<property name="log.path" value="./fangList_logs" />
	<property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />

	<!-- 控制台输出 -->
	<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
		<encoder>
			<pattern>${log.pattern}</pattern>
		</encoder>
	</appender>
	
	<!-- 系统日志输出 -->
	<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
	    <file>${log.path}/sys-info.log</file>
		<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
			<!-- 按天回滚 daily -->
			<fileNamePattern>${log.path}/sys-info.%d{yyyy-MM-dd}.log</fileNamePattern>
			<!-- 日志最大的历史 60天 -->
			<maxHistory>60</maxHistory>
		</rollingPolicy>
		<encoder>
			<pattern>${log.pattern}</pattern>
		</encoder>
		<filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>INFO</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
	</appender>
	
	<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
	    <file>${log.path}/sys-error.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${log.path}/sys-error.%d{yyyy-MM-dd}.log</fileNamePattern>
			<!-- 日志最大的历史 60天 -->
			<maxHistory>60</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>${log.pattern}</pattern>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERROR</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>
	
	<!-- 用户访问日志输出  -->
    <appender name="sys-user" class="ch.qos.logback.core.rolling.RollingFileAppender">
		<file>${log.path}/sys-user.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 按天回滚 daily -->
            <fileNamePattern>${log.path}/sys-user.%d{yyyy-MM-dd}.log</fileNamePattern>
            <!-- 日志最大的历史 60天 -->
            <maxHistory>60</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>${log.pattern}</pattern>
        </encoder>
    </appender>
	
	<!-- 显示形成的sql、使用的参数、结果集 -->
	
		<logger name="java.sql" level="debug" />
		<logger name="org.springframework.jdbc" level="debug" />
	

	<logger name="cn.com" level="info" />

	<root level="info">
		<appender-ref ref="console" />
	</root>
	
	<!--系统操作日志-->
    <root level="info">
        <appender-ref ref="file_info" />
        <appender-ref ref="file_error" />
    </root>
	
	<!--系统用户操作日志-->
    <logger name="sys-user" level="info">
        <appender-ref ref="sys-user"/>
    </logger>
</configuration>
logging:
  level:
    com.moudle.user.dao: debug
    org.springframework: WARN
    org.spring.springboot.dao: debug

3.代码测试

JAVA 熟悉业务代码日报怎么写 java系统业务日志设计_spring_02

4.日志记录

JAVA 熟悉业务代码日报怎么写 java系统业务日志设计_JAVA 熟悉业务代码日报怎么写_03

四:使用Aop的方法记录日志,并且异步方法执行日记记录

上面主要说明了将slf4j整合到springboot中,下面将Aop形式来处理日志。

1.定义一个异步线程池

package commons.utils.Thread;

import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

/**
 * springboot的异步线程池
 * @author Owner
 *
 */
@EnableAsync
@Configuration
class TaskPollConfig{
	 @Bean("taskExecutor")
     public Executor taskExecutor() {
         ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
         executor.setCorePoolSize(10);
         executor.setMaxPoolSize(20);
         executor.setQueueCapacity(200);
         executor.setKeepAliveSeconds(60);
         executor.setThreadNamePrefix("taskExecutor-");
         executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
         executor.setWaitForTasksToCompleteOnShutdown(true);
         executor.setAwaitTerminationSeconds(60);
         return executor;
     }
}

2.在日志的插入上生成为异步方法

    我这里日志插入有其他的一些未处理,这里适应插入用户来模拟的

                

JAVA 熟悉业务代码日报怎么写 java系统业务日志设计_java_04

3.环绕通知封装日志对象

package com.config.Aspect.log;

import java.lang.reflect.Method;
import java.util.Map;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import org.apache.catalina.servlet4preview.http.HttpServletRequest;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
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.aspectj.lang.reflect.MethodSignature;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import commons.json.JSON;
import commons.result.DataResult;
import lombok.extern.java.Log;
import lombok.extern.slf4j.Slf4j;

/**
 * 日志切面
 * ClassName: LogAscpect 
 * Function: 一句话描述功能. 
 * auth: monxz
 * date: 2019年9月18日 下午3:46:23 
 *
 *
 */
@Aspect
@Component
@Slf4j
public class LogAscpect {
  
	
	
	@Pointcut("execution(public * com.moudle.*.controller.*.*(..))")
	public void sysLog() {}
	
	@Around("sysLog()")
	public Object saveSysLog(ProceedingJoinPoint proceedingJoinPoint) {
		//从切面织入点处通过反射机制获取织入点处的方法
        MethodSignature signature = (MethodSignature) proceedingJoinPoint.getSignature();
        //获取切入点所在的方法
        Method method = signature.getMethod();

		
		 //获取请求的类名
		String className = proceedingJoinPoint.getTarget().getClass().getName();
		//获取请求的方法名
        String methodName = method.getName();        
        //请求的参数
        Object[] args = proceedingJoinPoint.getArgs();
        
        
      //获取用户名
        //获取用户ip地址
        // 接收到请求,记录请求内容
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = (HttpServletRequest) attributes.getRequest();

		
        // 记录下请求内容
        log.info("URL : " + request.getRequestURL().toString());
        log.info("HTTP_METHOD : " + request.getMethod());
        log.info("IP : " + request.getRemoteAddr());

        /**
         * 
         * TODO:将上述的参数封装成日志对象,并且日志插入
         * 
         */
        
        
      //开始调用时间
        // 计时并调用目标函数
        long start = System.currentTimeMillis();
        Long time = System.currentTimeMillis() - start;
        
        Object result ;
        try {
			result= proceedingJoinPoint.proceed();
			return result;
		} catch (Throwable e) {
			e.printStackTrace();	
			return  new DataResult().buildFail("系统异常");
		}
		
	}


	
}

4.说明

  在这里我们将日志插入进行异步插入,不会影响到主程序的运行。