Servlet之详解

曾经我们在学校里糊里糊涂的听老师说Tomcat是一个Servlet容器。

那么为什么你真正了解过么?

首先我们要明确几个概念性的问题。

J2EE--Java 2 Platform, Enterprise Edition(是一个为大企业主机级的计算类型而设计的Java平台)

J2EE的13种技术规范之一:servlet

Servlet

  servlet是用java编写的服务器端程序,主要功能在于交互式地浏览和修改数据,生成动态Web内容。狭义的Servlet是指Java语言实现的一个接口,广义的Servlet是指任何实现了这个Servlet接口的类,一般情况下,人们将Servlet理解为后者。

容    器

  java是面向对象的,那么容器就是一个特别的大的对象,一般这个容器里有一个Map类型属性,而这个Map来存放其他小对象,容器通过操纵Map来实现创建,管理,销毁等其他对象的生命周期。

  那么Servlet容器顾名思义就是来存放Servlet对象的容器。

Servlet『侠义』

    接口

Servlet『广义』

      实现类

 继承结构

  

 1 public interface Servlet {
 2 
 3     /**
 4      * Called by the servlet container to indicate to a servlet that the
 5      * servlet is being placed into service.
 6      * @param config  ServletConfig object containing the servlet's
 7      *     configuration and initialization parameters
 8      */
 9     public void init(ServletConfig config) throws ServletException;
10     
11     /**
12      *
13      * Returns a {@link ServletConfig} object, which contains that 
14      * initializes this servlet
15      */
16     public ServletConfig getServletConfig();
17     
18     /**
19      * Called by the servlet container to allow the servlet to respond to 
20      * a request.
21      */
22     public void service(ServletRequest req, ServletResponse res)
23     throws ServletException, IOException;
24 
25     /**
26      * Returns information about the servlet, such
27      * as author, version, and copyright.
28      * @return String containing servlet information
29      */
30     public String getServletInfo();
31     
32     /**
33      * Called by the servlet container to indicate to a servlet that the
34      * servlet is being taken out of service.
35      */
36     public void destroy();
37 }    
Servlet

 

Tomcat作为Servlet的容器,具体他是怎么做的呢?

apache-tomcat-8.5.23/config/web.xml 中默认定义了两种Serlvet:

  DefaultServlet extends HttpServlet

  JspServlet extends HttpServlet

这也就是为什么说Jsp也是一种servlet

 1     <servlet>
 2         <servlet-name>default</servlet-name>
 3         <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
 4         <init-param>
 5             <param-name>debug</param-name>
 6             <param-value>0</param-value>
 7         </init-param>
 8         <init-param>
 9             <param-name>listings</param-name>
10             <param-value>false</param-value>
11         </init-param>
12         <load-on-startup>1</load-on-startup>
13     </servlet>
14     <servlet>
15         <servlet-name>jsp</servlet-name>
16         <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
17         <init-param>
18             <param-name>fork</param-name>
19             <param-value>false</param-value>
20         </init-param>
21         <init-param>
22             <param-name>xpoweredBy</param-name>
23             <param-value>false</param-value>
24         </init-param>
25         <load-on-startup>3</load-on-startup>
26     </servlet>
web.xml

 ServletConfig顾名思义就是保存Servlet配置

具体有Servlet名字,应用本身,初始化的一些参数,和集合

 1 public interface ServletConfig {
 2 
 3     /**
 4      * @return the name of the servlet instance
 5      */
 6     public String getServletName();
 7 
 8     /**
 9      * Returns a reference to the {@link ServletContext} in which the caller is
10      * executing.
11      * @return a {@link ServletContext} object, used by the caller to interact
12      *         with its servlet container
13      */
14     public ServletContext getServletContext();
15 
16     /**
17      * Returns a <code>String</code> containing the value of the named
18      * initialization parameter, or <code>null</code> if the parameter does not
19      * exist.
20      */
21     public String getInitParameter(String name);
22 
23     /**
24      * @return an <code>Enumeration</code> of <code>String</code> objects
25      *         containing the names of the servlet's initialization parameters
26      */
27     public Enumeration<String> getInitParameterNames();
28 }
ServletConfig

 GenericServlet作为抽象的默认实现类,在继承了Servlet和ServletConfig的同时,

提供了一个没有参数的init()方法。

提供了2个log的方法,一个提供日志,一个提供异常记录。

 1 public abstract class GenericServlet implements Servlet, ServletConfig,
 2         java.io.Serializable {
 3 
 4     private static final long serialVersionUID = 1L;
 5 
 6     private transient ServletConfig config;
 7 
 8     public GenericServlet() {
 9         // NOOP
10     }
11 
12     /**
13      * A convenience method which can be overridden so that there's no need to
14      * call <code>super.init(config)</code>.
15      */
16     public void init() throws ServletException {
17         // NOOP by default
18     }
19 
20     /**
21      * Writes the specified message to a servlet log file, prepended by the
22      * servlet's name. See {@link ServletContext#log(String)}.
23      */
24     public void log(String msg) {
25         getServletContext().log(getServletName() + ": " + msg);
26     }
27 
28     /**
29      * Writes an explanatory message and a stack trace for a given
30      * <code>Throwable</code> exception to the servlet log file, prepended by
31      * the servlet's name. See {@link ServletContext#log(String, Throwable)}.
32      */
33     public void log(String message, Throwable t) {
34         getServletContext().log(getServletName() + ": " + message, t);
35     }
36 
37 }
GenericServlet

