技术派Filter实现请求日志记录
技术派实现了一个不那么明显的功能,将所有的外部访问都记录在日志文件中,为什么要设计这么个功能?
- 在不引入Prometheus进行接口监控时,基于日志文件就可以实现整个项目的监控
- 当出现问题时,可以基于此进行流量重放
实际部署到线上的表现效果如:

接下来我们看一下,这个请求日志的记录是怎么实现的
技术方案
如果单纯的将这个记录接口的请求信息,当作一个普通的需求来设计,我们可以怎么来实现呢?
- 基于过滤器Filter,来拦截web请求,记录请求相关信息
- 基于AOP来实现方法拦截,借助
@Around来实现请求方法执行前后增强,记录请求相关信息
那么两个方案如何选择呢?
Filter过滤器方案
关于过滤器的相关知识点,请参考教程:* WEB三大组件之Filter在技术派中的应用(已完成)
若使用过滤器,则主要就是拦截web请求了,具体的实现流程如

在过滤器的doFilter方法中,划分为三块:
- doBefore: 表示将请求转发到Controller执行之前
- 记录开始执行时间
- 记录请求相关信息
- doFilter: 即将请求转发到Controller去执行
- doAfter: Controller方法执行完
- 记录结束时间,计算执行耗时
- 日志输出
使用这种方式的优缺点比较突出,优点是适用性强,实现简单,缺点是只能记录Controller的请求相关信息,如果我们想统计某个Service方法、Mapper方法,那么这种方式则不太合适
AOP切面方案
若使用AOP来实现,则关键点在于我需要拦截哪些方法,即定义切点

基本策略与前面差不多,不过有几个关键点
- 定义切点:可以是直接拦截包路径方式,也可以配合自定义注解,拦截某些特定注解的方法
- 使用Around环绕方式
使用AOP来实现的优缺点也比较明显
优点:
- 灵活性非常高,可以拦截任何共有方法
缺点:
- 需要自定义切点,通常不太容易一次编写,所有项目适用
选型
技术派中,上面两个方案都会给出实现,所以不用担心二选一,毕竟我们的主旨是给大家提供一个完善的学习进阶项目,怎么可以遗漏知识点呢(😀)
这篇教程,主要介绍的是基于Filter来实现请求信息的记录;对于AOP的请期待下文
实现示例
实现类
在技术派中,核心实现类为:ReqRecordFilter
对应的包路径为:com.github.paicoding.forum.web.hook.filter.ReqRecordFilter
接下来我们看一下日志相关的核心实现(我会排除掉与日志无关的逻辑,所以会与实际的项目中代码不一致,不用因此产生疑问)
@Slf4j
@WebFilter(urlPatterns = "/*", filterName = "reqRecordFilter", asyncSupported = true)
public class ReqRecordFilter implements Filter {
private static Logger REQ_LOG = LoggerFactory.getLogger("req");
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
long start = System.currentTimeMillis();
HttpServletRequest request = null;
try {
// 构建请求上下文
request = this.initReqInfo((HttpServletRequest) servletRequest);
filterChain.doFilter(request, servletResponse);
} finally {
// 根据请求上下文,输出请求日志
buildRequestLog(ReqInfoContext.getReqInfo(), request, System.currentTimeMillis() - start);
ReqInfoContext.clear();
}
}
private HttpServletRequest initReqInfo(HttpServletRequest request) {
if (staticURI(request)) {
// 静态资源直接放行
return request;
}
try {
ReqInfoContext.ReqInfo reqInfo = new ReqInfoContext.ReqInfo();
reqInfo.setHost(request.getHeader("host"));
reqInfo.setPath(request.getPathInfo());
reqInfo.setReferer(request.getHeader("referer"));
reqInfo.setClientIp(IpUtil.getClientIp(request));
reqInfo.setUserAgent(request.getHeader("User-Agent"));
request = this.wrapperRequest(request, reqInfo);
...未能定位到原文的划线
企业级Agent工作流编排项目PaiFlow
Vibe Coding版本的PaiAgent
派聪明RAG AI知识库Java版本+Go版本
微服务 PmHub、技术派、MYDB
求职派JobClaw(OpenClaw/Hermes架构
PaiCLI(类似Claude Code的Agent
派简历(代码已完成)
等实战项目。
1. 微信扫右侧的优惠券加入知识星球
2. 解锁星球的实战项目教程和源码: 项目源码+教程获取
真诚点赞 诚不我欺
回复