1、新建Servlet文件
1)我们知道,要成为一个Servlet,则必须(一般)继承HttpServlet 类。
2)在D:\Javaspace\TestWeb\com\example\servlet\中,使用记事本新建如下MyServlet.java文件。
package com.example.servlet; public class MyServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); PrintWriter out = response.getWriter(); out.println("This is my first Servlet"); out.close(); } }
2、使用javac命令编译MyServlet.java文件
1)运行cmd,进入命令行提示符界面,直接执行javac命令,但很不幸报错了,如下图所示。
很明显,报错的提示是找不到MyServlet.java文件。
原因:MyServlet.java文件放在D:\Javaspace\TestWeb\com\example\servlet\中,而不是在C:\Users\Linwei\目录中,所以找不到指定文件。
解决方法:先切换到D:\Javaspace\TestWeb\com\example\servlet\目录,在进行编译。
2)切换到D:\Javaspace\TestWeb\com\example\servlet\目录中并再次编译。不幸的是,又报错了,如下所示。
直观的看报错提示,出错的原因是:
a)找不到HttpServlet类。
b)找不到HttpServletRequest类。
c)找不到HttpServletResponse类。
d)找不到ServletException类。
e)找不到IOException类。
f)找不到PrintWriter类。
看来是需要导入这些类所在的包才行,查看这些类所在的包发现:HttpServlet、HttpServletRequest、HttpServletResponse、ServletException都在servlet-api.jar中,而IOException和PrintWriter类都在java.io包中,所以修改源文件,导入相应的包,如下所示。
package com.example.servlet; import javax.servlet.http.*; import javax.servlet.*; import java.io.*; public class MyServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); PrintWriter out = response.getWriter(); out.println("This is my first Servlet"); out.close(); } }
3)修改完成后,重新执行编译,不幸的是还是报错,如下图所示。
直观的看报错提示,出错的原因是:
a)包javax.servlet 不存在。
b)包javax.servlet.http 不存在。
c)找不到HttpServletRequest类。
d)找不到HttpServletResponse类。
e)找不到ServletException类。
看出错提示好像和上一次的差不多,还是找不到相关的类什么的。由此我们引出以下问题:
a)我们已经导入了javax.servlet.* 和 javax.servlet.http.* 包,为什么还是提示找不到?
b)我们也导入了java.io.* 包,而且刚才找不到IOException类和找不到PrintWriter类的错误消失了,看来编译器能够正确的找到java.io包,但为什么又能找到java.io包呢?
要回答以上问题,得了解下JVM的类加载器。当JVM 启动的时候,Java 缺省使用如下三种类型类装入器:
a)启动(Bootstrap)类加载器:引导类装入器是用本地代码实现的类装入器,它负责加载Java的核心类库,即负责将<Java_Home>/jre/下面的类库加载到内存中。
b)标准扩展(Extension)类加载器 :扩展类加载器是由Sun的ExtClassLoader实现的。它负责将
< Java_Home >/jre/lib/ext 或者由系统变量java.ext.dir指定位置中的类库加载到内存中。
c)系统(System)类加载器 :系统类加载器是由 Sun 的AppClassLoader实现的。它负责将在命令java中的-classpath或者java.class.path系统属性或者CLASSPATH坏境变量指定的路径中的类库加载到内存中。
由此可以推出,当我们使用javac命令时,它会自动在以下三个地方查找相关的软件包及类:
a)<Java_Home>/jre/下的类库中
b)< Java_Home >/jre/lib/ext 中(该位置专门存放第三方的类库)
b)系统类路径(CLASSPATH)中
由此,我们也应该知道为什么我们不需要在系统属性CLASSPATH中指定这些类库了吧,因为JVM在启动的时候就自动加载它们了。
好了,了解了类加载器相关知识点后,我们回到上述问题本身:
问题a):为什么找不到javax.servlet.* 和 javax.servlet.http.* 包,他们又存放在哪呢?
原因:经过查询,Servlet依赖于servlet-api.jar包,进一步打开jar包可以发现javax.servlet.* 包和 javax.servlet.http.* 包确实都存放在该jar包中。
解决方法:
a)将servlet-api.jar直接加到< Java_Home >/jre/lib/ext中。由于servlet-api.jar属于第三行类库,所以必须放在jre的扩展类目录下,而不能直接加到jre根目录下。
b)将servlet-api.jar所在的目录添加到环境变量(CLASSPATH)中。比如我的tomcat目录中(D:\apache-tomcat-7.0.42\lib)有servlet-api.jar文件,则直接将该路径添加到系统环境变量中即可。
c)如果不想修改系统环境变量,则也可以在命令行编译时加上classpath,如:
javac -classpath D:\apache-tomcat-7.0.42\lib\servlet-api.jar MyServlet.java。
问题b): 为什么能找到java.io.*包?
原因:经查询,java.io.*包存放在< Java_Home >/jre/lib/下的rt.jar包中,而由上述类加载器部分可知rt.jar包在JVM启动时已经被加载过了,所以可以直接使用,无需再添加到系统环境变量中。
3、简单总结
1)Servlet类依赖于servlet-api.jar包,因此要编译和使用servlet,则必须确保程序能正确找到servlet-api.jar包。方法有两种:一是将servlet-api.jar添加到< Java_Home >/jre/lib/ext中。 二是将servlet-api.jar所在的目录添加到环境变量中。如果只是在命令行中编译servlet文件,则可以直接指定classpath,再编译即可。
2)Java内置类库中的类路径不需要配置到系统环境变量中,因为JVM启动时就已经加载过了。