问题描述
我有一个非常简单的 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);