Servlet详解

逃离我推掉我的手 2022-04-10 06:53 303阅读 0赞

越学到后面,越觉得基础重要,慢慢开始补充基础,因此这篇博客主要备忘一下扎实servlet的相关知识。

1.首先如何查看servlet的源码。

  1. servlet的源码在tomcat服务器的源代码中([点击下载][Link 1]) **[apache-tomcat-8.0.53-src.zip][Link 1]**
  2. 非源码的名字叫 **apache-tomcat-8.0.53.zip** 注意一下 没有src,去官网下载的时候请注意。

如何导源码包进eclipse 请看这篇博客:

https://blog.csdn.net/qq_29519041/article/details/82468100

结构图:

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzI5NTE5MDQx_size_16_color_FFFFFF_t_70

2.查看servlet源码的HttpServlet**类**

随便写一个类继承HttpServlet,按住ctrl点击HttpServlet

20181228145019228.png20181228145041466.png

点击Declaration为查看这个类的代码,点击Implementation为查看所有继承这个类的子类。

来看一下HttpServlet这个类的源码

  1. public abstract class HttpServlet extends GenericServlet {
  2. private static final long serialVersionUID = 1L;
  3. private static final String METHOD_DELETE = "DELETE";
  4. private static final String METHOD_HEAD = "HEAD";
  5. private static final String METHOD_GET = "GET";
  6. private static final String METHOD_OPTIONS = "OPTIONS";
  7. private static final String METHOD_POST = "POST";
  8. private static final String METHOD_PUT = "PUT";
  9. private static final String METHOD_TRACE = "TRACE";
  10. private static final String HEADER_IFMODSINCE = "If-Modified-Since";
  11. private static final String HEADER_LASTMOD = "Last-Modified";
  12. private static final String LSTRING_FILE =
  13. "javax.servlet.http.LocalStrings";
  14. private static final ResourceBundle lStrings =
  15. ResourceBundle.getBundle(LSTRING_FILE);
  16. public HttpServlet() {
  17. // NOOP
  18. }
  19. protected void doGet(HttpServletRequest req, HttpServletResponse resp)
  20. throws ServletException, IOException
  21. {
  22. String protocol = req.getProtocol();
  23. String msg = lStrings.getString("http.method_get_not_supported");
  24. if (protocol.endsWith("1.1")) {
  25. resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);
  26. } else {
  27. resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);
  28. }
  29. }
  30. protected long getLastModified(HttpServletRequest req) {
  31. return -1;
  32. }
  33. protected void doHead(HttpServletRequest req, HttpServletResponse resp)
  34. throws ServletException, IOException {
  35. if (DispatcherType.INCLUDE.equals(req.getDispatcherType())) {
  36. doGet(req, resp);
  37. } else {
  38. NoBodyResponse response = new NoBodyResponse(resp);
  39. doGet(req, response);
  40. response.setContentLength();
  41. }
  42. }
  43. protected void doPost(HttpServletRequest req, HttpServletResponse resp)
  44. throws ServletException, IOException {
  45. String protocol = req.getProtocol();
  46. String msg = lStrings.getString("http.method_post_not_supported");
  47. if (protocol.endsWith("1.1")) {
  48. resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);
  49. } else {
  50. resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);
  51. }
  52. }
  53. protected void doPut(HttpServletRequest req, HttpServletResponse resp)
  54. throws ServletException, IOException {
  55. String protocol = req.getProtocol();
  56. String msg = lStrings.getString("http.method_put_not_supported");
  57. if (protocol.endsWith("1.1")) {
  58. resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);
  59. } else {
  60. resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);
  61. }
  62. }
  63. protected void doDelete(HttpServletRequest req,
  64. HttpServletResponse resp)
  65. throws ServletException, IOException {
  66. String protocol = req.getProtocol();
  67. String msg = lStrings.getString("http.method_delete_not_supported");
  68. if (protocol.endsWith("1.1")) {
  69. resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);
  70. } else {
  71. resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);
  72. }
  73. }
  74. private static Method[] getAllDeclaredMethods(Class<?> c) {
  75. if (c.equals(javax.servlet.http.HttpServlet.class)) {
  76. return null;
  77. }
  78. Method[] parentMethods = getAllDeclaredMethods(c.getSuperclass());
  79. Method[] thisMethods = c.getDeclaredMethods();
  80. if ((parentMethods != null) && (parentMethods.length > 0)) {
  81. Method[] allMethods =
  82. new Method[parentMethods.length + thisMethods.length];
  83. System.arraycopy(parentMethods, 0, allMethods, 0,
  84. parentMethods.length);
  85. System.arraycopy(thisMethods, 0, allMethods, parentMethods.length,
  86. thisMethods.length);
  87. thisMethods = allMethods;
  88. }
  89. return thisMethods;
  90. }
  91. protected void doOptions(HttpServletRequest req,
  92. HttpServletResponse resp)
  93. throws ServletException, IOException {
  94. Method[] methods = getAllDeclaredMethods(this.getClass());
  95. boolean ALLOW_GET = false;
  96. boolean ALLOW_HEAD = false;
  97. boolean ALLOW_POST = false;
  98. boolean ALLOW_PUT = false;
  99. boolean ALLOW_DELETE = false;
  100. boolean ALLOW_TRACE = true;
  101. boolean ALLOW_OPTIONS = true;
  102. for (int i=0; i<methods.length; i++) {
  103. Method m = methods[i];
  104. if (m.getName().equals("doGet")) {
  105. ALLOW_GET = true;
  106. ALLOW_HEAD = true;
  107. }
  108. if (m.getName().equals("doPost"))
  109. ALLOW_POST = true;
  110. if (m.getName().equals("doPut"))
  111. ALLOW_PUT = true;
  112. if (m.getName().equals("doDelete"))
  113. ALLOW_DELETE = true;
  114. }
  115. String allow = null;
  116. if (ALLOW_GET)
  117. allow=METHOD_GET;
  118. if (ALLOW_HEAD)
  119. if (allow==null) allow=METHOD_HEAD;
  120. else allow += ", " + METHOD_HEAD;
  121. if (ALLOW_POST)
  122. if (allow==null) allow=METHOD_POST;
  123. else allow += ", " + METHOD_POST;
  124. if (ALLOW_PUT)
  125. if (allow==null) allow=METHOD_PUT;
  126. else allow += ", " + METHOD_PUT;
  127. if (ALLOW_DELETE)
  128. if (allow==null) allow=METHOD_DELETE;
  129. else allow += ", " + METHOD_DELETE;
  130. if (ALLOW_TRACE)
  131. if (allow==null) allow=METHOD_TRACE;
  132. else allow += ", " + METHOD_TRACE;
  133. if (ALLOW_OPTIONS)
  134. if (allow==null) allow=METHOD_OPTIONS;
  135. else allow += ", " + METHOD_OPTIONS;
  136. resp.setHeader("Allow", allow);
  137. }
  138. protected void doTrace(HttpServletRequest req, HttpServletResponse resp)
  139. throws ServletException, IOException
  140. {
  141. int responseLength;
  142. String CRLF = "\r\n";
  143. StringBuilder buffer = new StringBuilder("TRACE ").append(req.getRequestURI())
  144. .append(" ").append(req.getProtocol());
  145. Enumeration<String> reqHeaderEnum = req.getHeaderNames();
  146. while( reqHeaderEnum.hasMoreElements() ) {
  147. String headerName = reqHeaderEnum.nextElement();
  148. buffer.append(CRLF).append(headerName).append(": ")
  149. .append(req.getHeader(headerName));
  150. }
  151. buffer.append(CRLF);
  152. responseLength = buffer.length();
  153. resp.setContentType("message/http");
  154. resp.setContentLength(responseLength);
  155. ServletOutputStream out = resp.getOutputStream();
  156. out.print(buffer.toString());
  157. out.close();
  158. return;
  159. }
  160. protected void service(HttpServletRequest req, HttpServletResponse resp)
  161. throws ServletException, IOException {
  162. String method = req.getMethod();
  163. if (method.equals(METHOD_GET)) {
  164. long lastModified = getLastModified(req);
  165. if (lastModified == -1) {
  166. // servlet doesn't support if-modified-since, no reason
  167. // to go through further expensive logic
  168. doGet(req, resp);
  169. } else {
  170. long ifModifiedSince;
  171. try {
  172. ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
  173. } catch (IllegalArgumentException iae) {
  174. // Invalid date header - proceed as if none was set
  175. ifModifiedSince = -1;
  176. }
  177. if (ifModifiedSince < (lastModified / 1000 * 1000)) {
  178. // If the servlet mod time is later, call doGet()
  179. // Round down to the nearest second for a proper compare
  180. // A ifModifiedSince of -1 will always be less
  181. maybeSetLastModified(resp, lastModified);
  182. doGet(req, resp);
  183. } else {
  184. resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
  185. }
  186. }
  187. } else if (method.equals(METHOD_HEAD)) {
  188. long lastModified = getLastModified(req);
  189. maybeSetLastModified(resp, lastModified);
  190. doHead(req, resp);
  191. } else if (method.equals(METHOD_POST)) {
  192. doPost(req, resp);
  193. } else if (method.equals(METHOD_PUT)) {
  194. doPut(req, resp);
  195. } else if (method.equals(METHOD_DELETE)) {
  196. doDelete(req, resp);
  197. } else if (method.equals(METHOD_OPTIONS)) {
  198. doOptions(req,resp);
  199. } else if (method.equals(METHOD_TRACE)) {
  200. doTrace(req,resp);
  201. } else {
  202. //
  203. // Note that this means NO servlet supports whatever
  204. // method was requested, anywhere on this server.
  205. //
  206. String errMsg = lStrings.getString("http.method_not_implemented");
  207. Object[] errArgs = new Object[1];
  208. errArgs[0] = method;
  209. errMsg = MessageFormat.format(errMsg, errArgs);
  210. resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);
  211. }
  212. }
  213. private void maybeSetLastModified(HttpServletResponse resp,
  214. long lastModified) {
  215. if (resp.containsHeader(HEADER_LASTMOD))
  216. return;
  217. if (lastModified >= 0)
  218. resp.setDateHeader(HEADER_LASTMOD, lastModified);
  219. }
  220. @Override
  221. public void service(ServletRequest req, ServletResponse res)
  222. throws ServletException, IOException {
  223. HttpServletRequest request;
  224. HttpServletResponse response;
  225. try {
  226. request = (HttpServletRequest) req;
  227. response = (HttpServletResponse) res;
  228. } catch (ClassCastException e) {
  229. throw new ServletException("non-HTTP request or response");
  230. }
  231. service(request, response);
  232. }
  233. }

