天天看點

Servlet基礎總結1. 引言2. Servlet接口3. GenericServlet4. HttpServlet

文章目錄

  • 1. 引言
  • 2. Servlet接口
    • 2.1 一個簡單的Servlet應用程式
    • 2.2 ServletRequest
    • 2.3 ServletResponse
    • 2.4 ServletConfig
    • 2.5 ServletContext
  • 3. GenericServlet
  • 4. HttpServlet
    • 4.1 HttpServletRequest
    • 4.2 HttpServletResponse

1. 引言

Servlet技術的核心是Servlet,Servlet API有以下4個Java包:

  • javax.servlet
  • javax.servlet.http
  • javax.servlet.annotation
  • javax.servlet.descriptor

Servlet容器将Servlet類載入記憶體,并在Servlet執行個體上調用具體的方法,每個Servlet類型隻能有一個執行個體,按照慣例Servlet類的名稱要以Servlet作為字尾。

Servlet基礎總結1. 引言2. Servlet接口3. GenericServlet4. HttpServlet

javax.servlet.http中的主要類型

2. Servlet接口

package javax.servlet;

import java.io.IOException;

public interface Servlet {

  public 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();
}
           

init,service和destroy是生命周期方法,getServletInfo和getServetConfig是非生命周期方法。

  • init: 當Servlet第一次被請求時,Servlet會調用這個方法,執行初始化動作,Servlet容器會傳入一個ServletConfig,一般來說會将Servlet指派給一個類級别變量
  • service:每當請求Servlet時,Servlet容器會調用這個方法
  • destroy:當要銷毀Servlet時,Servlet會調用這個方法,用于回收資源并且在必要情況下同步記憶體的狀态到持久層中
  • getServletInfo: 傳回Servlet資訊,例如作者、版本等,注意此方法應該傳回的是純文字,而不是任何标記語言。
  • getServletConfig: 傳回init方法中傳入的ServletConfig,ServletConfig應該被儲存在servlet實作類中的類級變量中。

2.1 一個簡單的Servlet應用程式

package servlet;

import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;

/**
 * Servlet溫故而知新
 * @author littlemotor
 * @date 18.11.13
 */
@WebServlet(name = "MyServlet", urlPatterns = {"/my"})
public class MyServlet implements Servlet {

    ServletConfig servletConfig;


    /**
     * 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
     * @throws ServletException if an exception has occurred that
     *                          interferes with the servlet's normal
     *                          operation
     * @see UnavailableException
     * @see #getServletConfig
     */
    @Override
    public void init(ServletConfig config) throws ServletException {

        this.servletConfig = config;
    }

    /**
     * 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
     */
    @Override
    public ServletConfig getServletConfig() {
        return servletConfig;
    }

    /**
     * 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" target="_blank" rel="external nofollow" >
     * the Java tutorial on multi-threaded programming</a>.
     *
     * @param request the <code>ServletRequest</code> object that contains
     *            the client's request
     * @param response the <code>ServletResponse</code> object that contains
     *            the servlet's response
     * @throws ServletException if an exception occurs that interferes
     *                          with the servlet's normal operation
     * @throws IOException      if an input or output exception occurs
     */
    @Override
    public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html");
        PrintWriter writer = response.getWriter();
        writer.println("<html>" +
                "<head></head>" +
                "<body>hello,world</body>");
    }

    /**
     * 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
     */
    @Override
    public String getServletInfo() {
        return null;
    }

    /**
     * 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.
     */
    @Override
    public void destroy() {

    }
}

           

2.2 ServletRequest

對于每一個HTTP請求,Servlet容器都會建立一個ServletRequest執行個體,封裝了這個請求的資訊,并将他傳給Service方法

public String getParameter(String name);  //傳回指定參數名的值
public int getContentLength()             //請求主體的位元組數
public String getContentType()            //傳回主體的MIME類型
public String getProtocol()               //傳回HTTP請求的協定名稱和版本
           

2.3 ServletResponse

