3

我一直在花费数小时试图弄清楚为什么我得到了java.lang.NoClassDefFoundError.,并且我已经将原因缩小到 Tomcat 的类路径。

我使用下面的代码来查看路径变量包含什么:

out.println("Classpath: '" + System.getProperty( "java.class.path" ) + "'" );
out.println("Ext dirs: '" + System.getProperty( "java.ext.dirs" ) + "'" );
out.println("Library path: '" + System.getProperty( "java.library.path" ) + "'" );
out.println("Path separator: '" + System.getProperty( "path.separator" ) + "'" );

输出是:

类路径:':/usr/local/tomcat/bin/bootstrap.jar'
分机目录:'/usr/lib/jvm/java-6-sun-1.6.0.16/jre/lib/ext:/usr/java/packages/lib/ext'
库路径:'/usr/lib/jvm/java-6-sun-1.6.0.16/jre/lib/i386/server:/usr/lib/jvm/java-6-sun-1.6.0.16/jre/lib/ i386:/usr/lib/jvm/java-6-sun-1.6.0.16/jre/../lib/i386:/usr/java/packages/lib/i386:/lib:/usr/lib'
路径分隔符:':'

如您所见,Classpath 不以“.”开头。正如它应该的那样,我相信这就是为什么我的程序找不到我从 webapp 的子目录中导入的类的原因。

要查看类路径的设置位置,我做了grep -R bootstrap.jar /usr/local/tomcat/,并且遇到了这个:(CLASSPATH="$CLASSPATH":"$CATALINA_HOME"/bin/bootstrap.jar在文件中/usr/local/tomcat/bin/catalina.sh

这让我相信由于某种原因 $CLASSPATH 在这里是空的。但是,echo $CLASSPATH成功返回.:/usr/lib/jvm/java-6-sun/bin:/usr/local/tomcat/lib/servlet-api.jar

任何人都可以帮助解决这里的问题吗?


编辑:我所有的 servlet 文件都在WEB-INF/classes/controllers/,我试图加载的库是子目录中的类文件。例如,如果ClassName.class在 WEB-INF/classes/controllers/packagename/ 目录中,我添加package packagename到 的开头,然后使用inClassName.java导入它。import packagename.*someServlet.java


EDIT2:我已经解决了我的问题。我的主要问题是,如下所述,没有使用正确的包名称。另外,我试图从classes/controllers/目录内部编译,而不是从classes/. 谢谢大家的帮助!

4

3 回答 3

7

Web 应用程序所需的类应位于 WEB-INF/classes 文件夹中的 Web 应用程序中,或者打包在 WEB-INF/lib 中的 JAR 文件中。您通常不应该为此使用 servlet 容器通用类路径设置,正如您似乎尝试的那样。

于 2009-10-23T11:50:45.597 回答
7

Tomcat 的类路径不应该以.. 实际上,添加.到类路径只是告诉java在当前目录中查找类的一种方便方法,而不必-cp在命令行上使用它。

实际上,在大多数情况下,您不必调整 Tomcat 的类路径。为了使 Tomcat 能够找到您的类,您需要做的是将您的应用程序部署为具有特定布局的标准化 WAR(Web 存档)。像这样的东西:

.
|-- WEB-INF
|   |-- classes
|   |   `-- com
|   |       `-- mycompany
|   |           `-- MyServlet.class
|   |-- lib
|   |   |-- bar.jar
|   |   `-- foo.jar
|   `-- web.xml
|-- application.jsp
|-- image.gif
`-- index.html

WEB-INF/classes目录是您编译的类需要的位置,这是 Tomcat 将在其中查找它们的位置。如果您将类放在WEB-INF/classes/controllers,controllers将被视为包名称的一部分(这可能不是您想要的)。所以你有两个选择:

  1. 删除该controllers目录
  2. 或将其添加到包名称中。

但它们是相互排斥的,你不能两者兼得。

于 2009-10-23T13:05:28.070 回答
2

CLASSPATH不是“应该”以".". 由于它的目的是配置运行时,它可以自由地采用您选择的任何值。另请注意,CLASSPATH自 Java 1.1(1997 年初发布)以来一直不鼓励使用环境变量——至少 12 年。

另一方面,Web 应用程序的类路径是明确指定的。将目录(和任何其他无效子目录)的内容移动到中以便包目录是.controllersWEB-INF/classes/classes

于 2009-10-23T14:40:09.157 回答