去掉了注释部分(注释超多)

它有13个方法分别为




























































方法 解释或相关博客
public HttpServlet()  空参构造
protected void doGet(HttpServletRequest req, HttpServletResponse resp) 处理get方式的请求
protected long getLastModified(HttpServletRequest req)

获取最后的修改时间 (所请求的资源最后的修改时间)

比较优秀的解释博客:

http://blog.51cto.com/357712148/2104610

protected void doHead(HttpServletRequest req, HttpServletResponse resp) https://blog.csdn.net/qq_29519041/article/details/85329453
protected void doPost(HttpServletRequest req, HttpServletResponse resp) https://blog.csdn.net/qq_29519041/article/details/85331058
protected void doPut(HttpServletRequest req, HttpServletResponse resp) https://blog.csdn.net/qq_29519041/article/details/85331472
protected void doDelete(HttpServletRequest req,HttpServletResponse resp) https://blog.csdn.net/qq_29519041/article/details/85331647
private static Method[] getAllDeclaredMethods(Class<?> c) 该方法是获取本类中的所有方法,包括私有的(private、protected、默认以及public)的方法。
protected void doOptions(HttpServletRequest req,HttpServletResponse resp) https://blog.csdn.net/qq_29519041/article/details/85332183
protected void doTrace(HttpServletRequest req, HttpServletResponse resp) https://blog.csdn.net/qq_29519041/article/details/85332272
protected void service(HttpServletRequest req, HttpServletResponse resp)

