原文: http://zetcode.com/articles/javaservletlog4j/

Java servlet Log4j 教程显示了如何在 Java servlet 中使用 Log4j 进行日志记录。 本教程介绍 Log4j 版本 2。

Java Servlet

Servlet 是 Java 类,可响应特定类型的网络请求-最常见的是 HTTP 请求。 Java servlet 用于创建 Web 应用。 它们在 servlet 容器(例如 Tomcat 或 Jetty)中运行。 现代 Java Web 开发使用在 servlet 之上构建的框架。

Log4j

Apache Log4j 是基于 Java 的日志记录工具。 它是 Apache Software Foundation 的项目。 可以通过 Java 代码或在配置文件中配置 Log4j。 配置文件可以 XML,JSON,YAML 或属性文件格式编写。

Log4j 具有三个主要组件:记录器,附加器和布局。 记录器被命名为目标,可捕获捕获日志消息并将其发送到附加程序。 附加器将日志消息传递到其目的地,例如文件或控制台。 布局用于定义日志消息的格式。

Java servlet 日志记录示例

以下 Web 应用正在使用 Log4j 进行日志记录。 在 Servlet 3.0+应用中,Log4j 可以直接使用。 它在应用部署时自动启动,在应用取消部署时自动关闭。

  1. $ tree
  2. .
  3. ├── pom.xml
  4. └── src
  5. └── main
  6. ├── java
  7. └── com
  8. └── zetcode
  9. ├── service
  10. └── MyService.java
  11. └── web
  12. └── MyServlet.java
  13. ├── resources
  14. └── log4j2.xml
  15. └── webapp
  16. ├── index.html
  17. ├── META-INF
  18. └── context.xml
  19. └── WEB-INF

这是项目结构。 Log4j 配置文件位于src/main/resources/目录中。

pom.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
  5. http://maven.apache.org/xsd/maven-4.0.0.xsd">
  6. <modelVersion>4.0.0</modelVersion>
  7. <groupId>com.zetcode</groupId>
  8. <artifactId>JavaServletLog4j</artifactId>
  9. <version>1.0-SNAPSHOT</version>
  10. <packaging>war</packaging>
  11. <name>JavaServletLog4j</name>
  12. <properties>
  13. <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  14. <maven.compiler.source>1.8</maven.compiler.source>
  15. <maven.compiler.target>1.8</maven.compiler.target>
  16. </properties>
  17. <dependencies>
  18. <dependency>
  19. <groupId>javax.servlet</groupId>
  20. <artifactId>javax.servlet-api</artifactId>
  21. <version>3.1.0</version>
  22. <scope>provided</scope>
  23. </dependency>
  24. <dependency>
  25. <groupId>org.apache.logging.log4j</groupId>
  26. <artifactId>log4j-web</artifactId>
  27. <version>2.8.2</version>
  28. </dependency>
  29. </dependencies>
  30. <build>
  31. <plugins>
  32. <plugin>
  33. <groupId>org.apache.maven.plugins</groupId>
  34. <artifactId>maven-war-plugin</artifactId>
  35. <version>2.3</version>
  36. <configuration>
  37. <failOnMissingWebXml>false</failOnMissingWebXml>
  38. </configuration>
  39. </plugin>
  40. </plugins>
  41. </build>
  42. </project>

这是 Maven POM 文件。 我们有两个工件:用于服务器小程序的javax.servlet-api和用于 Web 应用中 Log4j 记录的log4j-webmaven-war-plugin负责收集 Web 应用的所有工件依赖项,类和资源,并将它们打包到 Web 应用存档(WAR)中。

context.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <Context path="/JavaServletLog4j"/>

在 Tomcat context.xml文件中,我们定义了上下文路径。 它是 Web 应用的名称。

log4j2.xml

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <Configuration status="info">
  3. <Properties>
  4. <Property name="logdir">/home/janbodnar/tmp</Property>
  5. <Property name="layout">%d [%t] %-5p %c- %m%n</Property>
  6. </Properties>
  7. <Appenders>
  8. <RollingFile name="LOCALHOST"
  9. fileName="${logdir}/localhost.log"
  10. filePattern="${logdir}/localhost.%d{yyyy-MM-dd}-%i.log">
  11. <PatternLayout pattern="${layout}"/>
  12. <Policies>
  13. <TimeBasedTriggeringPolicy />
  14. <SizeBasedTriggeringPolicy size="1 MB" />
  15. </Policies>
  16. <DefaultRolloverStrategy max="10" />
  17. </RollingFile>
  18. </Appenders>
  19. <Loggers>
  20. <Logger name="com.zetcode"
  21. level="info" additivity="false">
  22. <AppenderRef ref="LOCALHOST" />
  23. </Logger>
  24. <Root level="error">
  25. </Root>
  26. </Loggers>
  27. </Configuration>

log4j2.xml中配置 Log4j。 在我们的示例中,我们选择了 XML 文件格式。

  1. <Properties>
  2. <Property name="logdir">/home/janbodnar/tmp</Property>
  3. <Property name="layout">%d [%t] %-5p %c - %m%n</Property>
  4. </Properties>

Properties标记中,我们设置了日志目录和布局。 布局定义了日志的格式。

