Java EE/Jakarta EE是否支持Java模块系统?是否可以使用Java模块系统制作Web应用程序? [英] Does Java EE / Jakarta EE support the Java module system? Is it possible to make web application with the Java module system?

查看:46
本文介绍了Java EE/Jakarta EE是否支持Java模块系统?是否可以使用Java模块系统制作Web应用程序?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Java 11和Maven 3.6.1构建我的第一个模块化应用程序.我的IDE是IntellijIDEA 2019.1.3.我添加了一个模块"app"并添加了 module-info.java ,但是我感到困惑,因为即使我向应用程序模块中添加了spring依赖项,我的应用程序仍能正常工作,而我没有打开模块或模块中的一些软件包以进行反射.

I'm building my first modular app with Java 11 and Maven 3.6.1. My IDE is IntellijIDEA 2019.1.3. I added a module 'app' and added module-info.java, but I'm confused because my app is working even I added spring dependencies to the app module and I didn't open my module or some package in the module for reflection.

我使用IDE的功能添加了 module-info.java ,这迫使我添加了 requires 语句.到现在为止还挺好.但是,为什么不打开模块进行反射就可以工作呢?这是Java 11还是我的IDE版本中的某些新功能?我在做错什么吗?

I added module-info.java with my IDE's feature and it forces me to add requires statements. So far so good. But why it works without opening the module for reflection? Is that some new feature in Java 11 or in my IDE version? Am I doing something wrong?

我的 module-info.java :

module app {
    requires spring.web;
    requires spring.webmvc;
    requires javax.servlet.api;
    requires spring.context;
}

我试图在SO和JetBrains上找到答案,但是我失败了.

I tried to find the answer on SO and JetBrains, but I failed.

