当前位置: 首页 > 图文教程 > Java技术 > J2EE > J2EE:孙鑫教你一步一步编写Java Servlet
现在我们开始编写一个最简单的Servlet,其功能就是向客户端输出一个字符串“Hello World”。实例的开发主要有下列步骤。
Step1:编写HelloWorldServlet类
例2-1 HelloWorldServlet.java
package org.sunxin.ch02.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class HelloWorldServlet implements Servlet
{
private ServletConfig config;
public void destroy(){}
public ServletConfig getServletConfig()
{
return config;
}
/**
* 该方法很少使用,因此返回null即可。
*/
public String getServletInfo()
{
return null;
}
/**
* ServletConfig对象由容器构造。容器在调用init()方法时,将其作为参数传给Servlet
*/
public void init(ServletConfig config) throws ServletException
{
this.config = config;
}
public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException
{
//得到PrintWriter对象。Servlet使用输出流来产生响应
PrintWriter out=res.getWriter();
//向客户端发送字符数据。
out.println("Hello World");
//关闭输出流
out.close();
}
}
在Servlet中,主要的方法是service(),当客户端请求到来时,Servlet容器将调用Servlet实例的service()方法对请求进行处理。我们在service()方法中,首先通过ServletResponse类中的getWriter()方法调用得到一个PrintWriter类型的输出流对象out,然后调用out对象的println()方法向客户端发送字符串“Hello World”,最后关闭out对象。
Servlet容器调用Servlet实例对请求的处理过程如图2-2所示。

图2-2 Servlet容器调用Servlet实例对请求进行处理的全过程
Step2:编译HelloWorldServlet.java
打开命令提示符,转到HelloWorldServlet.java所在的目录%CATALINA_HOME%\ webapps\ch02\src下,然后执行
javac -d . HelloWorldServlet.java
大多数情况下,你会看到如图2-3所示的画面。

图2-3 编译HelloWorldServlet.java的出错信息
产生这些错误的原因是Java编译器没有找到javax.servlet包中的类。要解决这个问题,我们需要让Java编译器知道Servlet API库所在的位置。Tomcat在其发行版中已经包含了Servlet API库,是以JAR文件的形式提供的,这个JAR文件的完整路径名是:
%CATALINA_HOME%\lib\servlet-api.jar
我们只需要在系统的CLASSPATH环境变量下添加这个JAR文件的路径名就可以了。
设置CLASSPATH环境变量的方法和第1章设置JAVA_HOME环境变量的方法是一样的,在笔者的机器上CLASSPATH环境变量的配置如下:
CLASSPATH=.;D:\OpenSource\apache-tomcat-
关闭刚才打开的命令提示符窗口,重新打开一个新的命令提示符窗口,进入HelloWorldServlet.java所在的目录,再次执行:
javac -d . HelloWorldServlet.java
生成org\sunxin\ch02\servlet目录结构,以及在servlet子目录中的HelloWorldServlet.class文件。
Step3:部署HelloWorldServlet
Servlet是Web应用程序中的一个组件。一个Web应用程序是由一组Servlet、HTML页面、类,以及其他的资源组成的运行在Web服务器上的完整的应用程序,以一种结构化的有层次的目录形式存在。组成Web应用程序的这些资源文件要部署在相应的目录层次中,根目录代表了整个Web应用程序的根。我们通常是将Web应用程序的目录放到%CATALINA_HOME%\webapps目录下,在webapps目录下的每一个子目录都是一个独立的Web应用程序,子目录的名字就是Web应用程序的名字,也称为Web应用程序的上下文根。用户通过Web应用程序的上下文根来访问Web应用程序中的资源,如图2-4所示。
如果你要新建一个Web应用程序,可以在webapps目录下先建一个目录,在这个例子中,我们所建的目录是ch02,作为第一个Web应用程序的上下文根。Java开发的Web应用程序需要遵照一定的目录层次结构,在Servlet规范中定义了Web应用程序的目录层次结构,如图2-5所示。