模式布局由转换说明符组成。 每个说明符均以百分号开头,后跟可选的格式修饰符和强制转换字符。 %d输出记录事件的日期。 %t输出生成日志事件的线程的名称。 %-5p输出记录事件的级别,级别名称中至少要包含五个字符,并且这些字符必须对齐。 %c输出发布了记录事件的记录器的名称。 %m打印与日志记录事件关联的应用消息,%n是平台相关的行分隔符或多个字符。

  1. <Appenders>
  2. ...
  3. </Appenders>

附加项是定义日志消息保存位置的对象。 有几个可能的目的地,包括控制台,文件,数据库表或原型。

  1. <RollingFile name="LOCALHOST"
  2. fileName="${logdir}/localhost.log"
  3. filePattern="${logdir}/localhost.%d{yyyy-MM-dd}-%i.log">
  4. <PatternLayout pattern="${layout}" />
  5. ...
  6. <DefaultRolloverStrategy max="10" />
  7. </RollingFile>

我们设置日志文件的位置。 我们使用滚动文件附加器,该附加器会自动滚动或归档当前日志文件,并继续记录新文件。 PatternLayout设置日志消息的布局。 如果存档数量达到十个,则DefaultRolloverStrategy会删除较旧的存档。

  1. <Policies>
  2. <TimeBasedTriggeringPolicy />
  3. <SizeBasedTriggeringPolicy size="1 MB" />
  4. </Policies>

触发策略在Policies标记中定义。 它们控制发生翻转的条件。 在这里,我们使用两个策略:TimeBasedTriggeringPolicySizeBasedTriggeringPolicyTimeBasedTriggeringPolicy根据最具体的日期和时间模式开始翻转; 就我们而言,如果每小时日志文件的大小达到 1MB,则SizeBasedTriggeringPolicy开始翻转。

  1. <Loggers>
  2. <Logger name="com.zetcode"
  3. level="info" additivity="false">
  4. <AppenderRef ref="LOCALHOST" />
  5. </Logger>
  6. <Root level="error">
  7. </Root>
  8. </Loggers>

Loggers标签中,我们定义了记录器。 它们被称为日志消息目的地。 每个记录器可以配置不同级别的记录。 我们定义一个具有信息记录级别的记录器。 我们将先前定义的滚动文件附加器附加到此记录器。 在additivity设置为false的情况下,日志消息不会传播到其祖先。

MyServlet.java

  1. package com.zetcode.web;
  2. import com.zetcode.service.MyService;
  3. import java.io.IOException;
  4. import java.io.PrintWriter;
  5. import javax.servlet.ServletException;
  6. import javax.servlet.annotation.WebServlet;
  7. import javax.servlet.http.HttpServlet;
  8. import javax.servlet.http.HttpServletRequest;
  9. import javax.servlet.http.HttpServletResponse;
  10. import org.apache.logging.log4j.LogManager;
  11. import org.apache.logging.log4j.Logger;
  12. @WebServlet(name = "MyServlet", urlPatterns = {"/MyServlet"})
  13. public class MyServlet extends HttpServlet {
  14. final static Logger logger = LogManager.getLogger(MyService.class);
  15. @Override
  16. protected void doGet(HttpServletRequest request, HttpServletResponse response)
  17. throws ServletException, IOException {
  18. logger.info("MyServlet's doGet() called");
  19. MyService service = new MyService();
  20. service.doWork();
  21. response.setContentType("text/plain;charset=UTF-8");
  22. PrintWriter out = response.getWriter();
  23. out.print("MyServlet called");
  24. }
  25. }

这是MyServlet servlet。 它调用服务方法并将文本数据发送回客户端。

  1. final static Logger logger = LogManager.getLogger(MyService.class);

我们从LogManager获取记录器。

  1. logger.info("MyServlet's doGet() called");

我们记录一条信息级别的消息。

  1. MyService service = new MyService();
  2. service.doWork();

我们称为虚拟服务方法。

  1. PrintWriter out = response.getWriter();
  2. out.print("MyServlet called");

我们将文本数据发送给客户端。

MyService.java

  1. package com.zetcode.service;
  2. import org.apache.logging.log4j.LogManager;
  3. import org.apache.logging.log4j.Logger;
  4. public class MyService {
  5. final static Logger logger = LogManager.getLogger(MyService.class);
  6. public void doWork() {
  7. logger.info("MyService's doWork() called");
  8. }
  9. }

MyServicedoWork()方法记录信息级别的消息。

index.html

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <title>Home Page</title>
  5. <meta charset="UTF-8">
  6. </head>
  7. <body>
  8. <a href="MyServlet">Call Servlet</a>
  9. </body>
  10. </html>

主页包含一个调用MyServlet的链接。

  1. $ cat localhost.log
  2. 2017-11-14 16:50:30,157 [http-nio-8084-exec-5] INFO com.zetcode.service.MyService- MyServlet's doGet() called
  3. 2017-11-14 16:50:31,044 [http-nio-8084-exec-5] INFO com.zetcode.service.MyService- MyService's doWork() called

这是已记录消息的示例输出。

在本教程中,我们已经在 Java Web 应用中使用 Log4j 完成了一些日志记录。

您可能也对以下相关教程感兴趣: Java Log4j 教程Java Servlet RESTful 客户端Java Servlet 上传文件Java RequestDispatcher从 Java servlet 提供纯文本Java servlet 复选框教程Java servlet 图像教程Java Servlet HTTP 标头Java 教程