如何为REST API项目创建带依赖Jar包?打包运行报CXF错误如何解决?
问题根因
你遇到的启动报错和业务代码逻辑无关,核心是Maven Assembly打全量Fat Jar时,*SPI(服务发现机制)*的配置文件被覆盖丢失:
- 开发环境直接在控制台运行代码时,所有CXF依赖JAR独立加载,每个JAR包内
META-INF/services路径下的SPI配置文件可被Java ServiceLoader正常扫描识别,自动将HTTP传输对应的HttpDestinationFactory注册到CXF全局Bus上,因此服务可正常启动。 - 使用Maven Assembly构建包含全部依赖的Jar包时,默认打包规则会将所有依赖包内的文件解压后统一归档到最终Jar包;遇到相同路径的SPI配置文件时,会直接用后加载的文件覆盖先加载的内容,最终导致CXF HTTP传输组件的注册配置丢失,抛出“找不到已注册HttpDestinationFactory”的异常。
- 你尝试删除
setAddress传入值里的http前缀后程序不报错的现象,是因为去掉协议头后,CXF会将该地址识别为本地直连的非网络监听地址,不会触发HTTP传输组件的初始化逻辑;但此时程序根本没有启动端口监听,自然无法通过HTTP访问REST接口。
需补充的必要配置
- 调整maven-assembly-plugin的打包策略,新增对
META-INF/services目录的文件合并规则,避免SPI配置被覆盖。在assembly的打包描述符中增加如下合并配置,确保所有依赖的服务声明文件内容被整合到同一最终文件中:<containerDescriptorHandlers> <containerDescriptorHandler> <handlerImplementation> org.apache.maven.plugins.shade.resource.ServicesResourceTransformer </handlerImplementation> </containerDescriptorHandler> </containerDescriptorHandlers> - 若不调整打包配置,可在业务启动代码中手动注册HTTP传输组件,绕过SPI自动加载失效的问题。在初始化
JAXRSServerFactoryBean的逻辑中补充以下代码:// 获取CXF全局默认Bus Bus bus = BusFactory.getDefaultBus(); // 手动将HTTP传输工厂注册到Bus扩展点 bus.setExtension(new HTTPTransportFactory(), HttpDestinationFactory.class); // 将注册完成的Bus绑定到服务工厂 sf.setBus(bus); - 检查项目依赖完整性,确认已引入CXF内置Jetty HTTP监听模块
cxf-rt-transports-http-jetty。如果只引入了JAXRS API相关依赖、缺失该传输层组件,哪怕SPI配置正常,也会因为没有实际的HTTP服务实现类抛出相同报错。
内容的提问来源于stack exchange,提问作者John Smith
相关产品推荐
相关产品推荐

