Jetty 11中如何通过编程方式调整日志配置
Jetty 11 编程式调整日志实现方案
版本差异根因
- Jetty 9的
org.eclipse.jetty.util.log.Log采用延迟绑定机制:首次调用日志方法时才会加载、实例化日志实现,因此启动前调用setLog()注入自定义实现可以正常生效。 - Jetty 10/11重构了日志加载逻辑:日志实现的绑定被移到
Log类的静态初始化块中,JVM加载Log类的瞬间就会完成内置日志实例的初始化,后续调用被标记为废弃的setLog()不会修改已经绑定的静态实例,这也是该方法体直接标注// does nothing的核心原因,官方没有在方法注释上给出替代指引属于文档遗漏。
官方支持的编程式配置方式
适用于嵌入式Jetty(绝大多数编程式启动场景),核心逻辑是抢在Log类被JVM加载前,通过系统属性指定自定义日志实现类:
- 第一步:自定义日志类实现
org.eclipse.jetty.util.log.Logger接口,提供无参公共构造方法。 - 第二步:在程序入口的最前置位置(所有Jetty相关类被加载前)设置系统属性,再执行后续Jetty初始化逻辑:
public class Main { public static void main(String[] args) throws Exception { // !!!这行必须放在最前面,不能有任何Jetty相关的代码、对象初始化在它之前执行 System.setProperty("org.eclipse.jetty.util.log.class", "com.your.custom.YourCustomLogger"); // 属性设置完成后,再引入Jetty类、初始化Server Server server = new Server(8080); // 后续业务逻辑 server.start(); server.join(); } }
注意:如果代码中提前触发了
org.eclipse.jetty.util.log.Log类的加载(比如提前写了Jetty类的静态引用、提前调用了Jetty相关方法),静态初始化块会先执行完成,此时再设置系统属性不会生效。
特殊场景备选方案
如果受代码加载顺序限制,无法在Log类加载前完成属性设置,可以通过反射直接修改Log类的静态日志实例,该方式不被官方推荐,Jetty小版本升级如果修改了内部字段名可能失效:
import org.eclipse.jetty.util.log.Log; import java.lang.reflect.Field; public class LogConfigUtil { public static void setCustomLog(Log customLog) throws Exception { Field logField = Log.class.getDeclaredField("LOG"); logField.setAccessible(true); logField.set(null, customLog); } }
内容的提问来源于stack exchange,提问作者tipsy
相关产品推荐
相关产品推荐

