server loader不应该改动,但是shared loader还是有许多有用的应用。(shared loader将会在启动过程的最后阶段加载它的类,在Commons loader之后)。现在让我们看看一些常见的问题以及如何解决。
问题、解决方案和最佳实践
问题:我的应用程序依赖一个外部的仓库,我不能引用它。
让Tomcat知道一个外部的仓库,在catalina.properties文件的shared loader位置,使用正确的语法,声明这个仓库。语法基于你要配置的文件或仓库的类型:
1、增加一个文件夹作为类仓库,使用“path/to/foldername”
2、增加一个文件夹下的所有jar文件作为类仓库,使用"path/to/foldername/*.jar"
3、增加单个jar文件作为类仓库,使用"file://path/to/foldername/jarname.jar"
4、调用环境变量,使用${}格式,例如${VARIABLE_NAME}
5、声明多个资源,用逗号分隔开
6、所有的路径相对于CATALINA_BASE或CATALINA_HOME,或者是绝对路径
问题:我想多个应用程序共享一个jar文件,这个jar文件在Tomcat里面。
除了一些常见的第三方库(比如JDBC drivers),最好不要在$CATALINA_HOME/lib目录下包含额外的库,即使这样在一些情况下是可行的。应该重新创建比如/shared/lib和/shared/classes目录,然后在catalina.properties配置shared.loader属性:
"shared/classes,shared/lib/*.jar"
问题:除了另一个框架,我在一个应用中使用了一个嵌入式Tomcat server,当我访问框架组件的时候遇到classpath errors。
这个问题好像超出了这篇文章的范畴,但是作为一个常见的classpath相关的问题,这里对如何引起你的错误作一个简单的介绍。
当嵌入到包含另外核心框架(Wicket或者Spring)的应用中时,Tomcat将在启动框架的时候,使用System classloader加载核心类,而不是从应用的WEB-INF/lib目录下加载。
java的类加载是懒加载,就是说请求某个类的第一个加载器拥有这个类剩下的生命周期。如果System classloader,它的类对web应用是不可见的,首先加载了框架相关的类,java虚拟机将会阻止来的其他实例被创建,这样就引起了classpath错误。
解决这个问题的一种方式就是增加一个自定义的bootstrap classloader,使得这个classloader加载合适的库,然后对程序剩下部分的启动正常对待。
问题:我使用一个标准的应用程序,程序的war包含了依赖的所有包,但是我仍然遇到类定义错误。
这个问题可能是由许多事情引起的,包括编译或部署过程不是很正确,但是最有可能是web应用程序的目录结构不对造成的。
java命名转换要求类名映射到存放这个类的目录结构。例如,一个类com.mycompany.mygreat.class需要被存放到目录WEB-INF/classes/com/mycompany/。
经常代码中丢失一个点号就会引起classpath相关的问题。
问题:我的web应用程序的不同模块需要使用同一个jar包的两个不同版本。
这种情况常常出现在一个应用程序中使用多个web框架,这些web框架依赖一个库的不同版本。
有几种解决方案,但是它们都和classpath不相关。我们在这里说这个问题,是因为一些用户试图在框架的jar文件中的Manifest文件中指定依赖的库的不同版本的classpath,来解决这个问题。
这种方式在一些web应用服务器中是支持的,所以一些用户想要在Tomcat中也使用这种方式。但是在Manifest文件中指定classpath在Tomcat中是不支持的,这也不是Servlet说明的一部分。
有以下四种方式来解决这个问题:
1、你可以更新框架的版本,如果这里能够使得与其他框架依赖相同的版本。
2、你可以创建两个或更多的自定义classloaders,每个jar文件一个,在WEB/INF/context.xml文件中配置,创建你所需要的两个不同版本的类的实例。
3、你可以使用jarjar工具将框架和它依赖的库打包成一个jar文件,那么它们会一起被加载。