图2-4 多个Web应用程序和上下文根 图2-5 Web应用程序的目录层次结构
Web应用程序的目录层次结构如表2-1所示。
表2-1 Web应用程序的目录层次结构
| 目 录 | 描 述 |
| \ch02 | Web应用程序的根目录,属于此Web应用程序的所有文件都存放在这个目录下 |
| \ch02\WEB-INF | 存放Web应用程序的部署描述符文件web.xml |
| \ch02\WEB-INF\classes | 存放Servlet和其他有用的类文件 |
| \ch02\WEB-INF\lib | 存放Web应用程序需要用到的JAR文件,这些JAR文件中可以包含Servlet、Bean和其他有用的类文件 |
| \ch02\WEB-INF\web.xml | web.xml文件包含Web应用程序的配置和部署信息 |
从表2-1中可以看到,WEB-INF目录下的classes和lib目录都可以存放Java的类文件,在Servlet容器运行时,Web应用程序的类加载器将首先加载classes目录下的,其次才是lib目录下的类。如果这两个目录下存在同名的类,起作用的将是classes目录下的类。
在表2-1中,我们还可以看到一个特殊的目录WEB-INF,注意在书写时不要写错,所有字母都要大写。说这个目录特殊,是因为这个目录并不属于Web应用程序可以访问的上下文路径的一部分,对客户端来说,这个目录是不可见的。如果你将index.html文件放到WEB-INF目录下,对于客户端是无法通过下面的方式访问到这个文件的:
http://localhost:8080/ch02/WEB-INF/index.html
不过,WEB-INF目录下的内容对于Servlet代码是可见的,在Servlet代码中可以通过调用ServletContext对象中的getResource()或者getResourceAsStream()方法来访问WEB-INF目录下的资源,也可以使用RequestDispatcher调用(参见第2.6节)将WEB-INF目录下的内容呈现给客户端。
如果我们想要在Servlet代码中访问保存在文件中的配置信息,而又不希望这些配置信息被客户端访问到,就可以把这个文件放到WEB-INF目录下。
在%CATALINA_HOME%\webapps\ch02目录下新建一个目录WEB-INF,进入WEB-INF目录,新建一个classes目录,整个目录结构是:
%CATALINA_HOME%\webapps\ch02\WEB-INF\classes
将编译生成的HelloWorldServlet.class文件连同所在的包一起放到WEB-INF\classes目录下。
接下来,我们需要部署这个Servlet,Web应用程序的配置和部署是通过web.xml文件来完成的。web.xml文件被称为Web应用程序的部署描述符,它可以包含如下的配置和部署信息:
? ServletContext的初始化参数
? Session的配置
? Servlet/JSP的定义和映射
? 应用程序生命周期监听器类
? 过滤器定义和过滤器映射
? MIME类型映射
? 欢迎文件列表
? 错误页面
? 语言环境和编码映射
? 声明式安全配置
? JSP配置
我们所编写的web.xml文件必须是格式良好的XML。用记事本或者UltraEdit等文本编辑工具编写web.xml文件,内容如例2-2所示。
例2-2 web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<servlet>
<servlet-name>HelloWorldServlet</servlet-name>
<servlet-class>
org.sunxin.ch02.servlet.HelloWorldServlet
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HelloWorldServlet</servlet-name>
<url-pattern>/helloworld</url-pattern>
</servlet-mapping>
</web-app>
第一行是XML声明,接下来在根元素<web-app>上声明了使用的XML Schema的版本。这段代码是固定的,你无须记忆它,只要知道复制/粘贴就可以了。
注意代码中以粗体显示的部分,这部分代码使用了<servlet>和<servlet-mapping>元素,以及它们的子元素来部署HelloWorldServlet。在web.xml文件中,可以包含多个<servlet>和<servlet-mapping>元素,用于部署多个Servlet。
<servlet>元素用于声明Servlet,<servlet-name>子元素用于指定Servlet的名字,在同一个Web应用程序中,每一个Servlet的名字必须是唯一的,该元素的内容不能为空。<servlet-class>子元素用于指定Servlet类的完整限定名(如果有包名,要同时给出包名)。
<servlet-mapping>元素用于在Servlet和URL样式之间定义一个映射。它的子元素<servlet-name>指定的Servlet名字必须和<servlet>元素中的子元素<servlet-name>给出的名字相同。<url-pattern>子元素用于指定对应于Servlet的URL路径,该路径是相对于Web应用程序上下文根的路径。
经过这样的配置之后,我们可以在浏览器的地址栏中输入http://localhost:8080/ ch02/helloworld来访问HelloWorldServlet。当Servlet容器接收到/ch02/helloworld的请求后,就会将发送给ch02 Web应用程序的Context(参见第1.6节),ch02 Web应用程序的Context首先移除该Web应用程序上下文路径的前缀/ch02,然后将剩余部分与web.xml文件中配置的<url-pattern>元素的内容相比较,找到对应的Servlet名字为HelloWorldServlet,再根据这个名字找到HelloWorldServlet类,进而实例化这个类,对请求进行处理。
将编写好的web.xml文件保存到%CATALINA_HOME%\webapps\ch02\WEB-INF目录下。读者也可以将%CATALINA_HOME%\webapps\ROOT\WEB-INF目录下的web.xml复制一份,存放到%CATALINA_HOME%\webapps\ch02\WEB-INF目录下,这个文件的内容如下:
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun. com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<display-name>Welcome to Tomcat</display-name>
<description>
Welcome to Tomcat
</description>
</web-app>
然后编辑这个文件,添加HelloWorldServlet的配置,如下所示:
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun. com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<display-name>Welcome to Tomcat</display-name>
<description>
Welcome to Tomcat
</description>
<servlet>
<servlet-name>HelloWorldServlet</servlet-name>
<servlet-class>
org.sunxin.ch02.servlet.HelloWorldServlet
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HelloWorldServlet</servlet-name>
<url-pattern>/helloworld</url-pattern>
</servlet-mapping>
</web-app>
%CATALINA_HOME%\webapps\ROOT目录是Tomcat默认的Web应用程序的起始路径,当我们输入http://localhost:8080/时,访问的就是该目录下的Web应用程序资源。如果你将本例的Servlet部署在该目录下,访问时只需输入http://localhost:8080/helloworld即可。
Step4:访问HelloWorldServlet
当部署好Servlet之后,对客户端来说,访问Servlet和访问静态页面没有什么区别。为了让读者对Servlet的访问有一个较好的感性认识,在这里我们通过两种方式来访问SimpleHello。
第一种方式,我们通过telnet工具来访问本例中的Servlet,具体操作步骤,读者可以参看附录B。
首先确保Tomcat服务器正常启动了。打开命令提示符,输入
telnet localhost 8080
回车后,输入
GET /ch02/helloworld HTTP/1.1
Host: localhost
注意书写与空格。然后连续两个回车,你将看到如图2-6所示的画面。
第二种方式,通过浏览器访问Servlet,打开IE,在地址栏中输入:
http://localhost:8080/ch02/helloworld
注意在helloworld后面不要加斜杠(/),然后回车,你将看到如图2-7所示的画面。

图2-6 使用telnet工具与Servlet交互的信息 图2-7 使用IE访问HelloWorldServlet
在访问Servlet和JSP的时候,Servlet的名字和JSP的文件名都是区分大小写的,对于本例 来 说,如果你输入的是HelloWorld,那么Tomcat服务器会给出404的错误代码,提示“The requested resource (/ch02/HelloWorld) is not available”。
评论 (0) All