Play Framework2.5.19抛出NoSuchMethodError无日志无响应如何解决
问题原因
Play Framework 2.5.x 版本默认的请求处理链路只会捕获 Exception 类型的异常,你抛出的 NoSuchMethodError 属于 Error 类型(是 Throwable 的直接子类,不属于Exception体系),会直接穿透默认的异常捕获逻辑,不会走到你自定义的onServerError方法中,最终导致请求线程异常终止,既没有日志输出也不会返回响应。
解决方案
通过全局过滤器(Filter)捕获所有请求链路中抛出的Throwable类型对象,可同时实现全量错误日志记录和500响应返回:
- 编写全局异常捕获过滤器
import play.mvc.*; import play.libs.streams.Accumulator; import akka.util.ByteString; import java.util.concurrent.CompletionException; import org.apache.logging.log4j.LogManager; public class GlobalErrorFilter extends Filter { @Override public Accumulator<ByteString, Result> apply(Function<Http.RequestHeader, Accumulator<ByteString, Result>> next, Http.RequestHeader requestHeader) { try { Accumulator<ByteString, Result> resultAccumulator = next.apply(requestHeader); // 捕获异步处理阶段抛出的异常 return resultAccumulator.recover(throwable -> { Throwable realException = throwable; // 解开异步包装的CompletionException拿到原始异常 if (throwable instanceof CompletionException && throwable.getCause() != null) { realException = throwable.getCause(); } LogManager.getLogger().error("请求处理发生未捕获错误", realException); return Results.internalServerError("服务器内部错误"); }, play.libs.concurrent.HttpExecution.defaultContext()); } catch (Throwable t) { // 捕获请求路由阶段就抛出的同步异常 LogManager.getLogger().error("请求路由发生未捕获错误", t); return Accumulator.done(Results.internalServerError("服务器内部错误")); } } }
- 注册全局过滤器
在项目配置文件conf/application.conf中添加如下配置,替换为你自己的过滤器类全路径:
play.http.filters = "com.yourpackage.GlobalErrorFilter"
补充说明
NoSuchMethodError这类Error通常是编译期和运行期依赖版本不一致、依赖冲突导致的,建议排查项目依赖树确认相关类的版本匹配情况,从根源解决问题。
内容的提问来源于stack exchange,提问作者zelinka
相关产品推荐
相关产品推荐

