且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

Java EE/Jakarta EE是否支持Java模块系统?是否可以使用Java模块系统制作Web应用程序?

更新时间:2023-12-04 15:46:59

让我们总结一下问题和答案.

Let summarize the problem and the answer.

我重命名了我的问题以使其更适合该问题,因此将来可以重用它.当我启动该线程时,问题是:是否必须在module-info.java中添加open语句才能打开模块进行反射.发生的是,我使用Java 11和Spring制作了模块化Web应用程序,并且我注意到我的设置不需要反射模块或开放模块.

I renamed my question to better suit the problem, so in the future, it can be reused. When I start this thread question was: Do I have to add an open statement in module-info.java to open module for reflection. What happened is that I made modular web application with Java 11 and Spring and I have noticed that my setup does not require open modules or any packages in them for reflection.

使用-show-module-resolution 标志仅列出JDK模块.它没有显示我的任何模块.

Using --show-module-resolution flag listed only JDK modules. It didn't show any of my modules.

@Holger用户在此问题上的帮助最大.他建议使用 System.out.println("classpath:" + System.getProperty("java.class.path")); 来查看类路径上的内容.而且没有任何关系.

User @Holger helped the most with this issue,. He recommended using System.out.println("classpath: " + System.getProperty("java.class.path")); to see what is on the classpath. And there was nothing relevant.

然后他提议使用 System.out.println(SomeClass.class.getModule()); 在代码中的某个地方查看我的代码属于已声明模块还是未命名模块.结果发现它属于未命名的模块.

Then he proposed using System.out.println(SomeClass.class.getModule()); somewhere in the code to see is my code belongs to a declared module or unnamed module. And it turned out that it belongs to the unnamed module.

因此得出的结论是,Apache Tomcat的ClassLoader将我的类以及Spring jar加载到未命名的模块中.

So the conclusion was that Apache Tomcat's ClassLoader loads my classes as well as Spring jars to the unnamed module.

然后我问Apache支持我如何使Tomcat正确加载我的模块,答案是:

Then I asked Apache support how can I make Tomcat load my modules correctly and the answer was:

不能.Servlet API(也不是Java EE/Jakarta EE的任何部分)没有使用模块系统.标记

You can't. The Servlet API (nor any part of Java EE / Jakarta EE) does not make use of the module system. Mark

但是我还是不能放弃,因为我在上看到一个叫Jaap Coomans的人.*** 使用模块,他正在使用Tomcat.他把他的联系人放到了最后一张幻灯片中,所以我决定问他发生了什么事.这是他的回答的相关部分:

But I still couldn't let it go, because I saw the guy named Jaap Coomans on *** working with modules and he was using Tomcat. He put his contact on one of the last slides, so I decided to ask him what is going on. And here is a relevant part of his answer:

从我的描述中可以得出,您的设置与我的谈话之间的主要区别是您在单独的Tomcat服务器上运行Spring Web应用程序,而在我的谈话中我正在使用以下内容构建Spring Boot应用程序:嵌入式Tomcat服务器.这是一个细微的差异,很可能是导致您遇到此问题的原因.使用Spring Boot,应用程序本身是从命令行启动的.然后,应用程序启动嵌入式Tomcat,使应用程序模块本身负责类加载以及类路径和模块路径.其中大部分由Spring Boot进行后台管理,因此您可以说Spring(Boot)负责启动Tomcat.您采用的方法是经典" Spring(无引导)设置,Tomcat在该设置中启动了该过程,并负责类加载和加载应用程序.简单点说:在我的演讲示例中,Spring启动了Tomcat,就您而言,反之亦然.

From what I get from your description the main difference between your setup and the one in my talk is that your are running a Spring web application on a separate Tomcat server, whereas in my talk I'm building a Spring Boot application with an embedded Tomcat server. This is a subtle difference that is likely to be the cause of the issue you're running into. With Spring Boot, the application itself is booted from the command line. The application then launches the embedded Tomcat, making the application module itself in charge of classloading and the classpath and modulepath. Most of this is managed under the hood by Spring Boot, so you could say Spring (Boot) is in charge of booting Tomcat. The approach you've taken is the "classic" Spring (without Boot) setup where Tomcat starts the process and is in charge of classloading and loads your application. To put it a little simpler: in the example of my talk Spring starts Tomcat, in your case it is the other way around.

(...)

确实,当前Java/Jakarta EE规范不支持模块系统.由于规范的性质,我想这实际上可能是要克服的挑战.在过渡到Eclipse基础之后,我不确定该主题在Jakarta EE路线图上的位置.我一定会注意的.不幸的是,您实际问题的答案仍然是您的设置无法实现.

It is true that currently the Java / Jakarta EE spec does not support the module system. Due to the nature of the spec I guess this may actually be quite of a challenge to overcome. I'm not sure where this topic is on the roadmap of Jakarta EE right after the transition to the Eclipse foundation. That's something I will definitely look out for. Unfortunately the answer to your actual question is still that it is not possible in your setup.

关键要点是:

  • 核心Java支持Java模块系统.
  • Java EE/Jakarta EE不使用Java模块系统,因此Web容器会将所有类放入未命名的模块.这是通过单独的Tomcat设置进行的.
  • 如Jaap所述,Spring Boot使用嵌入式Tomcat,使应用程序模块本身负责类加载以及类路径和模块路径.

最后,当我从@Holger和Jaap得到答案后,我发现解决方案.我还没有尝试过.

And in the end, after I got an answer from @Holger and Jaap I found this and one interesting possible solution. I haven't tried it.

这是一条漫长的路,但最后我们明确了.

It was a long road, but we made it clear in the end.