Servlet的框架是由两个java包组成的
javax.servlet 和 javax.servlet.http.
在javax.servlet包中定义了所有的Servlet类都必须实现或扩展的通用接口和类。
在javax.servlet.http中定义了采用HTTP协议通信的HttpServlet类。
Servlet的框架的核心是javax.servlet.Servlet接口,所有的Servlet都必须实现这一接口。
在Servlet接口中定义了5个方法,其中有3个方法代表了Servlet的生命周期:
●init方法:负责初始化Servlet对象。
●service方法:负责响应客户的请求。
●destroy方法:当Servlet对象退出生命周期时,负责释放占用的资源。
Servlet的框架结构如下图所示
从上图可以看出,GenericServlet实现了Servlet接口,而HttpServlet扩展了GenericServlet。当用户开发自己的Servlet类时,Servlet类必须
扩展以下两个类中的一个。
●扩展GenericServlet类
如果Servlet扩展了GenericServlet类,则必须实现service方法,因为GenericServlet类中的service方法被声明为抽象方法。
声明形式如下
public abstract void service(javax.servlet.ServletRequest arg0, javax.servlet.ServletResponse arg1) throws javax.servlet.ServletException, java.io.IOException;
该方法有两个参数:ServletRequest和ServletResponse。Servlet容器将客户的请求信息封装在ServletRequest对象中,传给service方法。
service方法将响应客户的结果通过ServletResponse传给客户。
●扩展HttpServlet类
如果servlet类扩展了HttpServlet类,通常不必实现service方法,因为HttpServlet已经实现了service方法。声明如下
protected void service(javax.servlet.http.HttpServletRequest req, javax.servlet.http.HttpServletResponse resp) throws javax.servlet.ServletException, java.io.IOException;
在HttpServlet的service方法中,首先从HttpServletRequest对象中获取HTTP请求方式的信息,然后再根据请求方式调用相应的方法。
Get方式则调用doGet(),POST则调用doPost()。
提示:HTTP的请求方式包括DELETE,GET,OPTIONS,POST,PUT和TRACE.在HttpServlet类中分别提供了相应的方法。
HttpServletRequest:扩展了ServletRequest
HttpServletResponse:扩展了ServletResponse。
下面介绍ServletRequest和ServletResponse接口的作用以及它们的方法。
●ServletRequest接口
封装了客户请求信息,如客户请求方式,参数名和参数值,客户端正在使用的协议,以及发出客户请求的远程主机信息等。该接口还为
Servlet提供了直接以二进制数方式读取客户请求数据流的ServletInputStream.ServletRequest的子类可以为Servlet提供更多的与
特定协议相关的数据。例如,HttpServletRequest提供了读取HTTP Head信息的方法。
ServletRequest接口提供了一系列用于读取客户端的请求数据的方法。
getContentLength():返回请求正文的长度。如果请求正文的长度未知,则返回-1。
getContentType():获得请求正文的MIME类型。如果请求正文的类型未知,则返回null。
getInputStream():返回用于读取请求正文的输入流。
getLocalAddr() :返回服务器端的IP地址。
getLocalName():返回服务器端的主机名。
getLocalPort():返回服务器端的FTP端口号。
getParameter(String name):根据给定的请求参数名,返回来自客户请求中的匹配的请求参数值。关于请求参数的概念,参见本书第 1 章的 1.7 节(处理HTTP请求参数及HTML表单)。
getProtocol():返回客户端与服务器端通信所用的协议的名称及版本号。
getReader():返回用于读取字符串形式的请求正文的BufferedReader对象。
getRemoteAddr():返回客户端的IP地址。
getRemoteHost():返回客户端的主机名。
getRemotePort():返回客户端的FTP端口号。
此外,在ServletRequest接口中还定义了一组用于在请求范围内存取共享数据的方法,本书第5章的5.6.3节(请求范围)介绍了请求范围的概念。
setAttribute(String name, java.lang.Object object) :在请求范围内保存一个属性,参数name表示属性名,参数object表示属性值。
getAttribute(String name) :根据name参数给定的属性名,返回请求范围内的匹配的属性值。
removeAttribute(String name) :从请求范围内删除一个属性
●ServletResponse接口
在 Servlet 接口的 service(ServletRequest req, ServletResponse res)方法中有一个ServletResponse 类型的参数。Servlet 通过 ServletResponse 对象来生成响应结果。当Servlet 容器接收到客户端要求访问特定 Servlet 的请求时,容器会创建一个ServletResponse对象,并把它作为参数传给Servlet的service()方法。
在ServletResponse接口中定义了一系列与生成响应结果相关的方法。
setCharacterEncoding(String charset):设置响应正文的字符编码。响应正文的默认字符编码为ISO-8859-1。
setContentLength(int len):设置响应正文的长度。
setContentType(String type):设置响应正文的MIME类型。
getCharacterEncoding():返回响应正文的字符编码。
getContentType():返回响应正文的MIME类型。
setBufferSize(int size):设置用于存放响应正文数据的缓冲区的大小。
getBufferSize():获得用于存放响应正文数据的缓冲区的大小。
reset():清空缓冲区内的正文数据,并且清空响应状态代码及响应头。
resetBuffer():仅仅清空缓冲区内的正文数据,不清空响应状态代码及响应头。
flushBuffer():强制性地把缓冲区内的响应正文数据发送到客户端。
isCommitted():返回一个boolean类型的值。如果为true,表示缓冲区内的数据已经提交给客户,即数据已经发送到客户端。
getOutputStream():返回一个ServletOutputStream对象,Servlet用它来输出二进制的正文数据。
getWriter():返回一个PrintWriter对象,Servlet用它来输出字符串形式的正文数据。
ServletResponse中响应正文的默认MIME类型为text/plain,即纯文本类型。而HttpServletResponse中响应正文的默认MIME类型为text/html,即HTML文档类型。
Servlet 通过 ServletResponse 对象主要产生 HTTP 响应结果的正文部分。ServletResponse 的 getOutputStream()方法返回一个 ServletOutputStream 对象,Servlet可以利用ServletOutputStream来输出二进制的正文数据。ServletResponse的getWriter()方法返回一个PrintWriter对象,Servlet可以利用PrintWriter来输出字符串形式的正文数据。
为了提高输出数据的效率,ServletOutputStream和PrintWriter先把数据写到缓冲区内。当缓冲区内的数据被提交给客户后,ServletResponse的isCommitted()方法返回true。在以下几种情况下,缓冲区内的数据会被提交给客户,即数据被发送到客户端:
当缓冲区内的数据已满时,ServletOutputStream或PrintWriter会自动把缓冲区内的数据发送给客户端,并且清空缓冲区。
Servlet调用ServletResponse对象的flushBuffer()方法。
Servlet 调用 ServletOutputStream或 PrintWriter 对象的 flush()方法或 close()方法。
为了确保ServletOutputStream或PrintWriter 输出的所有数据都会被提交给客户,比较安全的做法是在所有数据都输出完毕后,调用 ServletOutputStream 或 PrintWriter的close()方法。
Tips
在 Tomcat 的实现中,如果 Servlet 的 service() 方法没有调用ServletOutputStream或PrintWriter的close()方法,那么Tomcat在调用完Servlet的service()方法后,会关闭ServletOutputStream或PrintWriter,从而确保Servlet输出的所有数据被提交给客户。
Servlet 还可通过 ServletResponse 对象的 setContentLength()、setContentType()和setCharacterEncoding()来分别设置响应正文的长度、MIME 类型和字符编码。在ServletResponse接口的实现类中,这些setXXX()方法会把相应的设置写到HTTP响应头中。
值得注意的是,如果要设置响应正文的 MIME 类型和字符编码,必须先调用ServletResponse 对象的 setContentType()和 setCharacterEncoding()方法,然后再调用ServletResponse的getOutputStream()或getWriter()方法,或者提交缓冲区内的正文数据。只有满足这样的操作顺序,所做的设置才能生效。