表示一個Servlet響應,在調用Servlet的Service方法之前,Servlet容器首先建立一個ServletResponse,并将它作為第二個參數傳給Service方法,ServletResponse隐藏了向浏覽器發送響應的複雜過程。

首先應該調用setContentType方法,設定響應内容類型為"text/html",調用getWriter方法傳回一個可以向用戶端發送文本的PrintWriter,還有getOutputStream方法,可以發送二進制資料。

2.4 ServletConfig

Servlet容器初始化Servlet時會向init方法傳入一個ServletConfig執行個體封裝了@WebServlet或者xml檔案傳遞給Servlet的配置資訊,初始參數為key-vealue形式存儲在HashMap中。

String getInitParameter(String name)  //擷取初始參數值
Enumeration<String> getInitParameterNames()  //傳回所有參數名稱枚舉類型
           

2.5 ServletContext

負責定義一系列和容器通訊的方法,例如擷取MIMI類型,排程器請求,寫日志。每個虛拟機的每個web應用隻有唯一的context,對于分布式web應用來說每個虛拟機都會有一個上下文,是以他們不能用來存儲全局資訊,可以用外部資料庫代替,ServletContext對象包含于ServletConfig當中。

3. GenericServlet

GenericServlet是Servlet接口的抽象類,完成了部分功能,通過繼承他隻需要重寫service方法即可。值得注意的是他有兩個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>.
     *
      public void init(ServletConfig config) throws ServletException {
	this.config = config;
	this.init();
    }


    /**
     * A convenience method which can be overridden so that there's no need
     * to call <code>super.init(config)</code>.
     *
     * <p>Instead of overriding {@link #init(ServletConfig)}, simply override
     * this method and it will be called by
     * <code>GenericServlet.init(ServletConfig config)</code>.
     * The <code>ServletConfig</code> object can still be retrieved via {@link
     * #getServletConfig}. 
     
    public void init() throws ServletException {
      //通過覆寫此方法,可以避免寫super.init(config)
    }
           

4. HttpServlet

HttpServlet類繼承自GenericServlet,并覆寫了原有的service方法,首先将原來的ServletRequest和ServletResponse轉換為HttpServletRequest和HttpServletResponse

/**
     * Dispatches client requests to the protected
     * <code>service</code> method. There's no need to
     * override this method.
     */
    @Override
    public void service(ServletRequest req, ServletResponse res)
        throws ServletException, IOException
    {
        HttpServletRequest  request;
        HttpServletResponse response;
        
        if (!(req instanceof HttpServletRequest &&
                res instanceof HttpServletResponse)) {
            throw new ServletException("non-HTTP request or response");
        }

        request = (HttpServletRequest) req;
        response = (HttpServletResponse) res;

        service(request, response);
    }
}
           

并通過重載service(HttpServletRequest,HttpServletResponse)方法,并調用以下方法之一,每一種方法都表示一個HTTP方法:

  • doGet
  • doPost
  • doHead
  • doPut
  • doTrace
  • doOptions
  • doDelete
/**
     * Receives standard HTTP requests from the public
     * <code>service</code> method and dispatches
     * them to the <code>do</code><i>XXX</i> methods defined in 
     * this class. This method is an HTTP-specific version of the 
     * {@link javax.servlet.Servlet#service} method. There's no
     * need to override this method.
     */
    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);
        }
    }
    
           

是以繼承HttpServlet類後隻要根據具體需要覆寫這七種方法之一就可以。

4.1 HttpServletRequest

定義的部分方法如下

Cookie[]  getCookies()  //傳回Cookie對象數組
String getHeader(String name)  //傳回頭檔案對應key name的value
HttpSession getSession()  //傳回與這個請求相關的會話對象,如果沒有就建立一個新的
String getMethod()  //傳回HTTP Method名稱
String getQueryString()  //傳回URL中查詢字元串
           

4.2 HttpServletResponse

定義的部分方法如下:

void addCookie(Cookie cookie)  //給響應對象添加一個cookie
void addHeader(String name,String value)  //給響應對象添加一個header
void sendRedirect(String location)  //給浏覽器發送一個重定向位址
           

繼續閱讀