虽然现在现在关于java的IDE已经非常的成熟了,但是我还是想从最原始的方式开始学习java,于是这次使用了记事本和cmd命令行方式编译一个小的servlet程序。
遇到的麻烦最郁闷的就是在编译servlet时候,需要使用到Tomcat的servlet-api.jar的类包。这个包一般位于Tomcat\lib目录下,javac -classpath时候将这个类包引用。但是问题来了,每当我输入命令符进行编译时:

Cmd代码

使用命令行 java debug 命令行javac_使用命令行 java debug

使用命令行 java debug 命令行javac_java_02

使用命令行 java debug 命令行javac_java_03



1. javac -classpath E:\Program Files\Apache Software Foundation\Tomcat  7.0\lib\servlet-api.jar -d classes E:\Program Files\Apache Software Foundation\Tomcat 7.0\webapps\Beer-v1\src\com\example\web\BeerSelect.java


javac -classpath E:\Program Files\Apache Software Foundation\Tomcat 7.0\lib\servlet-api.jar -d classes E:\Program Files\Apache Software Foundation\Tomcat 7.0\webapps\Beer-v1\src\com\example\web\BeerSelect.java



就会提示:javac: 无效的标记: Files\Apache


上网查询了许久,都说是环境变量配置错误了。但是平时使用javac的时候是正常的,应该不是环境变量的问题。后来我将jar的包复制到E:\的根目录下,这次可以正常运行了。弄了许久总要发现问题原来是,TomCat的安装目录尽量不要有空格,否则会出现各种错误。最后得出的


结论是:

不要把 Tomcat 装在带有空格的路径之中,因为命令行的参数是使用空格分隔的



接下来我只好将代码和servlet-api.jar复制到E盘根目录下,后来终于编译成功了:


Cmd代码

使用命令行 java debug 命令行javac_使用命令行 java debug

使用命令行 java debug 命令行javac_java_02

使用命令行 java debug 命令行javac_java_03

1. >javac -d classes -classpath e:\servlet-api.jar -sourcepath e:\Beer-v1 
2. \src e:\Beer-v1\src\com\example\web\BeerSelect.java


>javac -d classes -classpath e:\servlet-api.jar -sourcepath e:\Beer-v1
\src e:\Beer-v1\src\com\example\web\BeerSelect.java



其中BeerSelect.java为servlet文件,引用了包-classpath e:\servlet-api.jar,这个文件还依赖了一个模型类,位于\Beer-v1\src中。具体方法都是查看的附件里面的内容。



附件(引自):
javac参数(-classpath, -sourcepath)详解



引用


-classpath:

设置用户类路径,它将覆盖 CLASSPATH 环境变量中的用户类路径。若既未指定 CLASSPATH 又未指定 -classpath,则用户类路径由当前目录构成。



-sourcepath:

指定用以查找类或接口定义的源代码路径。与用户类路径一样,源路径项用分号 (;) 进行分隔,它们可以是目录、JAR 归档文件或 ZIP 归档文件。如果使用包,那么目录或归档文件中的本地路径名必须反映包名。

注意:通过类路径查找的类,如果找到了其源文件,则可能会自动被重新编译。



官方说法很简洁,但是具体操作起来总觉得不太清晰,我们还是找几个例子,来具体分析一下:

具体例子:

假设我们有如下的目录结构:

src-| 
 

 |-foo-| 
 

 |-Testfoo.java 
 

 |-baz-| 
 

 |-Testbaz.java 
 

 classes-| 
 

 其中Testfoo.java: 
 

 package foo; 
 

 public class Testfoo { 
 

 //.... 
 

 } 
 

 其中Testbaz.java: 
 

 package baz; 
 

 import foo.Testfoo; 
 

 public class Testbaz { 
 

 //... 
 

 }



也就是说Testbaz对Testfoo有引用。

我们目标是把Testbaz编译到目录classes里面,试用如下的命令:

javac -d classes src/baz/Testbaz.java

命令失败,因为找不到它依赖的Testfoo。我们可以用以下三种方式来实现:

1.我们最容易考虑到的就是编译被依赖的Testfoo类,并将其加入Testbaz的CLASSPATH

javac -d classes src/foo/Testfoo.java

javac -d classes -classpath classes src/baz/Testbaz.java

第二行使用了-classpath,使得编译器在寻找Testfoo类的时候以classes为根目录,根据根目录和package名,类名最终定位了需要用的(已编译出来的)Testfoo类。



2.在编译Testbaz的时候把被依赖的Testfoo类加入SOURCEPATH

javac -d classes -sourcepath src src/baz/Testbaz.java

在编译条件里面加入-verbose可以很清楚的看到,编译器在寻找Testfoo类的时候,以src为根目录,根据根目录和package名,类名最终定位了需要用的(源代码)Testfoo类。



3.把CLASSPATH和SOURCEPATH两者都加进来

javac -d classes src/foo/Testfoo.java 
 

 javac -d classes -sourcepath src -classpath classes src/baz/Testbaz.java



两个属性都被加入,编译器首先会判断Testfoo.class和Testfoo.java是否同时存在。如果单独存在,则适应于以上的方法之一。如果同时存在,则判断.class是否是.java的最新编译,如果有差异,则重新编译.java来覆盖.class