从网络的早期阶段开始,人们就但愿他们的网络服务器不只可以显示静态文档,通用网关接口(CGI) 扩展了服务器的能力,但其代价是增长了额外的处理进程。FastCGI则把外部CGI 处理进程同网络服务器更紧密地集成在一块儿,另外,对于专有的,诸如NSAPI 和ISAPI 这样的服务器API,它们直接把外部进程以服务器插件的形式集成到服务器中。如今有了Java servlets,它们的功能强大,能够快速替代你现有的CGI程序。html
什么是servlets?java
就象applet扩充了网络浏览器的能力同样,servlets这个Java部件,扩充了网络服务器的能力。对于任何种类的服务器端的处理,Servlets能够做为server-side includes使用或者做为CGI程序(在JavaSoft的Java Web server中能够做为插件)执行。 Servlets能够移植,不象CGI和专有的API模块,你能够利用Java的“编写一次,处处运行”的机制,在你的企业中配置网络应用程序。Servlets的运行也很稳固,在 servlet 中你建立了一个数据库链接,下一次你访问servlet时链接仍然存在,这同CGI 程序不同。Servlets也具备扩展性,因此你可使用面向对象的程序设计方法,来减小开发时间。Servlets能够运行在任何支持servlet的网络服务器上。目前,servlet SDK除了支持JavaSoft的Java Web server,还支持Netscape, Apache 和IIS,以及大量第三方的网络服务器。数据库
JSDK导游数组
为了建立servlets,你须要Java servlet SDK (JSDK),它能够从JavaSoft网站下载。JSDK包含诸如javax.servlet,javax.servlet.http等包,其中包含有你本身建立servlets时所须要的类和接口。对于sun.servlet 包来讲,其中包含了网络服务器用来运行servlets所须要的类。 (对Servlet的支持一般是经过服务器插件的形式)。一旦你有了JSDK,你只要建立GenericServlet类的子类,而且重载若干方法。GenericServlet 定义了你应该重载的三种主要方法: init(), service()和destroy()。浏览器
init() :初始化你的servlet,诸如打开数据库链接。缓存
destroy():在applet运行结束后,清除servlet 自身。服务器
service():每次调用servlet时,就调用service()方法。有两个对象 ServletRequest和ServletResponse须要传送给servlet,用于处理客户请求。网络
为了帮助处理基于Web 的事务,JSDK 在 javax.servlet.http包中有个HttpServlet类。HttpServlet是从GenericServlet中派生出来的,它提供了service()的一个实现,该实现用于自动处理GET, HEAD和POST的请求。多线程
HttpServlet类中的方法有doGet()和doPost()。一个典型的CGI servlet只须要实现doGet()和doPost()方法。 doGet()和doPost()的参数为HttpServletRequest和HttpServletResponse。app
HttpServletRequest是个接口,该接口提供了从客户的请求获取信息的一些方法。例如, getParameter()方法返回在客户请求中的关键字/值对(或者从请求串中取得,或者从POSTed数据中取得)。
HttpServletResponse提供了输出流,使得servlet把HTML格式的输出返回给客户。
基本Servlet代码
代替你的CGI
下面为一段能够取代CGI程序的基本的servlet代码。Servlet完成以下的简单事情:列出由HTML表单搜集的关键字/值对(key/value)。
BasicCGIServlet处理POST,也用一样处理GET。因此doPost()和doGet()都调用doService()。doService()能够在子类中重载,以实现更多特定的功能。
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import java.util.*;
public class BasicCGIServlet extends HttpServlet {
public BasicCGIServlet () {
super();
}
public void doPost (HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
doService(req, resp);
}
public void doGet (HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
doService(req, resp);
}
protected synchronized void doService (HttpServletRequest req,
HttpServletResponse resp) throws ServletException, IOException {
// get an output stream to write to
ServletOutputStream out = resp.getOutputStream();
// set the content type for the response
resp.setContentType (\\"text/html\\");
// optionally you should also set any special content-encoding
// and content length response headers, and return status codes
// write out the response!
out.println (\\"<body
bgcolor=\\\\"white\\\\">\\");
out.println (\\" \\");
out.println (\\"
\\");
for (Enumeration e = req.getParameterNames(); e.hasMoreElements(); ) {
String key = (String) e.nextElement();
out.println (\\"
\\");
}
out.println (\\"
Key | Value |
---|---|
\\" + key + \\" | \\" + req.getParameter(key) + \\" |
\\");
}
}
当调用req.getParameterNames()时,servlet请求对象读入表单数据,而且把它解码为关键字/值对(事实上,一旦第一次调用getParameterNames(),或者getParameterValues(),或者getParameter()
时,就进行解码)。 getParameterNames()返回全部关键字的列举。getParameter()返回同特定关键字相对应的值。当servlet请求被解析成关键字/值对时,每一个关键字的值保存在String数组中,以即可以处理一个关键字有多个值的状况。调用getParameterValues(),返回的是String数组,而调用 getParameter()后,则仅返回String数组中的第一个元素。
你也许会注意到doService()是个同步化的方法。这是由于servlets 一般是在多线程环境下运行的。由于网络服务器建立的servlet对象只有一个实例,因此servlet必须可以对同时发生的请求提供服务。所以,Servlets须要确保:这些请求在访问共享资源时保持同步。这些共享资源包括实例变量,数据库链接和文件流等。
运行你的servlet
一旦编写好servlet,而且编译成功以后,你能够把它放到网络服务器中servlet别名目录中。就同服务器中的cgi-bin别名目录的做用同样,任何放在servlet 目录中的文件,一旦被做为url的一部分被请求时,将被做为servlets执行。例如,BasicCGIServlet能够经过以下的url调用: http://mycompany.com/servlet/BasicCGIServlet。你既能够直接调用该url (而且传送给servlet一个请求关键字/值对的串),也能够经过HTML表单中的一个动做来调用。要了解更多的支持servlet的网络服务器的信息,请参阅JSDK中的有关文档信息。
进一步的用法
GenericServlet和 HttpServlet提供了一个构建servlets的固定的基类。经过重载service()方法,你能够在它们的基础上进行构建。例如,你能够加入对响应缓存的支持(请参见HttpServlet 中的getLastModified()),也能够加入对HTTP 1.1方法的支持,等等。你甚至能够构建一个扩展的模板引擎。(有谁真的喜欢在他们的程序中内置HTML代码呢?)
另一个用法是对JSDK进行扩展,使之除了支持标准的application/x-www-form-urlencoded mime 类型以外,还支持其余类型的表单编码。例如,你能够加入对multipart/form-data mime类型的支持,用于处理经过HTTP上载文件。接口方法getParameterNames(), getParameterValues()等等,都是在sun.servlet包中实现的,因此你须要配置JSDK ,以便加入这些支持。还有一种变通的方法,你能够本身实现有关方法,但那样作,就须要复制代码或者改变JSDK的语义。上面的这些方法都是可行的,可是没有哪种是天衣无缝的。
结论
如今你应该会本身建立Java servlets了,它们能够用来代替传统的Perl和C/C++ CGI程序。 Java的面向对象的特性和“编写一次,处处运行”的机制使得Java servlets的编写很简单。Servlet的稳固性,能够解决有关状态管理问题,而这些都是只用一次的CGI程序解决实际问题时一般会遇到的难题。 Servlets能够利用Java语言的全部功能,包括JDBC和RMI。因为大多数网络服务器都加入了对servlet的支持,Java将迅速成为开发企业级应用程序的一种可选语言。