我正在看这个人( https://youtu.be/hxsCYxZ1gXU?t=2238 )使用spring模块,并且他的IDE要求他打开模块进行反射.然后我下载了他的项目,并删除了 opens 语句,它仍然可以在我的IDE中编译.

I am looking at this guy (https://youtu.be/hxsCYxZ1gXU?t=2238) working with spring modules and his IDE requires him to open the module for reflection. And I downloaded his project and deleted opens statements and it still compiles in my IDE.

还有一个问题:如何使用我的IDE检查模块路径?如何查看我的类路径中有哪些模块,什么在类路径中(现在应该什么都没有)?

And one more question: How can I examine the module-path with my IDE? How can I see which modules are there and what is on my classpath (right now there should be nothing)?

我刚刚意识到我的IDE打印命令行参数:--add-opens = java.base/java.lang = ALL-UNNAMED log.我想这就是原因,但我找不到此arg的来源.我在正确的道路上吗?

I just realized that my IDE prints Command line argument: --add-opens=java.base/java.lang=ALL-UNNAMEDlog. I suppose this is the reason, but I can't find where this arg is coming from. Am I on the right trail?

在控制台日志中,作为命令行参数是:

EDIT No. 2: In the console log, as command-line arguments are:

--add-opens=java.base/java.lang=ALL-UNNAMED
--add-opens=java.base/java.io=ALL-UNNAMED
-Djava.util.logging.config.file=C:\Users\Nedim\.IntelliJIdea2019.2\system\tomcat\Unnamed_ems\conf\logging.properties
-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager
-Djdk.module.showModuleResolution=true
-Dcom.sun.management.jmxremote=
-Dcom.sun.management.jmxremote.port=1099
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.password.file=C:\Users\Nedim\.IntelliJIdea2019.2\system\tomcat\Unnamed_ems\jmxremote.password
-Dcom.sun.management.jmxremote.access.file=C:\Users\Nedim\.IntelliJIdea2019.2\system\tomcat\Unnamed_ems\jmxremote.access
-Djava.rmi.server.hostname=127.0.0.1
-Djdk.tls.ephemeralDHKeySize=2048
-Djava.protocol.handler.pkgs=org.apache.catalina.webresources
-Dignore.endorsed.dirs=
-Dcatalina.base=C:\Users\Nedim\.IntelliJIdea2019.2\system\tomcat\Unnamed_ems
-Dcatalina.home=D:\tomcat\apache-tomcat-9.0.21
-Djava.io.tmpdir=D:\tomcat\apache-tomcat-9.0.21\temp

另外,从我的日志中(我不确定是否与此有关):

Also, from my log (I'm not sure is this relevant):

D:\tomcat\apache-tomcat-9.0.21\bin\catalina.bat run
[2019-11-08 05:42:34,404] Artifact app:war exploded: Waiting for server connection to start artifact deployment...
Using CATALINA_BASE:   "C:\Users\Nedim\.IntelliJIdea2019.2\system\tomcat\Unnamed_ems"
Using CATALINA_HOME:   "D:\tomcat\apache-tomcat-9.0.21"
Using CATALINA_TMPDIR: "D:\tomcat\apache-tomcat-9.0.21\temp"
Using JRE_HOME:        "C:\Program Files\Java\jdk-11.0.5"
Using CLASSPATH:       "D:\tomcat\apache-tomcat-9.0.21\bin\bootstrap.jar;D:\tomcat\apache-tomcat-9.0.21\bin\tomcat-juli.jar"

-show-module-resolution 打印出来:

root java.sql jrt:/java.sql
root jdk.management.jfr jrt:/jdk.management.jfr
root java.rmi jrt:/java.rmi
root jdk.jdi jrt:/jdk.jdi
root java.transaction.xa jrt:/java.transaction.xa
root java.xml.crypto jrt:/java.xml.crypto
root java.logging jrt:/java.logging
root java.xml jrt:/java.xml
root jdk.xml.dom jrt:/jdk.xml.dom
root jdk.jfr jrt:/jdk.jfr
root java.datatransfer jrt:/java.datatransfer
root jdk.httpserver jrt:/jdk.httpserver
root jdk.net jrt:/jdk.net
root java.naming jrt:/java.naming
root java.desktop jrt:/java.desktop
root java.prefs jrt:/java.prefs
root java.net.http jrt:/java.net.http
root jdk.compiler jrt:/jdk.compiler
root java.security.sasl jrt:/java.security.sasl
root jdk.jconsole jrt:/jdk.jconsole
root jdk.attach jrt:/jdk.attach
root java.base jrt:/java.base
root jdk.javadoc jrt:/jdk.javadoc
root jdk.management.agent jrt:/jdk.management.agent
root jdk.jshell jrt:/jdk.jshell
root jdk.jsobject jrt:/jdk.jsobject
root java.sql.rowset jrt:/java.sql.rowset
root java.management jrt:/java.management
root jdk.sctp jrt:/jdk.sctp
root java.smartcardio jrt:/java.smartcardio
root jdk.unsupported jrt:/jdk.unsupported
root jdk.scripting.nashorn jrt:/jdk.scripting.nashorn
root java.instrument jrt:/java.instrument
root java.security.jgss jrt:/java.security.jgss
root jdk.management jrt:/jdk.management
root jdk.security.auth jrt:/jdk.security.auth
root java.compiler jrt:/java.compiler
root java.scripting jrt:/java.scripting
root jdk.dynalink jrt:/jdk.dynalink
root jdk.unsupported.desktop jrt:/jdk.unsupported.desktop
root jdk.accessibility jrt:/jdk.accessibility
root jdk.jartool jrt:/jdk.jartool
root java.management.rmi jrt:/java.management.rmi
root jdk.security.jgss jrt:/jdk.security.jgss
jdk.security.jgss requires java.security.sasl jrt:/java.security.sasl
jdk.security.jgss requires java.logging jrt:/java.logging
jdk.security.jgss requires java.security.jgss jrt:/java.security.jgss
java.management.rmi requires java.naming jrt:/java.naming
java.management.rmi requires java.rmi jrt:/java.rmi
java.management.rmi requires java.management jrt:/java.management
jdk.accessibility requires java.desktop jrt:/java.desktop
jdk.unsupported.desktop requires java.desktop jrt:/java.desktop
jdk.dynalink requires java.logging jrt:/java.logging
jdk.security.auth requires java.naming jrt:/java.naming
jdk.security.auth requires java.security.jgss jrt:/java.security.jgss
jdk.management requires java.management jrt:/java.management
java.security.jgss requires java.naming jrt:/java.naming
jdk.scripting.nashorn requires jdk.dynalink jrt:/jdk.dynalink
jdk.scripting.nashorn requires java.logging jrt:/java.logging
jdk.scripting.nashorn requires java.scripting jrt:/java.scripting
java.sql.rowset requires java.logging jrt:/java.logging
java.sql.rowset requires java.sql jrt:/java.sql
java.sql.rowset requires java.naming jrt:/java.naming
jdk.jsobject requires java.desktop jrt:/java.desktop
jdk.jshell requires jdk.compiler jrt:/jdk.compiler
jdk.jshell requires java.compiler jrt:/java.compiler
jdk.jshell requires java.logging jrt:/java.logging
jdk.jshell requires java.prefs jrt:/java.prefs
jdk.jshell requires jdk.internal.ed jrt:/jdk.internal.ed
jdk.jshell requires jdk.internal.le jrt:/jdk.internal.le
jdk.jshell requires jdk.internal.opt jrt:/jdk.internal.opt
jdk.jshell requires jdk.jdi jrt:/jdk.jdi
jdk.management.agent requires java.management jrt:/java.management
jdk.management.agent requires java.management.rmi jrt:/java.management.rmi
jdk.javadoc requires java.compiler jrt:/java.compiler
jdk.javadoc requires java.xml jrt:/java.xml
jdk.javadoc requires jdk.compiler jrt:/jdk.compiler
jdk.attach requires jdk.internal.jvmstat jrt:/jdk.internal.jvmstat
jdk.jconsole requires java.desktop jrt:/java.desktop
jdk.jconsole requires jdk.management.agent jrt:/jdk.management.agent
jdk.jconsole requires jdk.attach jrt:/jdk.attach
jdk.jconsole requires java.management.rmi jrt:/java.management.rmi
jdk.jconsole requires java.management jrt:/java.management
jdk.jconsole requires jdk.internal.jvmstat jrt:/jdk.internal.jvmstat
jdk.jconsole requires jdk.management jrt:/jdk.management
jdk.jconsole requires java.rmi jrt:/java.rmi
java.security.sasl requires java.logging jrt:/java.logging
jdk.compiler requires java.compiler jrt:/java.compiler
java.prefs requires java.xml jrt:/java.xml
java.desktop requires java.xml jrt:/java.xml
java.desktop requires java.prefs jrt:/java.prefs
java.desktop requires java.datatransfer jrt:/java.datatransfer
java.naming requires java.security.sasl jrt:/java.security.sasl
jdk.xml.dom requires java.xml jrt:/java.xml
java.xml.crypto requires java.xml jrt:/java.xml
java.xml.crypto requires java.logging jrt:/java.logging
jdk.jdi requires jdk.attach jrt:/jdk.attach
jdk.jdi requires jdk.jdwp.agent jrt:/jdk.jdwp.agent
java.rmi requires java.logging jrt:/java.logging
jdk.management.jfr requires jdk.jfr jrt:/jdk.jfr
jdk.management.jfr requires java.management jrt:/java.management
jdk.management.jfr requires jdk.management jrt:/jdk.management
java.sql requires java.logging jrt:/java.logging
java.sql requires java.transaction.xa jrt:/java.transaction.xa
java.sql requires java.xml jrt:/java.xml
jdk.dynalink binds jdk.scripting.nashorn jrt:/jdk.scripting.nashorn
java.naming binds jdk.naming.rmi jrt:/jdk.naming.rmi
java.naming binds jdk.naming.dns jrt:/jdk.naming.dns
java.management binds java.management.rmi jrt:/java.management.rmi
java.management binds jdk.management jrt:/jdk.management
java.management binds jdk.management.jfr jrt:/jdk.management.jfr
java.compiler binds jdk.compiler jrt:/jdk.compiler
java.compiler binds jdk.javadoc jrt:/jdk.javadoc
java.base binds jdk.zipfs jrt:/jdk.zipfs
java.base binds jdk.localedata jrt:/jdk.localedata
java.base binds jdk.security.jgss jrt:/jdk.security.jgss
java.base binds java.security.jgss jrt:/java.security.jgss
java.base binds jdk.crypto.cryptoki jrt:/jdk.crypto.cryptoki
java.base binds java.smartcardio jrt:/java.smartcardio
java.base binds jdk.crypto.mscapi jrt:/jdk.crypto.mscapi
java.base binds jdk.crypto.ec jrt:/jdk.crypto.ec
java.base binds java.security.sasl jrt:/java.security.sasl
java.base binds java.naming jrt:/java.naming
java.base binds java.xml.crypto jrt:/java.xml.crypto
java.base binds jdk.jdeps jrt:/jdk.jdeps
java.base binds jdk.javadoc jrt:/jdk.javadoc
java.base binds jdk.jlink jrt:/jdk.jlink
java.base binds jdk.jartool jrt:/jdk.jartool
java.base binds jdk.compiler jrt:/jdk.compiler
java.base binds java.desktop jrt:/java.desktop
java.base binds java.management jrt:/java.management
java.base binds jdk.security.auth jrt:/jdk.security.auth
java.base binds java.logging jrt:/java.logging
java.base binds jdk.charsets jrt:/jdk.charsets
jdk.jshell binds jdk.editpad jrt:/jdk.editpad
java.desktop binds jdk.accessibility jrt:/jdk.accessibility
java.desktop binds jdk.unsupported.desktop jrt:/jdk.unsupported.desktop
java.datatransfer binds java.desktop jrt:/java.desktop
java.scripting binds jdk.scripting.nashorn jrt:/jdk.scripting.nashorn
jdk.internal.jvmstat binds jdk.jstatd jrt:/jdk.jstatd
jdk.jstatd requires jdk.internal.jvmstat jrt:/jdk.internal.jvmstat
jdk.jstatd requires java.rmi jrt:/java.rmi
jdk.editpad requires java.desktop jrt:/java.desktop
jdk.editpad requires jdk.internal.ed jrt:/jdk.internal.ed
jdk.jlink requires jdk.jdeps jrt:/jdk.jdeps
jdk.jlink requires jdk.internal.opt jrt:/jdk.internal.opt
jdk.jdeps requires java.compiler jrt:/java.compiler
jdk.jdeps requires jdk.compiler jrt:/jdk.compiler
jdk.crypto.cryptoki requires jdk.crypto.ec jrt:/jdk.crypto.ec
jdk.naming.dns requires java.naming jrt:/java.naming
jdk.naming.rmi requires java.naming jrt:/java.naming
jdk.naming.rmi requires java.rmi jrt:/java.rmi

推荐答案

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

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的人.Youtube 使用模块,他正在使用Tomcat.他把他的联系人放到了最后一张幻灯片中,所以我决定问他发生了什么事.这是他的回答的相关部分:

But I still couldn't let it go, because I saw the guy named Jaap Coomans on Youtube 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.

这篇关于Java EE/Jakarta EE是否支持Java模块系统?是否可以使用Java模块系统制作Web应用程序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