Servlet源码解读
此源码解读是基于servlet-api-2.5.
Servlet接口
Servlet接口是servlet包中最核心的接口,是所有Servlet必须直接或间接实现的接口。
public interface Servlet{
publi c void init(ServletConfig config) throws ServletException;
public ServletConfig getServletConfig();
public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException;
public String getServletInfo();
public void destroy();
}
每一次新建servlet,都要实现Servlet接口里的方法,为了减轻我们的负担,Servlet包里为我们提供了一个模板类GenericServlet。该抽象类继承自Servlet,并实现了若干通用的初始化过程。1
public abstract class GenericServlet
implements Servlet, ServletConfig, java.io.Serializable{}
抽象类GenericServlet中有一个成员变量ServletConfig:
private transient ServletConfig config;
该成员变量封装了Servlet的相关配置信息。初始化时,Servlet容器调用Servlet的init()方法,将读取到的web.xml中的对应的Servlet配置信息封装成ServletConfig作为参数,传递给init()函数。
/**
*
* Called by the servlet container to indicate to a servlet that the
* servlet is being placed into service. See {@link Servlet#init}.
*
* <p>This implementation stores the {@link ServletConfig}
* object it receives from the servlet container for later use.
* When overriding this form of the method, call
* <code>super.init(config)</code>.
*
* @param config the <code>ServletConfig</code> object
* that contains configutation
* information for this servlet
*
* @exception ServletException if an exception occurs that
* interrupts the servlet's normal
* operation
*
*
* @see UnavailableException
*
*/
public void init(ServletConfig config) throws ServletException {
this.config = config;
this.init();
}
同时,GenericServlet也实现了Servlet接口中定义的getServletConfig()方法,用以实现对ServletConfig config成员变量的访问。
ServletRequest和ServletRespouse接口
Servlet包中另外两个重要的接口是ServletRequest和ServletResponse。对于每个HTTP请求,Servlet容器都会封装一个ServletRequest对象传递给Servlet的service()方法,通过ServletRequest,可以获得一些请求相关的参数.ServletResponse则封装了一个Servlet的响应,通过ServletResponse可以设置一些参数和内容,进行返回。不过在返回之前,为了避免出现问题,通常会调用setContentType()方法,设置返回内容的类型,如果不设置,会默认以html的形式返回。
/**
* Sets the content type of the response being sent to
* the client, if the response has not been committed yet.
* The given content type may include a character encoding
* specification, for example, <code>text/html;charset=UTF-8</code>.
* The response's character encoding is only set from the given
* content type if this method is called before <code>getWriter</code>
* is called.
* <p>This method may be called repeatedly to change content type and
* character encoding.
* This method has no effect if called after the response
* has been committed. It does not set the response's character
* encoding if it is called after <code>getWriter</code>
* has been called or after the response has been committed.
* <p>Containers must communicate the content type and the character
* encoding used for the servlet response's writer to the client if
* the protocol provides a way for doing so. In the case of HTTP,
* the <code>Content-Type</code> header is used.
*
* @param type a <code>String</code> specifying the MIME
* type of the content
*
* @see #setLocale
* @see #setCharacterEncoding
* @see #getOutputStream
* @see #getWriter
*
*/
public void setContentType(String type);
ServletResponse中还定义了getWriter()方法,将文本返回给客户端的java.io.PrintWriter,在默认的情况下,PrintWriter对象使用ISO-8859-1编码,这可能会引起乱码.
/**
* Returns a <code>PrintWriter</code> object that
* can send character text to the client.
* The <code>PrintWriter</code> uses the character
* encoding returned by {@link #getCharacterEncoding}.
* If the response's character encoding has not been
* specified as described in <code>getCharacterEncoding</code>
* (i.e., the method just returns the default value
* <code>ISO-8859-1</code>), <code>getWriter</code>
* updates it to <code>ISO-8859-1</code>.
* <p>Calling flush() on the <code>PrintWriter</code>
* commits the response.
* <p>Either this method or {@link #getOutputStream} may be called
* to write the body, not both.
*
*
* @return a <code>PrintWriter</code> object that
* can return character data to the client
*
* @exception UnsupportedEncodingException
* if the character encoding returned
* by <code>getCharacterEncoding</code> cannot be used
*
* @exception IllegalStateException
* if the <code>getOutputStream</code>
* method has already been called for this
* response object
*
* @exception IOException
* if an input or output exception occurred
*
* @see #getOutputStream
* @see #setCharacterEncoding
*
*/
public PrintWriter getWriter() throws IOException;
ServletConfig和ServletContext接口
ServletConfig如上文介绍的,封装了对应Servlet的配置信息。
ServletContext则是一个全局的储存信息的空间。服务启动时,便会加载ServletContext,服务关闭时,才会释放ServletContext。2
HttpServlet、HttpServletRequest和HttpServletResponse
下面会提到三个新的接口或抽象类,下面先看看这三个类与上文提到的类有什么关系.
HttpServletRequest继承自ServletRequest
public interface HttpServletRequest extends ServletRequest
HttpServletResponse继承自ServletResponse
public interface HttpServletResponse extends ServletResponse
HttpServlet继承自GenericServlet
public abstract class HttpServlet extends GenericServlet
implements java.io.Serializable
HttpServlet重写了doGet()方法和doPost()方法,并且用HttpServletRequest和HttpServletResponse替换了ServletRequest和ServletResponse
HttpServletRequest继承自ServletRequest
public interface HttpServletRequest extends ServletRequest
HttpServletResponse继承自ServletResponse
public interface HttpServletResponse extends ServletResponse
总结
在servlet-api-2.5中,最主要的成员包括: Servlet、GenericServlet、ServletRequest、ServletResponse,以及在http包下的分别继承自以上若干类的HttpServlet、HttpServletRequest和HttpServletResponse。当然还包括以后提到的HttpSeesion和Cookie。