Servlet Httpservlet Genericservlet 三者之间关系

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Servlet Httpservlet Genericservlet 三者之间关系相关的知识,希望对你有一定的参考价值。

1.1、Servlet 源码

技术分享
public abstract interface Servlet  
{  
  public abstract void init(ServletConfig paramServletConfig) throws ServletException;  
  public abstract ServletConfig getServletConfig();  
  public abstract void service(ServletRequest paramServletRequest, ServletResponse paramServletResponse) throws ServletException, IOException; 
  public abstract String getServletInfo();  
  public abstract void destroy();  
} 
技术分享

 

二、GenericServlet分析

2.1、GenericServlet源代码

 

技术分享
 1 package javax.servlet;
 2 
 3 import java.io.IOException;
 4 import java.io.Serializable;
 5 import java.util.Enumeration;
 6 
 7 public abstract class GenericServlet implements Servlet, ServletConfig,Serializable {
 9     private transient ServletConfig config;
10 
11     public void destroy() {
12     }
13 
14     public String getInitParameter(String name) {
15         return getServletConfig().getInitParameter(name);
16     }
17 
18     public Enumeration getInitParameterNames() {
19         return getServletConfig().getInitParameterNames();
20     }
21 
22     public ServletConfig getServletConfig() {
23         return this.config;
24     }
25 
26     public ServletContext getServletContext() {
27         return getServletConfig().getServletContext();
28     }
29 
30     public String getServletInfo() {
31         return "";
32     }
33 
34     public void init(ServletConfig config) throws ServletException {
35         this.config = config;
36         init();
37     }
38 
39     public void init() throws ServletException {
40     }
41 
42     public void log(String msg) {
43         getServletContext().log(getServletName() + ": " + msg);
44     }
45 
46     public void log(String message, Throwable t) {
47         getServletContext().log(getServletName() + ": " + message, t);
48     }
49 
50     public abstract void service(ServletRequest paramServletRequest,
51             ServletResponse paramServletResponse) throws ServletException,
52             IOException;
53 
54     public String getServletName() {
55         return this.config.getServletName();
56     }
57 }
技术分享

 

 

  需要注意的点:

  • GenericServlet是个抽象类,不能直接进行实例化,必须给出子类才能实例化。即:GenericServlet gs = new GenericServlet(); 编译会报错。GenericServlet gs = new MyServlet(); 这样是正确的(其中MyServlet是其子类)
  • 其service()方法是个抽象方法,即它把处理请求的任务交给了子类。子类必须实现该方法。
  • 总得来看,它给出了设计servlet的一些骨架,定义了servlet生命周期,还有一些得到名字、配置、初始化参数的方法,其设计的是和应用层协议无关的,也就是说你有可能用非http协议实现它(其实目前Java Servlet还是只有Http一种)。

 

三、HttpServlet分析

3.1、HttpServlet源代码

 

