You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现Java Servlet访问日志文件存储且满足条目及存储时效限制

Servlet 原生环境请求日志落地文件实现方案

优先推荐使用成熟日志框架实现,天然处理并发写、性能、日志滚动等边界问题,无需自行实现IO相关逻辑。

第一步:引入日志框架依赖

以行业常用的Logback为例,如果你使用Maven构建项目,在pom.xml中添加如下依赖:

<dependencies>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>2.0.7</version>
    </dependency>
    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
        <version>1.4.8</version>
    </dependency>
    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-core</artifactId>
        <version>1.4.8</version>
    </dependency>
</dependencies>

如果不使用构建工具,直接将上述三个Jar包放入项目的WEB-INF/lib目录即可。

第二步:配置日志滚动规则

在项目resources目录下创建logback.xml配置文件,直接满足你要求的30天保留、最多1万条日志、自动覆盖旧日志的规则:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <!-- 保留原有控制台打印(可选) -->
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss} %-5level - %msg%n</pattern>
        </encoder>
    </appender>

    <!-- 访问日志文件输出配置 -->
    <appender name="REQUEST_LOG" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${catalina.base}/logs/request.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <FileNamePattern>${catalina.base}/logs/request.%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <!-- 日志最长保留30天 -->
            <maxHistory>30</maxHistory>
            <!-- 按单条日志平均1KB计算,单文件存1000条日志设为1MB,可根据实际日志长度调整 -->
            <maxFileSize>1MB</maxFileSize>
            <!-- 总日志大小上限设为10MB,对应约10000条日志,满了自动删除最旧的日志 -->
            <totalSizeCap>10MB</totalSizeCap>
            <cleanHistoryOnStart>true</cleanHistoryOnStart>
        </rollingPolicy>
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss} | %msg%n</pattern>
        </encoder>
    </appender>

    <logger name="替换为你自己Filter的全类名" level="info" additivity="false">
        <appender-ref ref="REQUEST_LOG"/>
        <appender-ref ref="CONSOLE"/>
    </logger>

    <root level="info">
        <appender-ref ref="CONSOLE"/>
    </root>
</configuration>

如果需要精确控制条目数,可以根据你实际单条日志的平均大小调整totalSizeCap的数值即可。

第三步:改造现有Filter

将原来打印到控制台的逻辑替换为使用Logger打印,日志框架会自动处理写入文件和滚动逻辑:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

public class RequestLogFilter implements Filter {
    private static final Logger logger = LoggerFactory.getLogger(RequestLogFilter.class);

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        long startTime = System.currentTimeMillis();
        chain.doFilter(request, response);
        long cost = System.currentTimeMillis() - startTime;
        // 可自行扩展拼接请求参数、UA、响应状态码等信息
        String logContent = String.format("%s | %s | %s | %dms",
                req.getRemoteAddr(), req.getMethod(), req.getRequestURI(), cost);
        logger.info(logContent);
    }
}

如果你需要记录请求体内容,需要自行实现HttpServletRequestWrapper缓存请求输入流,避免流被读取一次后后续Servlet无法获取。

无第三方依赖手动实现方案

如果不想引入日志框架,可以按以下逻辑自行实现:

  • 定义容量为10000的FIFO阻塞队列,队列满时自动弹出队首最旧的日志条目
  • 启动单独的守护线程异步将队列中的日志写入文件,避免阻塞请求线程
  • 每次写入时统计条目数,同时每天定时扫描日志目录,删除生成时间超过30天的日志文件
  • 处理并发写的文件锁问题,避免多请求同时写文件出现内容错乱

内容的提问来源于stack exchange,提问作者juan manuel rodriguez

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 13:06:06