概述
在web项目中记录每个接口的访问信息做审计是很重要的,下面介绍使用log4j2+拦截器将日志记录到日志文件的一种方式。
1、编写记录日志实体类AccessLog
package com.iscas.biz.model.common.access;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.Date;
/**
* 访问日志的实体
*
* @author zhuquanwen
* @vesion 1.0
* @date 2021/8/29 20:37
* @since jdk1.8
*/
@Data
@Accessors(chain = true)
public class AccessLog {
/**访问用户*/
private String username = "unknown";
/**uri*/
private String uri;
/**访问时长*/
private Long duration;
/**请求方式*/
private String method;
/**客户端IP*/
private String ip;
/**状态码*/
private int status;
/**时间*/
private Date createTime;
}
2、编写拦截器
这里在preHandle中构建基础AccessLog的属性和请求时间并将它们绑定到request中,在postHandle中从request中取出AccessLog并设置访问耗时、访问用户等属性,注意:这里的访问用户的获取方式是我项目中的方式,根据实际情况要做修改。
设置完所有AccessLog的属性后,使用log.debug输出日志。
package com.iscas.biz.config.log;
import com.iscas.base.biz.model.auth.AuthContext;
import com.iscas.base.biz.util.AuthContextHolder;
import com.iscas.base.biz.util.SpringUtils;
import com.iscas.biz.model.common.access.AccessLog;
import lombok.extern.slf4j.Slf4j;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;
/**
* 访问/审计日志
* @author zhuquanwen
* @vesion 1.0
* @date 2021/8/29 20:42
* @since jdk1.8
*/
@Slf4j
public class AccessLogInterceptor implements HandlerInterceptor {
/**访问开始时间*/
private static final String KEY_REQUEST_START_TIME = "KEY_REQUEST_START_TIME";
/**访问开始时间*/
private static final String KEY_ACCESS_LOG = "KEY_ACCESS_LOG";
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
AccessLog accessLog = new AccessLog();
accessLog.setIp(SpringUtils.getIpAddr())
.setMethod(request.getMethod())
.setUri(request.getRequestURI());
//将信息绑定在request中
request.setAttribute(KEY_REQUEST_START_TIME, System.currentTimeMillis());
request.setAttribute(KEY_ACCESS_LOG, accessLog);
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
@Nullable ModelAndView modelAndView) throws Exception {
AccessLog accessLog = (AccessLog) request.getAttribute(KEY_ACCESS_LOG);
Long startTime = (Long) request.getAttribute(KEY_REQUEST_START_TIME);
if (accessLog != null) {
Date createTime = new Date();
AuthContext context = AuthContextHolder.getContext();
accessLog.setCreateTime(createTime)
.setDuration(createTime.getTime() - startTime)
.setStatus(response.getStatus())
.setUsername(context == null ? null : context.getUsername());
log.debug(accessLog.toString());
}
}
}
3、注册拦截器
package com.iscas.biz.config;
import com.iscas.biz.config.log.AccessLogInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
*
* @author zhuquanwen
* @vesion 1.0
* @date 2021/8/29 21:02
* @since jdk1.8
*/
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 添加拦截器,配置拦截地址
registry.addInterceptor(new AccessLogInterceptor())
.addPathPatterns("/**");
// .excludePathPatterns("/login","/userLogin")
// .excludePathPatterns("/image/**");
}
}
4、配置log4j2对审计日志的支持
log4j2的配置方式见上一篇文章介绍:https://blog.csdn.net/u011943534/article/details/119876319
在上一篇的配置基础上,添加审计日志的RollingFile,日志级别为debug
<!--访问日志-->
<RollingFile name="accessAppender"
fileName="${FILE_PATH}/${FILE_NAME}/log_access.log"
filePattern="${FILE_PATH}/${FILE_NAME}/access/log-access-%d{yyyy-MM-dd}_%i.log.gz"
append="true">
<!--设置日志格式-->
<PatternLayout pattern="${ACCESS_LOG_PATTERN}" charset="UTF-8"/>
<Filters>
<ThresholdFilter level="debug" onMatch="ACCEPT" onMismatch="DENY"/>
</Filters>
<Policies>
<!-- 基于时间的触发策略。该策略主要是完成周期性的log文件封存工作。有两个参数:
interval,integer型,指定两次封存动作之间的时间间隔。单位:以日志的命名精度来确定单位,
比如yyyy-MM-dd-HH 单位为小时,yyyy-MM-dd-HH-mm 单位为分钟
modulate,boolean型,说明是否对封存时间进行调制。若modulate=true,
则封存时间将以0点为边界进行偏移计算。比如,modulate=true,interval=4hours,
那么假设上次封存日志的时间为00:00,则下次封存日志的时间为04:00,
之后的封存时间依次为08:00,12:00,16:00-->
<TimeBasedTriggeringPolicy interval="1"/>
<SizeBasedTriggeringPolicy size="10MB"/>
</Policies>
<!-- DefaultRolloverStrategy 属性如不设置,则默认为最多同一文件夹下当天 7 个文件后开始覆盖-->
<DefaultRolloverStrategy max="30">
<!-- 删除处理策略,在配置的路径中搜索,maxDepth 表示往下搜索的最大深度 -->
<Delete basePath="${FILE_PATH}/${FILE_NAME}/" maxDepth="2">
<!-- 文件名搜索匹配,支持正则 -->
<IfFileName glob="*.log.gz"/>
<!--!Note: 这里的 age 必须和 filePattern 协调, 后者是精确到 dd, 这里就要写成 xd, xD 就不起作用
另外, 数字最好 >2, 否则可能造成删除的时候, 最近的文件还处于被占用状态,导致删除不成功!-->
<!--7天-->
<IfLastModified age="7d"/>
</Delete>
</DefaultRolloverStrategy>
</RollingFile>
ACCESS_LOG_PATTERN的格式如下:
<!--变量配置-->
<properties>
<!-- 格式化输出:%date 表示日期,%thread 表示线程名,%-5level:级别从左显示 5 个字符宽度 %msg:日志消息,%n 是换行符-->
<!-- %logger{36} 表示 Logger 名字最长 36 个字符 -->
<property name="LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level [%logger{50}:%L] - %msg%n"/>
<property name="LOG_CONSOLE_PATTERN" value="%style{%d{ISO8601}}{bright,green} %highlight{%-5level} [%style{%t}{bright,blue}] %style{%C{}}{bright,yellow}: %msg%n%style{%throwable}{red}"/>
<property name="ACCESS_LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} - %msg%n"/>
<!-- 定义日志存储的路径 -->
<property name="FILE_PATH" value="logs"/>
<property name="FILE_NAME" value="newframe"/>
</properties>
将拦截器类单独配置一个Logger:
<AsyncLogger name="com.iscas.biz.config.log.AccessLogInterceptor" level="debug" includeLocation="true" additivity="false">
<AppenderRef ref="accessAppender"/>
<AppenderRef ref="consoleAppender"/>
</AsyncLogger>
大功告成,看下我生成的access_log.log文件:
2021-08-29 21:11:36.822 - AccessLog(username=null, uri=/demo/ttt, duration=7, method=GET, ip=0:0:0:0:0:0:0:1, status=404, createTime=Sun Aug 29 21:11:36 CST 2021)
2021-08-29 21:11:39.639 - AccessLog(username=null, uri=/demo/404, duration=23, method=GET, ip=0:0:0:0:0:0:0:1, status=404, createTime=Sun Aug 29 21:11:39 CST 2021)
最后
以上就是风趣水池为你收集整理的springboot学习(五十四) springboot中记录审计/访问日志的全部内容,希望文章能够帮你解决springboot学习(五十四) springboot中记录审计/访问日志所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复