技术分享
  1 package javax.servlet.http;
  2 
  3 import java.io.IOException;
  4 import java.io.Serializable;
  5 import java.lang.reflect.Method;
  6 import java.text.MessageFormat;
  7 import java.util.Enumeration;
  8 import java.util.ResourceBundle;
  9 import javax.servlet.GenericServlet;
 10 import javax.servlet.ServletException;
 11 import javax.servlet.ServletOutputStream;
 12 import javax.servlet.ServletRequest;
 13 import javax.servlet.ServletResponse;
 14 
 15 public abstract class HttpServlet extends GenericServlet implements Serializable {
 17     private static final long serialVersionUID = 1L;
 18     private static final String METHOD_DELETE = "DELETE";
 19     private static final String METHOD_HEAD = "HEAD";
 20     private static final String METHOD_GET = "GET";
 21     private static final String METHOD_OPTIONS = "OPTIONS";
 22     private static final String METHOD_POST = "POST";
 23     private static final String METHOD_PUT = "PUT";
 24     private static final String METHOD_TRACE = "TRACE";
 25     private static final String HEADER_IFMODSINCE = "If-Modified-Since";
 26     private static final String HEADER_LASTMOD = "Last-Modified";
 27     private static final String LSTRING_FILE = "javax.servlet.http.LocalStrings";
 28     private static ResourceBundle lStrings = ResourceBundle
 29             .getBundle("javax.servlet.http.LocalStrings");
 30 
 31     protected long getLastModified(HttpServletRequest req) {
 32         return -1L;
 33     }
 34 
 35     protected void doHead(HttpServletRequest req, HttpServletResponse resp)
 36             throws ServletException, IOException {
 37         NoBodyResponse response = new NoBodyResponse(resp);
 38         doGet(req, response);
 39         response.setContentLength();
 40     }
 41 
 42     protected void doPost(HttpServletRequest req, HttpServletResponse resp)
 43             throws ServletException, IOException {
 44         String protocol = req.getProtocol();
 45         String msg = lStrings.getString("http.method_post_not_supported");
 46         if (protocol.endsWith("1.1"))
 47             resp.sendError(405, msg);
 48         else
 49             resp.sendError(400, msg);
 50     }
 51 
 52     protected void doGet(HttpServletRequest req, HttpServletResponse resp)
 53             throws ServletException, IOException {
 54         String protocol = req.getProtocol();
 55         String msg = lStrings.getString("http.method_get_not_supported");
 56         if (protocol.endsWith("1.1"))
 57             resp.sendError(405, msg);
 58         else
 59             resp.sendError(400, msg);
 60     }
 61 
 62     protected void doPut(HttpServletRequest req, HttpServletResponse resp)
 63             throws ServletException, IOException {
 64         String protocol = req.getProtocol();
 65         String msg = lStrings.getString("http.method_put_not_supported");
 66         if (protocol.endsWith("1.1"))
 67             resp.sendError(405, msg);
 68         else
 69             resp.sendError(400, msg);
 70     }
 71 
 72     protected void doDelete(HttpServletRequest req, HttpServletResponse resp)
 73             throws ServletException, IOException {
 74         String protocol = req.getProtocol();
 75         String msg = lStrings.getString("http.method_delete_not_supported");
 76         if (protocol.endsWith("1.1"))
 77             resp.sendError(405, msg);
 78         else
 79             resp.sendError(400, msg);
 80     }
 81 
 82     private static Method[] getAllDeclaredMethods(Class c) {
 83         if (c.equals(HttpServlet.class)) {
 84             return null;
 85         }
 86         Method[] parentMethods = getAllDeclaredMethods(c.getSuperclass());
 87         Method[] thisMethods = c.getDeclaredMethods();
 88 
 89         if ((parentMethods != null) && (parentMethods.length > 0)) {
 90             Method[] allMethods = new Method[parentMethods.length
 91                     + thisMethods.length];
 92 
 93             System.arraycopy(parentMethods, 0, allMethods, 0,
 94                     parentMethods.length);
 95 
 96             System.arraycopy(thisMethods, 0, allMethods, parentMethods.length,
 97                     thisMethods.length);
 98 
 99             thisMethods = allMethods;
100         }
101         return thisMethods;
102     }
103 
104     protected void doOptions(HttpServletRequest req, HttpServletResponse resp)
105             throws ServletException, IOException {
106         Method[] methods = getAllDeclaredMethods(getClass());
107 
108         boolean ALLOW_GET = false;
109         boolean ALLOW_HEAD = false;
110         boolean ALLOW_POST = false;
111         boolean ALLOW_PUT = false;
112         boolean ALLOW_DELETE = false;
113         boolean ALLOW_TRACE = true;
114         boolean ALLOW_OPTIONS = true;
115 
116         for (int i = 0; i < methods.length; i++) {
117             Method m = methods[i];
118 
119             if (m.getName().equals("doGet")) {
120                 ALLOW_GET = true;
121                 ALLOW_HEAD = true;
122             }
123             if (m.getName().equals("doPost"))
124                 ALLOW_POST = true;
125             if (m.getName().equals("doPut"))
126                 ALLOW_PUT = true;
127             if (m.getName().equals("doDelete")) {
128                 ALLOW_DELETE = true;
129             }
130         }
131         String allow = null;
132         if ((ALLOW_GET) && (allow == null))
133             allow = "GET";
134         if (ALLOW_HEAD)
135             if (allow == null)
136                 allow = "HEAD";
137             else
138                 allow = allow + ", HEAD";
139         if (ALLOW_POST)
140             if (allow == null)
141                 allow = "POST";
142             else
143                 allow = allow + ", POST";
144         if (ALLOW_PUT)
145             if (allow == null)
146                 allow = "PUT";
147             else
148                 allow = allow + ", PUT";
149         if (ALLOW_DELETE)
150             if (allow == null)
151                 allow = "DELETE";
152             else
153                 allow = allow + ", DELETE";
154         if (ALLOW_TRACE)
155             if (allow == null)
156                 allow = "TRACE";
157             else
158                 allow = allow + ", TRACE";
159         if (ALLOW_OPTIONS) {
160             if (allow == null)
161                 allow = "OPTIONS";
162             else
163                 allow = allow + ", OPTIONS";
164         }
165         resp.setHeader("Allow", allow);
166     }
167 
168     protected void doTrace(HttpServletRequest req, HttpServletResponse resp)
169             throws ServletException, IOException {
170         String CRLF = "\\r\\n";
171         String responseString = "TRACE " + req.getRequestURI() + " "
172                 + req.getProtocol();
173 
174         Enumeration reqHeaderEnum = req.getHeaderNames();
175 
176         while (reqHeaderEnum.hasMoreElements()) {
177             String headerName = (String) reqHeaderEnum.nextElement();
178             responseString = responseString + CRLF + headerName + ": "
179                     + req.getHeader(headerName);
180         }
181 
182         responseString = responseString + CRLF;
183 
184         int responseLength = responseString.length();
185 
186         resp.setContentType("message/http");
187         resp.setContentLength(responseLength);
188         ServletOutputStream out = resp.getOutputStream();
189         out.print(responseString);
190         out.close();
191     }
192 
193     protected void service(HttpServletRequest req, HttpServletResponse resp)
194             throws ServletException, IOException {
195         String method = req.getMethod();
196 
197         if (method.equals("GET")) {
198             long lastModified = getLastModified(req);
199             if (lastModified == -1L) {
200                 doGet(req, resp);
201             } else {
202                 long ifModifiedSince = req.getDateHeader("If-Modified-Since");
203                 if (ifModifiedSince < lastModified / 1000L * 1000L) {
204                     maybeSetLastModified(resp, lastModified);
205                     doGet(req, resp);
206                 } else {
207                     resp.setStatus(304);
208                 }
209             }
210         } else if (method.equals("HEAD")) {
211             long lastModified = getLastModified(req);
212             maybeSetLastModified(resp, lastModified);
213             doHead(req, resp);
214         } else if (method.equals("POST")) {
215             doPost(req, resp);
216         } else if (method.equals("PUT")) {
217             doPut(req, resp);
218         } else if (method.equals("DELETE")) {
219             doDelete(req, resp);
220         } else if (method.equals("OPTIONS")) {
221             doOptions(req, resp);
222         } else if (method.equals("TRACE")) {
223             doTrace(req, resp);
224         } else {
225             String errMsg = lStrings.getString("http.method_not_implemented");
226             Object[] errArgs = new Object[1];
227             errArgs[0] = method;
228             errMsg = MessageFormat.format(errMsg, errArgs);
229 
230             resp.sendError(501, errMsg);
231         }
232     }
233 
234     private void maybeSetLastModified(HttpServletResponse resp,
235             long lastModified) {
236         if (resp.containsHeader("Last-Modified"))
237             return;
238         if (lastModified >= 0L)
239             resp.setDateHeader("Last-Modified", lastModified);
240     }
241 
242     public void service(ServletRequest req, ServletResponse res)
243             throws ServletException, IOException {
244         HttpServletRequest request;
245         HttpServletResponse response;
246         try {
247             request = (HttpServletRequest) req;
248             response = (HttpServletResponse) res;
249         } catch (ClassCastException e) {
250             throw new ServletException("non-HTTP request or response");
251         }
252         service(request, response);
253     }
254 }
技术分享

 

 