HttpServlet 作为次级抽象的实现类,是基于Http协议的Servlet父类。

他定义了7种请求方法(GET,POST,PUT,OPTIONS,DELETE,HEAD,TRACE);

实现了Servlet的Service方法,Service方法作为路由,通过获得请求方法来做相应的请求处理(doGET,doPOST等)

  1 public abstract class HttpServlet extends GenericServlet {
  2 
  3     private static final long serialVersionUID = 1L;
  4 
  5     private static final String METHOD_DELETE = "DELETE";
  6     private static final String METHOD_HEAD = "HEAD";
  7     private static final String METHOD_GET = "GET";
  8     private static final String METHOD_OPTIONS = "OPTIONS";
  9     private static final String METHOD_POST = "POST";
 10     private static final String METHOD_PUT = "PUT";
 11     private static final String METHOD_TRACE = "TRACE";
 12 
 13     private static final String HEADER_IFMODSINCE = "If-Modified-Since";
 14     private static final String HEADER_LASTMOD = "Last-Modified";
 15 
 16    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
 17         throws ServletException, IOException
 18     {
 19         String protocol = req.getProtocol();
 20         String msg = lStrings.getString("http.method_get_not_supported");
 21         if (protocol.endsWith("1.1")) {
 22             resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);
 23         } else {
 24             resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);
 25         }
 26     }
 27 
 28   protected void doPost(HttpServletRequest req, HttpServletResponse resp)
 29         throws ServletException, IOException {
 30 
 31         String protocol = req.getProtocol();
 32         String msg = lStrings.getString("http.method_post_not_supported");
 33         if (protocol.endsWith("1.1")) {
 34             resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);
 35         } else {
 36             resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);
 37         }
 38     }
 39 
 40     protected void service(HttpServletRequest req, HttpServletResponse resp)
 41         throws ServletException, IOException {
 42 
 43         String method = req.getMethod();
 44 
 45         if (method.equals(METHOD_GET)) {
 46             long lastModified = getLastModified(req);
 47             if (lastModified == -1) {
 48                 // servlet doesn't support if-modified-since, no reason
 49                 // to go through further expensive logic
 50                 doGet(req, resp);
 51             } else {
 52                 long ifModifiedSince;
 53                 try {
 54                     ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
 55                 } catch (IllegalArgumentException iae) {
 56                     // Invalid date header - proceed as if none was set
 57                     ifModifiedSince = -1;
 58                 }
 59                 if (ifModifiedSince < (lastModified / 1000 * 1000)) {
 60                     // If the servlet mod time is later, call doGet()
 61                     // Round down to the nearest second for a proper compare
 62                     // A ifModifiedSince of -1 will always be less
 63                     maybeSetLastModified(resp, lastModified);
 64                     doGet(req, resp);
 65                 } else {
 66                     resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
 67                 }
 68             }
 69 
 70         } else if (method.equals(METHOD_HEAD)) {
 71             long lastModified = getLastModified(req);
 72             maybeSetLastModified(resp, lastModified);
 73             doHead(req, resp);
 74 
 75         } else if (method.equals(METHOD_POST)) {
 76             doPost(req, resp);
 77 
 78         } else if (method.equals(METHOD_PUT)) {
 79             doPut(req, resp);
 80 
 81         } else if (method.equals(METHOD_DELETE)) {
 82             doDelete(req, resp);
 83 
 84         } else if (method.equals(METHOD_OPTIONS)) {
 85             doOptions(req,resp);
 86 
 87         } else if (method.equals(METHOD_TRACE)) {
 88             doTrace(req,resp);
 89 
 90         } else {
 91             //
 92             // Note that this means NO servlet supports whatever
 93             // method was requested, anywhere on this server.
 94             //
 95 
 96             String errMsg = lStrings.getString("http.method_not_implemented");
 97             Object[] errArgs = new Object[1];
 98             errArgs[0] = method;
 99             errMsg = MessageFormat.format(errMsg, errArgs);
100 
101             resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);
102         }
103     }
104 
105     @Override
106     public void service(ServletRequest req, ServletResponse res)
107         throws ServletException, IOException {
108 
109         HttpServletRequest  request;
110         HttpServletResponse response;
111 
112         try {
113             request = (HttpServletRequest) req;
114             response = (HttpServletResponse) res;
115         } catch (ClassCastException e) {
116             throw new ServletException("non-HTTP request or response");
117         }
118         service(request, response);
119     }
120 }
HttpServlet

而SpringMVC中的DispaticServlet就是继承了HttpServlet。

 DispaticServlet的具体请看Spring章节介绍。

 

 

  

posted on 2018-05-11 21:08  剑姬  阅读(163)  评论(0编辑  收藏  举报

导航