主要作用是对针对不同的请求调用不同的方法来处理,service方法会被自动调用,因此覆盖service方法的时候,需要在service方法里调用其他doXXX方法,不然其他方法将不会被调用,一般我们不用重写service方法,只需要重写get和post方法即可。

https://blog.csdn.net/qq_29519041/article/details/85332367

private void maybeSetLastModified(HttpServletResponse resp,long lastModified) 如果尚未设置Last-Modified实体标头字段,如果它还没有被设置并且这个值是有用的,则设置该字段。在doGet之前调用,以确保在写入响应数据之前设置头。子类可能已经设置了这个标头,需要进行检查。
public void service(ServletRequest req, ServletResponse res)

它的主要作用是把请求和响应的类型(做强转强转不了报错)

ServletRequest req   =>  HttpServletRequest  request;

ServletResponse res  => HttpServletResponse response;

3.GenericServlet类

他的作用如注释所说:

定义通用的、独立于协议的servlet。要编写用于Web的HTTP servlet,请改为{@link javax.servlet.http.HttpServlet}。

  1. package javax.servlet;
  2. import java.io.IOException;
  3. import java.util.Enumeration;
  4. /**
  5. * Defines a generic, protocol-independent servlet. To write an HTTP servlet for
  6. * use on the Web, extend {@link javax.servlet.http.HttpServlet} instead.
  7. * <p>
  8. * <code>GenericServlet</code> implements the <code>Servlet</code> and
  9. * <code>ServletConfig</code> interfaces. <code>GenericServlet</code> may be
  10. * directly extended by a servlet, although it's more common to extend a
  11. * protocol-specific subclass such as <code>HttpServlet</code>.
  12. * <p>
  13. * <code>GenericServlet</code> makes writing servlets easier. It provides simple
  14. * versions of the lifecycle methods <code>init</code> and <code>destroy</code>
  15. * and of the methods in the <code>ServletConfig</code> interface.
  16. * <code>GenericServlet</code> also implements the <code>log</code> method,
  17. * declared in the <code>ServletContext</code> interface.
  18. * <p>
  19. * To write a generic servlet, you need only override the abstract
  20. * <code>service</code> method.
  21. */
  22. public abstract class GenericServlet implements Servlet, ServletConfig,
  23. java.io.Serializable {
  24. private static final long serialVersionUID = 1L;
  25. private transient ServletConfig config;
  26. /**
  27. * Does nothing. All of the servlet initialization is done by one of the
  28. * <code>init</code> methods.
  29. */
  30. public GenericServlet() {
  31. // NOOP
  32. }
  33. /**
  34. * Called by the servlet container to indicate to a servlet that the servlet
  35. * is being taken out of service. See {@link Servlet#destroy}.
  36. */
  37. @Override
  38. public void destroy() {
  39. // NOOP by default
  40. }
  41. /**
  42. * Returns a <code>String</code> containing the value of the named
  43. * initialization parameter, or <code>null</code> if the parameter does not
  44. * exist. See {@link ServletConfig#getInitParameter}.
  45. * <p>
  46. * This method is supplied for convenience. It gets the value of the named
  47. * parameter from the servlet's <code>ServletConfig</code> object.
  48. *
  49. * @param name
  50. * a <code>String</code> specifying the name of the
  51. * initialization parameter
  52. * @return String a <code>String</code> containing the value of the
  53. * initialization parameter
  54. */
  55. @Override
  56. public String getInitParameter(String name) {
  57. return getServletConfig().getInitParameter(name);
  58. }
  59. /**
  60. * Returns the names of the servlet's initialization parameters as an
  61. * <code>Enumeration</code> of <code>String</code> objects, or an empty
  62. * <code>Enumeration</code> if the servlet has no initialization parameters.
  63. * See {@link ServletConfig#getInitParameterNames}.
  64. * <p>
  65. * This method is supplied for convenience. It gets the parameter names from
  66. * the servlet's <code>ServletConfig</code> object.
  67. *
  68. * @return Enumeration an enumeration of <code>String</code> objects
  69. * containing the names of the servlet's initialization parameters
  70. */
  71. @Override
  72. public Enumeration<String> getInitParameterNames() {
  73. return getServletConfig().getInitParameterNames();
  74. }
  75. /**
  76. * Returns this servlet's {@link ServletConfig} object.
  77. *
  78. * @return ServletConfig the <code>ServletConfig</code> object that
  79. * initialized this servlet
  80. */
  81. @Override
  82. public ServletConfig getServletConfig() {
  83. return config;
  84. }
  85. /**
  86. * Returns a reference to the {@link ServletContext} in which this servlet
  87. * is running. See {@link ServletConfig#getServletContext}.
  88. * <p>
  89. * This method is supplied for convenience. It gets the context from the
  90. * servlet's <code>ServletConfig</code> object.
  91. *
  92. * @return ServletContext the <code>ServletContext</code> object passed to
  93. * this servlet by the <code>init</code> method
  94. */
  95. @Override
  96. public ServletContext getServletContext() {
  97. return getServletConfig().getServletContext();
  98. }
  99. /**
  100. * Returns information about the servlet, such as author, version, and
  101. * copyright. By default, this method returns an empty string. Override this
  102. * method to have it return a meaningful value. See
  103. * {@link Servlet#getServletInfo}.
  104. *
  105. * @return String information about this servlet, by default an empty string
  106. */
  107. @Override
  108. public String getServletInfo() {
  109. return "";
  110. }
  111. /**
  112. * Called by the servlet container to indicate to a servlet that the servlet
  113. * is being placed into service. See {@link Servlet#init}.
  114. * <p>
  115. * This implementation stores the {@link ServletConfig} object it receives
  116. * from the servlet container for later use. When overriding this form of
  117. * the method, call <code>super.init(config)</code>.
  118. *
  119. * @param config
  120. * the <code>ServletConfig</code> object that contains
  121. * configuration information for this servlet
  122. * @exception ServletException
  123. * if an exception occurs that interrupts the servlet's
  124. * normal operation
  125. * @see UnavailableException
  126. */
  127. @Override
  128. public void init(ServletConfig config) throws ServletException {
  129. this.config = config;
  130. this.init();
  131. }
  132. /**
  133. * A convenience method which can be overridden so that there's no need to
  134. * call <code>super.init(config)</code>.
  135. * <p>
  136. * Instead of overriding {@link #init(ServletConfig)}, simply override this
  137. * method and it will be called by
  138. * <code>GenericServlet.init(ServletConfig config)</code>. The
  139. * <code>ServletConfig</code> object can still be retrieved via
  140. * {@link #getServletConfig}.
  141. *
  142. * @exception ServletException
  143. * if an exception occurs that interrupts the servlet's
  144. * normal operation
  145. */
  146. public void init() throws ServletException {
  147. // NOOP by default
  148. }
  149. /**
  150. * Writes the specified message to a servlet log file, prepended by the
  151. * servlet's name. See {@link ServletContext#log(String)}.
  152. *
  153. * @param msg
  154. * a <code>String</code> specifying the message to be written to
  155. * the log file
  156. */
  157. public void log(String msg) {
  158. getServletContext().log(getServletName() + ": " + msg);
  159. }
  160. /**
  161. * Writes an explanatory message and a stack trace for a given
  162. * <code>Throwable</code> exception to the servlet log file, prepended by
  163. * the servlet's name. See {@link ServletContext#log(String, Throwable)}.
  164. *
  165. * @param message
  166. * a <code>String</code> that describes the error or exception
  167. * @param t
  168. * the <code>java.lang.Throwable</code> error or exception
  169. */
  170. public void log(String message, Throwable t) {
  171. getServletContext().log(getServletName() + ": " + message, t);
  172. }
  173. /**
  174. * Called by the servlet container to allow the servlet to respond to a
  175. * request. See {@link Servlet#service}.
  176. * <p>
  177. * This method is declared abstract so subclasses, such as
  178. * <code>HttpServlet</code>, must override it.
  179. *
  180. * @param req
  181. * the <code>ServletRequest</code> object that contains the
  182. * client's request
  183. * @param res
  184. * the <code>ServletResponse</code> object that will contain the
  185. * servlet's response
  186. * @exception ServletException
  187. * if an exception occurs that interferes with the servlet's
  188. * normal operation occurred
  189. * @exception IOException
  190. * if an input or output exception occurs
  191. */
  192. @Override
  193. public abstract void service(ServletRequest req, ServletResponse res)
  194. throws ServletException, IOException;
  195. /**
  196. * Returns the name of this servlet instance. See
  197. * {@link ServletConfig#getServletName}.
  198. *
  199. * @return the name of this servlet instance
  200. */
  201. @Override
  202. public String getServletName() {
  203. return config.getServletName();
  204. }
  205. }