需要注意的点:

  • HttpServlet也是个抽象类,不能直接进行实例化,必须给出子类才能实例化(即不能直接使用,只能继承它)。
  • HttpServlet是采用Http协议进行通信的,所以它也实现Http协议中的多种方法,每种方法可以处理相应类型的请求

    Http协议方法

 HttpServlet实现方法

    OPTIONS

    doOption()

     GET

    doGet()

     POST

    doPost()

     TRACE

    doTrace()

     PUT

    doPut()

     DELETE

    doDelete()

  • HttpServlet的service()方法比较特殊,带public关键字的service()方法明显是继承自父类,它只接收HTTP请求,这里把相应的request和response转换为了基于HTTP协议的相应对象,最终将请求转到带protected关键字的service()方法中。protected service()方法根据请求的类型将请求转发到相应的doDelete()、doGet()、doOptions()、doPost()、doPut()等方法中。所以开发自己的Servlet时,不需要覆盖HttpServlet的service()方法,因为该方法最终将请求转发相相应的doXXX方法中,只需要覆盖相应的doXXX方法进行请求处理即可。如果重写了该方法,那么就不会根据方法名调用其他具体的方法了。
  • 同上道理, doOptions和doTrace方法也不需要覆盖。
  • 查看doGet、doPost、doPut、doDelete四个方法代码,发现这些方法只是判断协议类型,然后抛出相应的异常,其他什么都没做,所以实现自己的Servlet时,需要重写这些方法,以符合自己的需要进行请求处理。

 

四、三者比较

4.1 servlet 主要类之间的关系

技术分享

 

GenericServlet是所有Servlet类的祖先类,实现了接口:Servlet , ServletConfig ,GenericServlet是个抽象的父类,必须给出子类才能实例化

HttpServlet 类继承了GenericServlet 

Servlet有两个非常重要的对象,可以说是Java web非常核心的两个对象,HttpServletRequest和HttpServletResponse

 

 4.2 HttpServletRequest和HttpServletResponse 对象

技术分享

 

以上是关于Servlet Httpservlet Genericservlet 三者之间关系的主要内容,如果未能解决你的问题,请参考以下文章

扩展 HttpServlet实现Servlet程序 学习笔记

servlet实现的三种方式对比(servlet 和GenericServlet和HttpServlet)

Servlet--HttpServlet

HttpServlet详解

BaseServlet 继承 httpServlet

Servlet,GenericServlet和HttpServlet的继承关系