使用 Java 16 时 Tomcat 找不到 Spring 初始值设定项类

问题描述

我有一个非常简单的 Gradle (7.0-rc-1) 脚本,用于使用嵌入式 Tomcat 实例初始化单个 Spring 5“hello world”端点。原始代码取自 random example I found on the internet。 我的示例 Gradle 项目可以在 here 中找到。

我不确定它是如何工作的,但不知何故网络服务器知道在启动时调用 WebApplicationInitializer.onStartup(ServletContext) 方法以便初始化 Spring。

这在 Java 8 上正常工作;但是当我将 Gradle 构建定义中的以下工具链规范更改为 Java 16 时失败。

java {
    toolchain {
//        languageVersion = JavaLanguageVersion.of(16)
        languageVersion = JavaLanguageVersion.of(8)
    }
}

使用 Java 8 时,Spring 会正确初始化并且端点正常工作。

在使用 Java 16 时,不会调用 onStartup() 方法,因此不会初始化 Spring 并且端点不起作用(尽管 Tomcat 仍然启动并响应错误)。

日志显示一条​​消息,虽然没有堆栈跟踪:

INFO: No Spring WebApplicationInitializer types detected on classpath

我需要做什么才能在 Java 16 上运行?

注意我不想使用spring-boot,请不要推荐。

解决方法

我找到了一种解决方法,可以配置 Spring 并响应 /hello 端点。但我不知道它为什么有效,也不知道这样做是否正确。

如果有人可以通过解释 Java 16 正在发生的事情来回答这个问题 - 我很乐意将其标记为已接受的答案。


解决方法

我的解决方法是以编程方式添加 ServletContainerInitializer 类。

所以之前我只是调用 addWebapp() 方法:

tomcat.addWebapp("",appBase);

我现在显式添加我的 Spring 初始化器:

Context appContext = tomcat.addWebapp("",appBase);
appContext.addServletContainerInitializer(new SpringAppConfig(),null);

Updated code on Github