最近我尝试将Jersey2应用程序部署到Glassfish4.1。我有很多依赖问题,发现了很多ClassCastException。
后来我在这里找到了用户指南:https://jersey.java.net/documentation/latest/modules-and-dependencies.html#servlet-app-glassfish
我必须配置pom.xml,如:
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
<version>2.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>2.23.1</version>
<scope>provided</scope>
</dependency>
如果您使用的是Glassfish应用程序服务器,则无需使用您的应用程序打包任何内容,所有内容都已包含在内。您只需要声明(提供)对JAX-RS API的依赖,以便能够编译您的应用程序。
我的问题是为什么Glassfish必须为应用程序提供jersey2(JSR实现)本身。为什么不让应用程序选择它正在使用的JSR实现?
我还在glassfish-web.xml
下添加WEB-INF
:
<glassfish-web-app>
<class-loader delegate="false" />
</glassfish-web-app>
根据此处的文件(https://docs.oracle.com/cd/E19798-01/821-1752/beagb/index.html):
首先让Glassfish加载WEB-INF/lib/
下的类。但是为什么Glassfish仍然使用自己的平针版和javax版?
对于javax,我猜Glassfish是一个java应用程序版本,它只支持特定的JSR实现。所以当我在我的应用程序中选择JSR实现时,我必须找到正确的Glassfish版本。
但为什么jersey2如此特别以至于玻璃鱼必须提供它。如果我想使用另一个版本的jersey2怎么办?
更新:
我又做了一些测试。当我将一个jersey1应用程序(jersey1包含在war文件中)部署到glassfish4并要求glassfish4将类加载器进程委托给其父进程时,此应用程序正常工作,应用程序可以处理传入的休息请求。为什么?我想因为glassfish没有包含jersey1,所以它会从war文件中的库中加载jersey1,而glassfish4实际上是在使用jersey1。这是否意味着我可以覆盖glassfish默认行为,让应用程序选择JAX-RS实现。
如果我用jersey2替换jersey1并且仍然让glassfish4首先从战争中加载库,那么会抛出异常:
WebModule[/invoiceLoader]StandardWrapper.Throwable
java.lang.ClassCastException: Cannot cast org.glassfish.jersey.gf.cdi.internal.CdiComponentProvider to org.glassfish.jersey.server.spi.ComponentProvider
at java.lang.Class.cast(Class.java:3369)
at org.glassfish.jersey.internal.ServiceFinder$LazyObjectIterator.hasNext(ServiceFinder.java:713)
at org.glassfish.jersey.server.ApplicationHandler.getRankedComponentProviders(ApplicationHandler.java:743)
at org.glassfish.jersey.server.ApplicationHandler.access$600(ApplicationHandler.java:184)
at org.glassfish.jersey.server.ApplicationHandler$4.get(ApplicationHandler.java:406)
at org.glassfish.jersey.server.ApplicationHandler$4.get(ApplicationHandler.java:399)
at org.glassfish.jersey.internal.util.collection.Values$LazyValueImpl.get(Values.java:340)
at org.glassfish.jersey.server.ApplicationHandler.createApplication(ApplicationHandler.java:366)
at org.glassfish.jersey.server.ApplicationHandler.<init>(ApplicationHandler.java:342)
at org.glassfish.jersey.servlet.WebComponent.<init>(WebComponent.java:392)
at org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:177)
这个异常是如何发生的?
答案 0 :(得分:3)
我的问题是为什么Glassfish必须为应用程序提供jersey2(JSR实现)本身。为什么不让应用程序选择它正在使用的JSR实现?
因为Glassfish是符合Java EE的服务器,而JAX-RS是EE规范的一部分。因此,它需要JAX-RS的实现来运行JAX-RS应用程序。它恰好使用Jersey作为实现,就像JBoss使用RESTEasy一样。如果服务器没有实现,那么它将不符合EE。应用程序应该能够运行完整的EE应用程序,仅针对单个EE jar编译应用程序。它不应该对实现有任何了解。
如果我想使用其他版本的jersey2怎么办?
您可以尝试用新的替换所有Jersey实施jar。请参阅Updating Jersey 2 in GlassFish 4。