曾經咱們在學校裏糊里糊塗的聽老師說Tomcat是一個Servlet容器。java
那麼爲何你真正瞭解過麼?web
首先咱們要明確幾個概念性的問題。apache
J2EE--Java 2 Platform, Enterprise Edition(是一個爲大企業主機級的計算類型而設計的Java平臺)tomcat
J2EE的13種技術規範之一:servlet服務器
Servletless
servlet是用java編寫的服務器端程序,主要功能在於交互式地瀏覽和修改數據,生成動態Web內容。狹義的Servlet是指Java語言實現的一個接口,廣義的Servlet是指任何實現了這個Servlet接口的類,通常狀況下,人們將Servlet理解爲後者。jsp
容 器ide
java是面向對象的,那麼容器就是一個特別的大的對象,通常這個容器裏有一個Map類型屬性,而這個Map來存放其餘小對象,容器經過操縱Map來實現建立,管理,銷燬等其餘對象的生命週期。post
那麼Servlet容器顧名思義就是來存放Servlet對象的容器。this
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 }
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>
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 }
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 }
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 }
而SpringMVC中的DispaticServlet就是繼承了HttpServlet。
DispaticServlet的具體請看Spring章節介紹。