他有13个方法




























































方法 解析
public GenericServlet() 空参构造
public void destroy() 用于销毁一个servlet时
public String getInitParameter(String name)

https://blog.csdn.net/qq_35873847/article/details/77988619

用来获取在web.xml中配置的初始化参数

<init-param>

<param-name>XXXXX</param-name>

<param-value>XXXXXX</param-value>

</init-param>

有错误欢迎留言指正

public Enumeration<String> getInitParameterNames()

老夫掐指一算 获得的应该是 所有web.xml中param-name标签包含的玩意,返回的是一个枚举字符串数组。

https://zhidao.baidu.com/question/82397101.html

 public ServletConfig getServletConfig()  
public ServletContext getServletContext()  
public String getServletInfo()  
public void init(ServletConfig config) throws ServletException  
public void init() throws ServletException  
public void log(String msg)  
public void log(String message, Throwable t)  
public abstract void service(ServletRequest req, ServletResponse res) throws ServletException, IOException;  
public String getServletName()

 

———— 最后更新于2018年12月31日 22:46 待续…————

发表评论

表情:
评论列表 (有 0 条评论,303人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Servlet 详解

    一.什么是servlet?   Java Servlet 是运行在 Web 服务器或应用服务器上的程序,它是作为来自 Web 浏览器或其他 HTTP 客户端的请求和 HT

    相关 JAVA Servlet详解

    什么是Servlet         Servlet是运行在web服务器或应用服务器上的程序。         Servlet作为来自web浏览器或其他Http客户端的

    相关 Servlet详解

    越学到后面,越觉得基础重要,慢慢开始补充基础,因此这篇博客主要备忘一下扎实servlet的相关知识。 1.首先如何查看servlet的源码。     servlet的源

    相关 Servlet详解3

    ServletConfig 该接口是用来描述Servlet的基本信息的 ServletConfig中含有的方法,上面四个加粗的是这个类自定义的方法,后面的是继承过来的方

    相关 Servlet详解(一)

    什么是Servlet? Servlet是Java Web开发的基石,与平台无关的服务器组件,它是运行在Servlet容器/Web应用服务器/Tomcat,负责与客户端进行通