如何在服务器范围内缓存(在此服务器上跨越多个WAR的缓存范围)来自JAR的类实例,该JAR在Web容器(服务器,例如Tomcat)上的几个WAR中包含二进制相同的内容?
< EDIT> 我希望跨WAR缓存应用程序数据,因为数据对他们来说很常见。 (这是一个门户项目,在不同的“视图”中共享公共数据非常有用,这些“视图”实现为部署为不同WAR的不同portlet,并且使用Java对象缓存比使用中央数据保持服务更快,更简单。 )< / EDIT>
这有可能吗?或者是否需要将这样的JAR放在由公共父类加载器访问的路径上,例如在/ lib / ext中?
请参阅:Java, Classpath, Classloading => Multiple Versions of the same jar/project
请参阅:How does class loading work when the same class exists in different applications on the same server?
答案 0 :(得分:0)
是的,最好的选择是将类放在一个类加载器中,该类加载器是两个应用程序的父级。如果lib/ext
表示JAVA_HOME/lib/ext
,那么我就不建议这样做。相反,您应该将它们放在CATALINA_HOME/lib
目录中。请参阅文档的Shared Library Files部分,该部分链接到Class Loader HOW-TO文档。
答案 1 :(得分:0)
您可以在shared.loader
中的conf/catalina.properties
属性中添加公共类(jar)。这些类可用于所有Web应用程序,但不适用于tomcat本身。
如果围绕静态单例实现缓存,那么您将能够从不同的Web应用程序访问对象。但我不知道这是否是最好的做法。例如,它使得难以扩展,因为它使得无法将应用程序负载平衡到许多服务器上。
答案 2 :(得分:0)
答案似乎是" 取决于"。
如果相关的JAR(或类)没有与服务器上部署的其他组件冲突的依赖项,两个建议的解决方案(CATALINA_HOME/lib/ext/
和CATALINA_HOME/conf/catalina.properties :: shared.loader
)应该明白工作即可。因此,两者都是正确答案"我看不出哪一个更正确"比另一个。
然而,当我第一次提出问题时,我错过了一个关键细节(但这并没有使它无效):在我的情况下,有问题的JAR需要Spring 4.2.9.RELEASE(以及其他依赖项),但部署了其他相关的WAR相同的服务器包含并要求Spring 3.0.7。 (要缓存的对象不依赖于Spring,但JAR的设计并未考虑到这个问题,并且它还包含其他相关代码,具体取决于Spring,现在很难分离。)
通常情况下,只要所有已经部署的WAR包含他们需要的所有内容,就应该可以将CATALINA_HOME/lib/ext/
放入任何你想要的:"模块第一个/父最后一个&# 34;类加载策略应该可以防止冲突,即使(如本例所示)Spring 4.2.9可用于父类加载器并且Spring 3.0.7可用于WAR类加载器。但它看起来有点不干净"对我来说是混乱的事情。
因此,我决定使用" to-be-cached" object的类加载器哈希码作为地图中的键,其中缓存的数据是值。然后通过类加载器"选择所有缓存的数据。它自动且透明地确保分配兼容性。如果在服务器上部署了另一个可以更改并因此使缓存数据无效的WAR,它可以从缓存中删除整个映射,从而强制执行"读取访问" WAR在下次访问时重新加载数据。
然而这种方法不允许跨WAR缓存:实际上每个WAR都会获得自己的私有缓存段。
另一种方法是故意将所有数据转换为高速缓存到/来自e。 G。 JSON以便获得一个自然全球化的#34;缓存数据的数据类型,如java.lang.String
。如果从项目的开头选择,对我来说这似乎是最干净的方式,但如果已经有一个复杂的(通常是有效的)实现,这可能会导致一些工作要做。
欢迎评论这个自我回答!