如何为拆分EJB、Web和EAR模块的Maven项目添加日志工具
我通常会推荐用SLF4J作为日志门面(它能让业务代码和具体日志实现解耦,后续换日志框架不用改业务代码),搭配Logback作为日志实现——这是目前Java生态里轻量又好用的组合,下面一步步给你说怎么配置到你的三模块项目里:
1. 统一依赖版本(用父POM管理更省心)
如果你的三个模块有父POM的话,先在父POM的dependencyManagement里统一锁定SLF4J和Logback的版本,避免不同模块依赖版本不一致导致冲突:
<dependencyManagement> <dependencies> <!-- SLF4J 日志门面 --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.36</version> <!-- 可替换为最新稳定版 --> </dependency> <!-- Logback 核心实现 --> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-core</artifactId> <version>1.2.11</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.2.11</version> </dependency> </dependencies> </dependencyManagement>
2. EJB模块配置
EJB作为业务逻辑层,肯定需要日志能力,在EJB模块的pom.xml里添加依赖:
<dependencies> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-core</artifactId> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> </dependency> </dependencies>
然后在EJB模块的src/main/resources下创建logback.xml配置文件,示例配置(同时输出到控制台和本地文件):
<configuration> <!-- 控制台输出 --> <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern> </encoder> </appender> <!-- 文件滚动输出 --> <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>${user.home}/logs/ejb-service.log</file> <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> <fileNamePattern>${user.home}/logs/ejb-service.%d{yyyy-MM-dd}.%i.log</fileNamePattern> <maxFileSize>10MB</maxFileSize> <maxHistory>30</maxHistory> <totalSizeCap>1GB</totalSizeCap> </rollingPolicy> <encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern> </encoder> </appender> <!-- 全局日志级别 --> <root level="INFO"> <appender-ref ref="CONSOLE"/> <appender-ref ref="FILE"/> </root> <!-- 单独给业务包设置调试级别 --> <logger name="com.yourpackage.ejb" level="DEBUG"/> </configuration>
在EJB类里使用日志:
import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.ejb.Stateless; @Stateless public class YourEJBService { private static final Logger logger = LoggerFactory.getLogger(YourEJBService.class); public void doBusiness() { logger.debug("执行业务方法前的调试信息"); logger.info("开始执行业务操作:doBusiness"); try { // 业务逻辑代码 } catch (Exception e) { logger.error("业务操作执行失败", e); } } }
3. Web模块配置
Web模块的配置和EJB类似,先在pom.xml里添加依赖:
<dependencies> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-core</artifactId> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> </dependency> </dependencies>
在Servlet或Web控制器里使用日志:
import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @WebServlet("/hello") public class HelloServlet extends HttpServlet { private static final Logger logger = LoggerFactory.getLogger(HelloServlet.class); @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { logger.info("收到请求:{},请求IP:{}", req.getRequestURI(), req.getRemoteAddr()); resp.getWriter().write("Hello World"); } }
Web模块的日志配置可以复用EJB的logback.xml,也可以单独创建自己的配置文件,放在src/main/resources下即可。
4. EAR模块配置
EAR模块只负责打包整个项目,不需要添加任何日志依赖——因为EJB和Web模块已经包含了所需的依赖,Maven在打包EAR时会自动把这些依赖打包到对应模块中(比如Web模块的依赖会在WAR的WEB-INF/lib下,EJB模块的依赖在JAR包内)。
如果是部署到JBoss、WebLogic这类Java EE应用服务器,需要注意:部分服务器自带日志框架,可能会和Logback冲突。这时候可以在服务器的部署配置文件(比如JBoss的jboss-deployment-structure.xml)中配置日志类加载隔离,避免冲突。
一些额外注意事项
- 永远不要用
System.out.println输出日志,日志框架能帮你灵活控制日志级别、输出位置,还能自动记录线程、时间等关键信息。 - 生产环境记得把日志级别调到
INFO或WARN,避免过多调试日志影响性能。 - 日志里不要输出敏感信息,比如用户密码、银行卡号等。
内容的提问来源于stack exchange,提问作者Joe

