回顾下Servlet(1) 2018-08-02

Servlet的核心是Servelt那么我们就以此展开进回顾

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和destory是生命周期的方法:

(1) init()方法:当第一次请求Servlet时,创建完servlet对象的时候调用。只会调用1次。说明Servelt是单例,成员变量有线程安全的问题。

(2) service()方法:每次发出请求时调用。调用n次,也就是说每发出一次请求都会调用一次service()。

(3) destroy()方法: 销毁servlet对象的时候调用。停止服务器或者重新部署web应用时销毁servlet对象。只会调用1次。

其他两个非生命周期的方法:

getServletInfo():获取Servelt的描述信息

getServletConfig():获取封装Servelt配置的ServeltConfig

 由于Servlet不是线程安全的,一个应用程序中所有的用户公用一个Servlet实例,因此不建议使用类级别的变量(只使用局部变量最好),除非是只读的或者java.utilconcurrent.atomic包中的成员。

其中涉及到的对象:
ServletRequest :

 对于每一个HTTP请求,servlet容器会创建一个封装了HTTP请求的ServletRequest实例传递给servlet的service方法。

ServletResponse:

 ServletResponse则表示一个Servlet响应,在调用service方法前,servelt容器首先创建一个ServeltResponse,并 将它作为第二个参数传给Service方法。其影藏了将响应发给浏览器的复杂性。

ServletConfig:

 ServletConfig封装可以通过@WebServlet或者web.xml传给一个Servlet的配置信息,以这种方式传递的每一条信息都称做初始化信息,初始化信息就是一个个K-V键值对。为了从一个Servlet内部获取某个初始参数的值,init方法中调用ServletConfig的getinitParameter方法或getinitParameterNames方法获取,除此之外,还可以通过getServletContext获取ServletContext对象。

ServletContext:

 ServletContext是代表了Servlet应用程序。每个Web应用程序只有一个context。在分布式环境中,一个应用程序同时部署到多个容器中,并且每台Java虚拟机都有一个ServletContext对象。有了ServletContext对象后,就可以共享能通过应用程序的所有资源访问的信息,促进Web对象的动态注册,共享的信息通过一个内部Map中的对象保存在ServiceContext中来实现。保存在ServletContext中的对象称作属性。

接着我们来看看Servlet的两个子类:

GenericServlet:

GenericServlet抽象类就是为了为我们省略一些模板代码,实现了Servlet和ServletConfig,完成了一下几个工作:
1、将init方法中的ServletConfig赋给一个类级变量,使的可以通过getServletConfig来获取。
2、为Servlet接口中的所有方法提供默认实现。
3、提供方法来包装ServletConfig中的方法。

HttpServelt

 HttpServlet继承了GenericServlet,HttpServletRequest/Response继承了覆盖了ServletRequest/Response,成为了新的Servlet请求和响应的代表。在HttpServlet中覆盖了GenericServlet的service方法,并用新的Servlet请求和响应代表作为参数添加了一个service方法:

//覆盖GenereicServlet中的service

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,HttpServletRequest,HttpServletResponse由于带有了HTTP的特性,因此除了ServletRequest,ServletResponse中的方法之外还增加了几个可以获取HTTP特性信息的方法。

  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;
                try {
                    ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
                } catch (IllegalArgumentException iae) {
                    // Invalid date header - proceed as if none was set
                    ifModifiedSince = -1;
                }
                if (ifModifiedSince < (lastModified / 1000 * 1000)) {
                    // 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);
        }
    }

Service方法会通过httpServeltRequest.getMethod()检查用来发送http请求的方法并调用doGet、doPut、doPost、doDelete、doHead、doTrace、doOptions这7种方法。这7种方法每一种都代表着一个http方法。

HTTP请求的方法:

HTTP/1.1协议中共定义了八种方法(有时也叫“动作”),来表明Request-URL指定的资源不同的操作方式

1、GET:请求指定的页面信息,并返回实体主体。
2、HEAD:类似于get请求,只不过返回的响应中没有响应体,用于获取消息头中的元信息
3、POST:向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源的建立和/或已有资源的修改。
4、PUT:向指定资源位置上传其最新内容。
5、DELETE:请求服务器删除Request-URL所标识的资源。
6、CONNECT:HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。
7、OPTIONS:返回服务器针对特定资源所支持的HTTP请求方法,也可以利用向web服务器发送‘*’的请求来测试服务器的功能性
8、TRACE:回显服务器收到的请求,主要用于测试或诊断。

你可能感兴趣的:(回顾下Servlet(1) 2018-08-02)