SparkJava在Android API26以下运行异常,求解决方案
这个问题的核心很明确:你用的SparkJava 2.3.0依赖的Jetty 9.4.4版本,引入了Android API26才支持的ThreadLocal.withInitial(Supplier)方法,而API24(Android7)并没有这个方法,所以触发了NoSuchMethodError。下面给你几个可行的解决思路:
1. 手动替换Jetty为兼容API24的旧版本
Jetty 9.3.x是最后一个不强制依赖Java 8特性的分支,完全兼容Android API24及以上。你需要先排除SparkJava自带的Jetty依赖,再手动引入Jetty 9.3.x的核心组件。
以Gradle为例,修改你的依赖配置:
dependencies { // 引入SparkCore,排除所有Jetty相关依赖 implementation('com.sparkjava:spark-core:2.3.0') { exclude group: 'org.eclipse.jetty' exclude group: 'org.eclipse.jetty.websocket' } // 手动添加兼容API24的Jetty 9.3.x稳定版 implementation 'org.eclipse.jetty:jetty-server:9.3.29.v20190903' implementation 'org.eclipse.jetty:jetty-servlet:9.3.29.v20190903' implementation 'org.eclipse.jetty:jetty-webapp:9.3.29.v20190903' implementation 'org.eclipse.jetty.websocket:websocket-server:9.3.29.v20190903' implementation 'org.eclipse.jetty.websocket:websocket-servlet:9.3.29.v20190903' }
如果是Maven项目,用<exclusions>标签排除Jetty依赖,再单独引入9.3.x的依赖即可。
2. 降级SparkJava到依赖Jetty 9.3.x的版本
SparkJava 2.1.x及更早的版本,默认依赖的就是Jetty 9.3.x,不需要手动替换依赖。比如SparkJava 2.1.0依赖的Jetty版本是9.3.11.v20160721,这个版本完全兼容API24。
你可以直接修改依赖版本:
implementation 'com.sparkjava:spark-core:2.1.0'
不过要注意,旧版本的SparkJava可能缺少一些你需要的新特性,所以先确认这个版本的功能是否能满足你的代理需求。
3. 换用Android原生兼容的轻量HTTP服务器
如果上述两种方法都有麻烦,或者你只是需要一个简单的代理功能,可以考虑用专门为Android设计的轻量服务器,比如NanoHTTPD。它体积小,没有多余依赖,兼容几乎所有Android版本,API也很简单,能快速实现代理逻辑。
比如添加依赖:
implementation 'org.nanohttpd:nanohttpd:2.3.1'
然后基于它编写代理逻辑,比折腾Spark+Jetty的兼容性要省心很多。
验证步骤
修改依赖后,先clean项目再重新构建,然后在Android7(API24)设备上测试:
- 检查是否还出现
NoSuchMethodError - 验证代理的核心功能是否正常运行
内容的提问来源于stack exchange,提问作者Greg Rynkowski

