Jersey 2:ApplicationEventListener被忽略如何排查?包扫描为何失效?
嘿,针对你遇到的Jersey 2问题,我分两部分来解答——先教你怎么开调试日志排查扫描问题,再解释为什么包扫描参数没生效但直接指定类名管用:
要搞清楚你的ExceptionLogger为什么没被扫描到,最直接的办法就是打开Jersey的调试日志,看它到底扫了哪些类。这里分几种常见情况:
1. 用日志配置文件(推荐)
如果你用的是Logback,在logback.xml里添加这两个日志器:
<logger name="org.glassfish.jersey" level="DEBUG"/> <logger name="org.glassfish.jersey.server.scanning" level="TRACE"/>
其中org.glassfish.jersey.server.scanning的TRACE级别会输出超详细的扫描日志,包括每个被扫描的包、检测到的类,甚至会告诉你哪些类因为没有合适的注解被跳过,一眼就能看到你的ExceptionLogger有没有被纳入扫描范围。
如果是Log4j2,在log4j2.xml里加同样逻辑的配置:
<Logger name="org.glassfish.jersey" level="DEBUG"/> <Logger name="org.glassfish.jersey.server.scanning" level="TRACE"/>
2. 临时通过web.xml开启追踪(应急用)
如果不想改日志配置,也可以在Jersey的Servlet初始化参数里加这两行,直接输出调试信息到控制台:
<init-param> <param-name>jersey.config.server.tracing.type</param-name> <param-value>ALL</param-value> </init-param> <init-param> <param-name>jersey.config.server.tracing.threshold</param-name> <param-value>TRACE</param-value> </init-param>
注意这个会输出大量请求和组件加载的细节,生产环境千万别开,用来排查问题就好。
provider.packages扫不到,但provider.classnames能生效? 结合Jersey的组件注册逻辑,大概率是这几个原因之一:
你的
ExceptionLogger没加@Provider注解
Jersey的包扫描只会自动注册带有@Provider(用于扩展组件,比如监听器、过滤器)或@Path(用于资源类)的类。如果你的ExceptionLogger没加@Provider,包扫描会直接忽略它。而用provider.classnames指定类名时,Jersey会直接尝试注册这个类,不管有没有注解(不过规范上还是建议加上@Provider,符合JAX-RS标准)。类加载器或扫描范围的问题
如果你的项目和Spring等其他框架整合,可能Spring的组件扫描接管了Jersey的扫描逻辑,或者类加载器的层级导致Jersey扫不到你的包。直接指定类名绕开了扫描环节,直接告诉Jersey要加载哪个类,所以能生效。包路径拼写错误
虽然你说类在com.mypackage.rest下,但仔细检查下web.xml里的jersey.config.server.provider.packages参数值是不是完全匹配?有没有大小写错误、少打了字母?比如写成com.mypackage.res就会直接漏掉你的类。Jersey版本的扫描逻辑差异
不同版本的Jersey在包扫描上可能有细微差别,比如某些版本对嵌套包的扫描规则不同,或者对非标准注解的识别有变化。直接指定类名是最直接的注册方式,不受这些扫描逻辑的影响。
内容的提问来源于stack exchange,提问作者Daniel Kaplan

