本章要点
— 了解如何通过实现Servlet接口来编写Servlet
— 掌握ServletRequest和ServletResponse接口
— 掌握ServletConfig接口
— 掌握GenericServlet和HttpServlet抽象类
— 掌握HttpServletRequest和HttpServletResponse接口
— 掌握Servlet开发中一些方法和技巧的使用
— 熟悉Servlet异常
— 掌握Servlet上下文
— 掌握RequestDispatcher对象的使用
— 区分sendRedirect()和forward()方法的使用
从这一章开始,我 们将详细介绍Java服务器端编程的重要技术——Servlet。
2.1 Servlet API
这一节我们主要介绍一下开发Servlet需要用到的主要接口和类,这些接口和类的UML类图如图2-1所示。
2.1.1 Servlet接口
在Java语言中,我们已经了解了Java Applet(Java小应用程序)。它运行在客户端的浏览器中。Java Applet与Java Servlet有以下一些共同点。
— 它们都不是独立的应用程序,都没有main()方法。
— 它们都不是由用户或程序员直接调用,而是生存在容器中,由容器管理。Applet运行在浏览器中,Servlet运行在Servlet容器中。
— 它们都有生命周期,都包含了init()和destroy()方法。
当然,Applet与Servlet也有不同点。
— Applet具有图形界面,运行在客户端的浏览器中。
— Servlet没有图形界面,运行在服务器端的Servlet容器中。
要编写一个Applet,需要从java.applet.Applet类派生一个子类;和Applet类似,要编写一个Servlet,需要实现javax.servlet.Servlet接口,该接口定义了如下5个方法。
Ø public void init(ServletConfig config) throws ServletException
Ø public void service(ServletRequest req, ServletResponse res) throws ServletException, java.io.IOException
Ø public void destroy()
Ø public ServletConfig getServletConfig()
Ø public java.lang.String getServletInfo()
下面介绍一下这5个方法的作用。
— init():在Servlet实例化之后,Servlet容器会调用init()方法,来初始化该对象,主要是为了让Servlet对象在处理客户请求 前可以完成一些初始化的工作,例如,建立数据库的连接,获取配置信息等。对于每一个Servlet实例,init()方法只能被调用一次。init()方 法有一个类型为ServletConfig的参数,Servlet容器通过这个参数向Servlet传递配置信息。Servlet使用 ServletConfig对象从Web应用程序的配置信息中获取以名-值对形式提供的初始化参数。另外,在Servlet中,还可以通过 ServletConfig对象获取描述Servlet运行环境的ServletContext对象,使用该对象,Servlet可以和它的 Servlet容器进行通信。
— service():容器调用service()方法来处理客户端的请求。要注意的是,在service()方法被容器调用之前,必须确保init()方 法正确完成。容器会构造一个表示客户端请求信息的请求对象(类型为ServletRequest)和一个用于对客户端进行响应的响应对象(类型为 ServletResponse)作为参数传递给service()方法。在service()方法中,Servlet对象通过 ServletRequest对象得到客户端的相关信息和请求信息,在对请求进行处理后,调用ServletResponse对象的方法设置响应信息。
— destroy():当容器检测到一个Servlet对象应该从服务中被移除的时候,容器会调用该对象的destroy()方法,以便让Servlet对 象可以释放它所使用的资源,保存数据到持久存储设备中,例如,将内存中的数据保存到数据库中,关闭数据库的连接等。当需要释放内存或者容器关闭时,容器就 会调用Servlet对象的destroy()方法。在Servlet容器调用destroy()方法前,如果还有其他的线程正在service()方法 中执行,容器会等待这些线程执行完毕或等待服务器设定的超时值到达。一旦Servlet对象的destroy()方法被调用,容器不会再把其他的请求发送 给该对象。如果需要该Servlet再次为客户端服务,容器将会重新产生一个Servlet对象来处理客户端的请求。在destroy()方法调用之后, 容器会释放这个Servlet对象,在随后的时间内,该对象会被Java的垃圾收集器所回收。
— getServletConfig():该方法返回容器调用init()方法时传递给Servlet对象的ServletConfig对象,ServletConfig对象包含了Servlet的初始化参数。
— getServletInfo():返回一个String类型的字符串,其中包括了关于Servlet的信息,例如,作者、版本和版权。该方法返回的应该是纯文本字符串,而不是任何类型的标记(HTML、XML等)。
Servlet API包含在J2EE中,如果要查看Servlet API的文档,你需要下载J2EE(从J2EE 1.5开始改名为Java EE 5)SDK,Java EE 5 SDK的下载地址如下:http://java.sun.com/javaee/downloads/?intcmp=1282。
2.1.2 ServletRequest和ServletResponse
Servlet 由Servlet容器来管理,当客户请求到来时,容器创建一个ServletRequest对象,封装请求数据,同时创建一个 ServletResponse对象,封装响应数据。这两个对象将被容器作为service()方法的参数传递给Servlet,Servlet利用 ServletRequest对象获取客户端发来的请求数据,利用ServletResponse对象发送响应数据。
ServletRequest和ServletResponse接口都在javax.servlet包中定义,我们首先看一下ServletRequest接口中的常用方法。
Ø public java.lang.Object getAttribute(java.lang.String name)
返回以name为名字的属性的值。如果该属性不存在,这个方法将返回null。
Ø public java.util.Enumeration getAttributeNames()
返回请求中所有可用的属性的名字。如果在请求中没有属性,这个方法将返回一个空的枚举集合。
Ø public void removeAttribute(java.lang.String name)
移除请求中名字为name的属性。
Ø public void setAttribute(java.lang.String name, java.lang.Object o)
在请求中保存名字为name的属性。如果第二个参数o为null,那么相当于调用removeAttribute(name)。
Ø public java.lang.String getCharacterEncoding()
返回请求正文使用的字符编码的名字。如果请求没有指定字符编码,这个方法将返回null。
Ø public int getContentLength()
以字节为单位,返回请求正文的长度。如果长度不可知,这个方法将返回-1。
Ø public java.lang.String getContentType()
返回请求正文的MIME类型。如果类型不可知,这个方法将返回null。
Ø public ServletInputStream getInputStream()
返回一个输入流,使用该输入流以二进制方式读取请求正文的内容。javax.servlet.ServletInputStream是一个抽象类,继承自java.io.InputStream。
Ø public java.lang.String getLocalAddr()
返回接收到请求的网络接口的IP地址,这个方法是在Servlet 2.4规范中新增的方法。
Ø public java.lang.String getLocalName()
返回接收到请求的IP接口的主机名,这个方法是在Servlet 2.4规范中新增的方法。
Ø public int getLocalPort()
返回接收到请求的网络接口的IP端口号,这个方法是在Servlet 2.4规范中新增的方法。
Ø public java.lang.String getParameter(java.lang.String name)
返回请求中name参数的值。如果name参数有多个值,那么这个方法将返回值列表中的第一个值。如果在请求中没有找到这个参数,这个方法将返回null。
Ø public java.util.Enumeration getParameterNames()
返回请求中包含的所有的参数的名字。如果请求中没有参数,这个方法将返回一个空的枚举集合。
Ø public java.lang.String[] getParameterValues(java.lang.String name)
返回请求中name参数所有的值。如果这个参数在请求中并不存在,这个方法将返回null。
Ø public java.lang.String getProtocol()
返回请求使用的协议的名字和版本,例如:HTTP/1.1。
Ø public java.io.BufferedReader getReader() throws java.io.IOException
返回BufferedReader对象,以字符数据方式读取请求正文。
Ø public java.lang.String getRemoteAddr()
返回发送请求的客户端或者最后一个代理服务器的IP地址。
Ø public java.lang.String getRemoteHost()
返回发送请求的客户端或者最后一个代理服务器的完整限定名。
Ø public int getRemotePort()
返回发送请求的客户端或者最后一个代理服务器的IP源端口,这个方法是在Servlet 2.4规范中新增的方法。
Ø public RequestDispatcher getRequestDispatcher(java.lang.String path)
返回RequestDispatcher对象,作为path所定位的资源的封装。
Ø public java.lang.String getServerName()
返回请求发送到的服务器的主机名。
Ø public int getServerPort()
返回请求发送到的服务器的端口号。
Ø public void setCharacterEncoding (java.lang.String env) throws java.io.Unsupported EncodingException
覆盖在请求正文中所使用的字符编码的名字。
下面我们看一下ServletResponse接口中的常用方法:
Ø public void flushBuffer() throws java.io.IOException
强制把任何在缓存中的内容发送到客户端。
Ø public int getBufferSize()
返回实际用于响应的缓存的大小。如果没有使用缓存,这个方法将返回0。
Ø public java.lang.String getCharacterEncoding()
返回在响应中发送的正文所使用的字符编码(MIME字符集)。