1.什么是servlet:
Java Servlet 是运行在 Web 服务器或应用服务器上的程序,它是作为来自 Web 浏览器或其他 HTTP 客户端的请求和 HTTP 服务器上的数据库或应用程序之间的中间层。
其实我的理解,servlet就是在 遵循JAVAEE规范的服务器上运行的一小段用java编写的小程序.
2.servlet的实现方式
1) 直接implements servlet
2) 继承GenericSevlet
3) 继承HttpServlet
先看一下目录结构
当我看到这个目录结构的时候很费解,扒源码发现那个facesServlet类是final修饰的
不太明白这样设计的目的,希望对这方面了解的能交流一下。
3.servlet 的生命周期
我们先看一下API的方法
public interface Servlet {
/**
* Called by the servlet container to indicate to a servlet that the
* servlet is being placed into service.
*
* <p>The servlet container calls the <code>init</code>
* method exactly once after instantiating the servlet.
* The <code>init</code> method must complete successfully
* before the servlet can receive any requests.
*
* <p>The servlet container cannot place the servlet into service
* if the <code>init</code> method
* <ol>
* <li>Throws a <code>ServletException</code>
* <li>Does not return within a time period defined by the Web server
* </ol>
*
*
* @param config a <code>ServletConfig</code> object
* containing the servlet's
* configuration and initialization parameters
*
* @exception ServletException if an exception has occurred that
* interferes with the servlet's normal
* operation
*
* @see UnavailableException
* @see #getServletConfig
*
*/
public void init(ServletConfig config) throws ServletException;
/**
*
* Returns a {@link ServletConfig} object, which contains
* initialization and startup parameters for this servlet.
* The <code>ServletConfig</code> object returned is the one
* passed to the <code>init</code> method.
*
* <p>Implementations of this interface are responsible for storing the
* <code>ServletConfig</code> object so that this
* method can return it. The {@link GenericServlet}
* class, which implements this interface, already does this.
*
* @return the <code>ServletConfig</code> object
* that initializes this servlet
*
* @see #init
*
*/
public ServletConfig getServletConfig();
/**
* Called by the servlet container to allow the servlet to respond to
* a request.
*
* <p>This method is only called after the servlet's <code>init()</code>
* method has completed successfully.
*
* <p> The status code of the response always should be set for a servlet
* that throws or sends an error.
*
*
* <p>Servlets typically run inside multithreaded servlet containers
* that can handle multiple requests concurrently. Developers must
* be aware to synchronize access to any shared resources such as files,
* network connections, and as well as the servlet's class and instance
* variables.
* More information on multithreaded programming in Java is available in
* <a href="http://java.sun.com/Series/Tutorial/java/threads/multithreaded.html">
* the Java tutorial on multi-threaded programming</a>.
*
*
* @param req the <code>ServletRequest</code> object that contains
* the client's request
*
* @param res the <code>ServletResponse</code> object that contains
* the servlet's response
*
* @exception ServletException if an exception occurs that interferes
* with the servlet's normal operation
*
* @exception IOException if an input or output exception occurs
*
*/
public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException;
/**
* Returns information about the servlet, such
* as author, version, and copyright.
*
* <p>The string that this method returns should
* be plain text and not markup of any kind (such as HTML, XML,
* etc.).
*
* @return a <code>String</code> containing servlet information
*
*/
public String getServletInfo();
/**
*
* Called by the servlet container to indicate to a servlet that the
* servlet is being taken out of service. This method is
* only called once all threads within the servlet's
* <code>service</code> method have exited or after a timeout
* period has passed. After the servlet container calls this
* method, it will not call the <code>service</code> method again
* on this servlet.
*
* <p>This method gives the servlet an opportunity
* to clean up any resources that are being held (for example, memory,
* file handles, threads) and make sure that any persistent state is
* synchronized with the servlet's current state in memory.
*
*/
public void destroy();
}
1)初始化 调用init()方法 并且创建servlet实例
servlet是单例多线程模式,在服务器启动之后,如果当客户端第一次请求的时候,开始运行init()方法 并创建servlet实例,多个请求会自动创建多线程,对于每个线程来说,servlet实例都是单例的。在servlet的生命周期中,init()方法仅执行一次。
如果想在服务器启动的时候就运行init()方法,创建servlet实例 ,需要在web.xml 里配置 增加 <load-on-startup>1</load-on-startup> 即可
<span style="white-space:pre"> </span><servlet>
<servlet-name>MyServlet</servlet-name>
<servlet-class>demo.com.cn.ssm.controller.UserServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>MyServlet</servlet-name>
<url-pattern>/myServlet</url-pattern>
</servlet-mapping>
2)调用 调用service() 方法
我们来看一下开发的时候 直接extends HttpServlet 这种方式 , HttpServlet 的 service() 方法源码
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException
{
String method = req.getMethod();
if (method.equals(METHOD_GET)) {
long lastModified = getLastModified(req);
if (lastModified == -1) {
// servlet doesn't support if-modified-since, no reason
// to go through further expensive logic
doGet(req, resp);
} else {
long ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
if (ifModifiedSince < lastModified) {
// If the servlet mod time is later, call doGet()
// Round down to the nearest second for a proper compare
// A ifModifiedSince of -1 will always be less
maybeSetLastModified(resp, lastModified);
doGet(req, resp);
} else {
resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
}
}
} else if (method.equals(METHOD_HEAD)) {
long lastModified = getLastModified(req);
maybeSetLastModified(resp, lastModified);
doHead(req, resp);
} else if (method.equals(METHOD_POST)) {
doPost(req, resp);
} else if (method.equals(METHOD_PUT)) {
doPut(req, resp);
} else if (method.equals(METHOD_DELETE)) {
doDelete(req, resp);
} else if (method.equals(METHOD_OPTIONS)) {
doOptions(req,resp);
} else if (method.equals(METHOD_TRACE)) {
doTrace(req,resp);
} else {
//
// Note that this means NO servlet supports whatever
// method was requested, anywhere on this server.
//
String errMsg = lStrings.getString("http.method_not_implemented");
Object[] errArgs = new Object[1];
errArgs[0] = method;
errMsg = MessageFormat.format(errMsg, errArgs);
resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);
}
}
它的实现实际就是判断不同的提交方式来跳转不同的方法,所有开发的时候我们一般不去重写这个方法,只需根据情况重写 doGet() 和 doPost()等
public class UserServlet extends HttpServlet{
/** */
private static final long serialVersionUID = -7018671373592622333L;
@Override
public void doGet(HttpServletRequest request,HttpServletResponse response){
System.out.println("doGet ~~~");
}
@Override
public void doPost(HttpServletRequest request,HttpServletResponse response){
System.out.println("doPost ~~");
}
@Override
public void init(ServletConfig servletConfig) throws ServletException {
System.out.println("初始化 servlet实例");
}
@Override
public void destroy() {
System.out.println("销毁 servlet实例");
}
}
3)销毁 调用 destroy() 方法
调用 destroy()方法,即 开始恢复一些初始化的变量,释放资源,线程正常退出等。之后等待JVM垃圾回收。
4)回收 等待JVM回收