日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

servlet 源码分析

發(fā)布時間:2023/12/10 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 servlet 源码分析 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

servlet源碼分析

  • 1. servlet接口
    • 1.1 看servlet源碼
    • 1.2 直接用類實(shí)現(xiàn)servlet接口,來寫servlet類
  • 2. servlet子類GenericServlet
    • 2.1 servlet子類實(shí)現(xiàn)GenericServlet抽象類
    • 2.2 繼承GenericServelt抽象類
  • 3. httpServelt類分析
  • 4. 這么多搬來的代碼,最后總結(jié)

1. servlet接口

1.1 看servlet源碼

// 接口是一種標(biāo)準(zhǔn),規(guī)范 public interface Servlet {// 初始化servletpublic void init(ServletConfig config) throws ServletException;// service服務(wù)方法public void service(ServletRequest req, ServletResponse res)throws ServletException, IOException;// servlet的信息,如作者...public String getServletInfo();// servlet 銷毀public void destroy(); }
  • 注意,tomcat只認(rèn)上面的標(biāo)準(zhǔn),如以ServletRequest請求對象,ServletConfig等…

1.2 直接用類實(shí)現(xiàn)servlet接口,來寫servlet類

package com.lovely.servlet;import java.io.IOException;import javax.servlet.Servlet; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse;public class Servlet1 implements Servlet {// 1.寫一個類實(shí)現(xiàn)Servlet接口,// 然后當(dāng)客戶端請求Servlet之后,// servlet拿到自己的名字,打印到客戶端(解決亂碼問題)private ServletConfig config;public void destroy() {}public ServletConfig getServletConfig() {return this.config;}public String getServletInfo() {return null;}public void init(ServletConfig config) throws ServletException {this.config = config;// 初始化時賦值配置信息}public void service(ServletRequest req, ServletResponse resp)throws ServletException, IOException {resp.setContentType("text/html;charset=utf-8");resp.getWriter().print("servlet名字為: " + config.getServletName());// 得到web.xml 配置信息System.out.println(config.getInitParameter("encode"));}}

2. servlet子類GenericServlet

  • servletconfig接口
package javax.servlet;import java.util.Enumeration;public interface ServletConfig {// servlet的 名字public String getServletName();// application public ServletContext getServletContext();// web.xml 配置信息 <init-param></init-param>/*** <init-param><param-name>encode</param-name><param-value>utf-8</param-value></init-param>*/public String getInitParameter(String name);public Enumeration<String> getInitParameterNames(); }

2.1 servlet子類實(shí)現(xiàn)GenericServlet抽象類

package javax.servlet;import java.io.IOException; import java.util.Enumeration;public abstract class GenericServlet implements Servlet, ServletConfig,java.io.Serializable {private static final long serialVersionUID = 1L;private transient ServletConfig config;public GenericServlet() {}public void destroy() {}// web.xml <param-init/>信息public String getInitParameter(String name) {return getServletConfig().getInitParameter(name);}public Enumeration<String> getInitParameterNames() {return getServletConfig().getInitParameterNames();}// 返回servlet配置信息public ServletConfig getServletConfig() {return config;}// servletContext 也是一個接口public ServletContext getServletContext() {return getServletConfig().getServletContext();}// servlet信息public String getServletInfo() {return "";}// 實(shí)現(xiàn)了servlet接口中的init方法。 tomcat可以認(rèn)識的init 方法public void init(ServletConfig config) throws ServletException {this.config = config;// 調(diào)用了下面重載的init方法this.init();}// 重載init方法!!! public void init() throws ServletException {}// 兩個log都是日志信息public void log(String msg) {getServletContext().log(getServletName() + ": " + msg);}public void log(String message, Throwable t) {getServletContext().log(getServletName() + ": " + message, t);}// servlet接口中未實(shí)現(xiàn)的service方法public abstract void service(ServletRequest req, ServletResponse res)throws ServletException, IOException;// 重寫得到配置信息public String getServletName() {return config.getServletName();} }

2.2 繼承GenericServelt抽象類

// 有適配器的味道了 package com.lovely.servlet;import java.io.IOException;import javax.servlet.GenericServlet; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse;public class MyServlet1 extends GenericServlet {/*** 2.寫一個類繼承GenericServlet,測試servlet的生命周期*/private static final long serialVersionUID = 1L;/*** init() 方法分析* 重寫GenericServlet init(), 但是tomcat不會調(diào)用下面手寫的init(), 它不認(rèn)得 * 就找到init(ServletConfig config),而它里面調(diào)用了自身的重載的init() 承上啟下* 而GenericServlet重載的init() 被子類重寫啦* 則:* myservlet1初始化*/ public void init() throws ServletException {System.out.println("myservlet1初始化");}@Overridepublic void service(ServletRequest req, ServletResponse resp)throws ServletException, IOException {System.out.println("服務(wù)...");}@Overridepublic void destroy() {System.out.println("銷毀...");}}

3. httpServelt類分析

package javax.servlet.http;import java.io.IOException; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.io.UnsupportedEncodingException; import java.lang.reflect.Method; import java.text.MessageFormat; import java.util.Enumeration; import java.util.ResourceBundle;import javax.servlet.GenericServlet; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse;public abstract class HttpServlet extends GenericServlet {private static final long serialVersionUID = 1L;// 下面的常量是數(shù)據(jù)的提交方式 增刪改查 restful風(fēng)private static final String METHOD_DELETE = "DELETE";private static final String METHOD_HEAD = "HEAD";private static final String METHOD_GET = "GET";private static final String METHOD_OPTIONS = "OPTIONS";private static final String METHOD_POST = "POST";private static final String METHOD_PUT = "PUT";private static final String METHOD_TRACE = "TRACE";private static final String HEADER_IFMODSINCE = "If-Modified-Since";private static final String HEADER_LASTMOD = "Last-Modified";private static final String LSTRING_FILE ="javax.servlet.http.LocalStrings";private static ResourceBundle lStrings =ResourceBundle.getBundle(LSTRING_FILE);public HttpServlet() {}// make client do anything belowprotected void doGet(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException{String protocol = req.getProtocol();String msg = lStrings.getString("http.method_get_not_supported");if (protocol.endsWith("1.1")) {resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);} else {resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);}}protected long getLastModified(HttpServletRequest req) {return -1;}protected void doHead(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {NoBodyResponse response = new NoBodyResponse(resp);doGet(req, response);response.setContentLength();}protected void doPost(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {String protocol = req.getProtocol();String msg = lStrings.getString("http.method_post_not_supported");if (protocol.endsWith("1.1")) {resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);} else {resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);}}protected void doPut(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {String protocol = req.getProtocol();String msg = lStrings.getString("http.method_put_not_supported");if (protocol.endsWith("1.1")) {resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);} else {resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);}}protected void doDelete(HttpServletRequest req,HttpServletResponse resp)throws ServletException, IOException {String protocol = req.getProtocol();String msg = lStrings.getString("http.method_delete_not_supported");if (protocol.endsWith("1.1")) {resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);} else {resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);}}private static Method[] getAllDeclaredMethods(Class<?> c) {if (c.equals(javax.servlet.http.HttpServlet.class)) {return null;}Method[] parentMethods = getAllDeclaredMethods(c.getSuperclass());Method[] thisMethods = c.getDeclaredMethods();if ((parentMethods != null) && (parentMethods.length > 0)) {Method[] allMethods =new Method[parentMethods.length + thisMethods.length];System.arraycopy(parentMethods, 0, allMethods, 0,parentMethods.length);System.arraycopy(thisMethods, 0, allMethods, parentMethods.length,thisMethods.length);thisMethods = allMethods;}return thisMethods;}protected void doOptions(HttpServletRequest req,HttpServletResponse resp)throws ServletException, IOException {Method[] methods = getAllDeclaredMethods(this.getClass());boolean ALLOW_GET = false;boolean ALLOW_HEAD = false;boolean ALLOW_POST = false;boolean ALLOW_PUT = false;boolean ALLOW_DELETE = false;boolean ALLOW_TRACE = true;boolean ALLOW_OPTIONS = true;for (int i=0; i<methods.length; i++) {Method m = methods[i];if (m.getName().equals("doGet")) {ALLOW_GET = true;ALLOW_HEAD = true;}if (m.getName().equals("doPost")) ALLOW_POST = true;if (m.getName().equals("doPut"))ALLOW_PUT = true;if (m.getName().equals("doDelete"))ALLOW_DELETE = true;}String allow = null;if (ALLOW_GET)allow=METHOD_GET;if (ALLOW_HEAD)if (allow==null) allow=METHOD_HEAD;else allow += ", " + METHOD_HEAD;if (ALLOW_POST)if (allow==null) allow=METHOD_POST;else allow += ", " + METHOD_POST;if (ALLOW_PUT)if (allow==null) allow=METHOD_PUT;else allow += ", " + METHOD_PUT;if (ALLOW_DELETE)if (allow==null) allow=METHOD_DELETE;else allow += ", " + METHOD_DELETE;if (ALLOW_TRACE)if (allow==null) allow=METHOD_TRACE;else allow += ", " + METHOD_TRACE;if (ALLOW_OPTIONS)if (allow==null) allow=METHOD_OPTIONS;else allow += ", " + METHOD_OPTIONS;resp.setHeader("Allow", allow);}protected void doTrace(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException{int responseLength;String CRLF = "\r\n";StringBuilder buffer = new StringBuilder("TRACE ").append(req.getRequestURI()).append(" ").append(req.getProtocol());Enumeration<String> reqHeaderEnum = req.getHeaderNames();while( reqHeaderEnum.hasMoreElements() ) {String headerName = reqHeaderEnum.nextElement();buffer.append(CRLF).append(headerName).append(": ").append(req.getHeader(headerName)); }buffer.append(CRLF);responseLength = buffer.length();resp.setContentType("message/http");resp.setContentLength(responseLength);ServletOutputStream out = resp.getOutputStream();out.print(buffer.toString()); out.close();return;} // 重載service方法, 也是要繼承httpservlet子類重寫的方法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) {doGet(req, resp);} else {long ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);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 lessmaybeSetLastModified(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 {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);}}// 重寫GenericServlet,也是tomcat會調(diào)用的方法public void service(ServletRequest req, ServletResponse res)throws ServletException, IOException {HttpServletRequest request;HttpServletResponse response;try {// 轉(zhuǎn)型Http 遵循h(huán)ttp 協(xié)議。request = (HttpServletRequest) req;response = (HttpServletResponse) res;} catch (ClassCastException e) {throw new ServletException("non-HTTP request or response");}// 調(diào)用自身service(HttpServletRequest req, HttpServletResponse resp)的方法,而自身的方法被子類重寫了// 所以自身判斷get/post等其它方法的提交,被覆蓋啦service(request, response);} }
  • 問題,為什么寫了service方法,doGet() / doPost() 方法會失效?

答:
tomcat只認(rèn)識service(ServletRequest req, ServletResponse resp),
它調(diào)用自身service(HttpServletRequest req, HttpServletResponse resp)的方法,而自身的方法被子類重寫了。
所以自身判斷get/post等其它方法的提交,被覆蓋啦。

4. 這么多搬來的代碼,最后總結(jié)

問題1:這些方法為什么可以被tomcat自動調(diào)用? 問題2:為什么這些方法不能亂寫,必須有一個固定寫法? 問題3:為什么doGet/doPost與Service方法不能同時出現(xiàn)?

一: 以上這些問題與Servlet的體系(繼承)有關(guān)系
HttpServlet 繼承 GenericServlet 實(shí)現(xiàn) Servlet接口
注意:Servlet接口是整個Servlet體系的標(biāo)準(zhǔn)所在,tomcat只認(rèn)這個標(biāo)準(zhǔn)

二:分析完代碼后,servlet到底該怎么寫?
實(shí)現(xiàn)Servlet的三種方式:

  • 實(shí)現(xiàn)Servlet接口(非常不方便)
  • 繼承GenericServlet抽象類(相對于方式1方便很多,但是還是不夠方便)
  • 繼承HttpServlet抽象類(最簡便)
  • 總結(jié)

    以上是生活随笔為你收集整理的servlet 源码分析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。