JavaWeb学习笔记之Servlet(二)

1.  GenericServlet 抽象类:

    1). 是一个 Serlvet. 是 Servlet 接口和 ServletConfig 接口的实现类. 但是一个抽象类. 其中的 service 方法为抽象方法 

    2). 如果新建的 Servlet 程序直接继承 GenericSerlvet 会使开发更简洁. 

    3). 具体实现: 

       ①. 在 GenericServlet 中声明了一个 SerlvetConfig 类型的成员变量, 在 init(ServletConfig) 方法中对其进行了初始化

       ②. 利用 servletConfig 成员变量的方法实现了 ServletConfig 接口的方法

         ③. 还定义了一个 init() 方法, 在 init(SerlvetConfig) 方法中对其进行调用, 子类可以直接覆盖 init() 在其中实现对 Servlet 的初始化.

       ④. 不建议直接覆盖 init(ServletConfig), 因为如果忘记编写 super.init(ServletConfig); 而还是用了 SerlvetConfig 接口的方法,则会出现空指针异常.

       ⑤. 新建的 init(){} 并非 Serlvet 的生命周期方法. 而 init(ServletConfig) 是生命周期相关的方法.

     注:为什么添加一个无参的init()方法?相信你有JavaSE的基础就会明白了!在此就不在赘述了,如果你不知道你可以去看一下关于方法的重载、方法的重写、类与父        类的关系之super的用法。

 GenericServlet的源码:

 1 public abstract class GenericServletimplements Servlet, ServletConfig, java.io.Serializable{
 2 
 3 private transient ServletConfig config;
 4 
 5     public GenericServlet() { }
 6       /**
 7          * 下面的方法是实现Servlet接口中的方法。
 8          */    
 9     public void destroy() {
10 }
11 
12     public ServletConfig getServletConfig() {
13         return config;
14 } 
15 
16     public String getServletInfo() {
17         return "";
18 }
19 
20 public abstract void service(ServletRequest req, ServletResponse res)
21     throws ServletException, IOException;
22 
23     public void init(ServletConfig config) throws ServletException {
24         this.config = config;
25         this.init();
26 }
27 
28     public void init() throws ServletException {
29 
30 }
31 
32 /**
33          * 下面的方法是实现ServletConfig接口中的方法。
34               */
35 
36     public String getInitParameter(String name) {
37         return getServletConfig().getInitParameter(name);
38 }
39     
40     public Enumeration getInitParameterNames() {
41         return getServletConfig().getInitParameterNames();
42 }
43 
44 public ServletContext getServletContext() {
45         return getServletConfig().getServletContext();
46 }
47 
48 public String getServletName() {
49         return config.getServletName();
50     }
51 
52 public void log(String msg) {
53         getServletContext().log(getServletName() + ": "+ msg);
54     } 
55    /**
56          * 下面的方法是GenericServlet抽象类自己定义的方法。
57               */
58 
59     public void log(String message, Throwable t) {
60         getServletContext().log(getServletName() + ": " + message, t);
61     } 
62 }
View Code

2.  HttpServlet 抽象类: 

   1). 是一个 Servlet, 继承自 GenericServlet. 针对于 HTTP 协议所定制. 

   2). 在service(ServletRequest, ServletResponse) 方法中直接把 ServletReuqest和ServletResponse 转为 HttpServletRequestHttpServletResponse.并调用了重载的 service(HttpServletRequest, HttpServletResponse)方法重载的 service(HttpServletRequest, HttpServletResponse) 获取了请求方式: request.getMethod(). 根据请求方式有创建了doXxx() 方法(xxx 为具体的请求方式, 比如 Get, Post等等方式。)

HttpServlet源码:

  1 public abstract class HttpServlet extends GenericServlet
  2     implements java.io.Serializable {
  3 
  4     private static final String METHOD_DELETE = "DELETE";
  5     private static final String METHOD_HEAD = "HEAD";
  6     private static final String METHOD_GET = "GET";
  7     private static final String METHOD_OPTIONS = "OPTIONS";
  8     private static final String METHOD_POST = "POST";
  9     private static final String METHOD_PUT = "PUT";
 10     private static final String METHOD_TRACE = "TRACE";
 11 
 12     private static final String HEADER_IFMODSINCE = "If-Modified-Since";
 13     private static final String HEADER_LASTMOD = "Last-Modified";
 14     
 15     private static final String LSTRING_FILE =
 16         "javax.servlet.http.LocalStrings";
 17     private static ResourceBundle lStrings =
 18         ResourceBundle.getBundle(LSTRING_FILE);
 19    public HttpServlet() { }
 20     
 21     protected void doGet(HttpServletRequest req, HttpServletResponse resp)
 22         throws ServletException, IOException
 23     {
 24         String protocol = req.getProtocol();
 25         String msg = lStrings.getString("http.method_get_not_supported");
 26         if (protocol.endsWith("1.1")) {
 27             resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);
 28         } else {
 29             resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);
 30         }
 31     }
 32 protected long getLastModified(HttpServletRequest req) {
 33         return -1;
 34     }
 35 
 36    protected void doHead(HttpServletRequest req, HttpServletResponse resp)
 37         throws ServletException, IOException {
 38 
 39         NoBodyResponse response = new NoBodyResponse(resp);
 40 
 41         doGet(req, response);
 42         response.setContentLength();
 43     }
 44 
 45 protected void doPost(HttpServletRequest req, HttpServletResponse resp)
 46         throws ServletException, IOException {
 47 
 48         String protocol = req.getProtocol();
 49         String msg = lStrings.getString("http.method_post_not_supported");
 50         if (protocol.endsWith("1.1")) {
 51             resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);
 52         } else {
 53             resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);
 54         }
 55     }
 56 
 57 protected void doPut(HttpServletRequest req, HttpServletResponse resp)
 58         throws ServletException, IOException {
 59 
 60         String protocol = req.getProtocol();
 61         String msg = lStrings.getString("http.method_put_not_supported");
 62         if (protocol.endsWith("1.1")) {
 63             resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);
 64         } else {
 65             resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);
 66         }
 67     }
 68   protected void doDelete(HttpServletRequest req,
 69                             HttpServletResponse resp)
 70         throws ServletException, IOException {
 71 
 72         String protocol = req.getProtocol();
 73         String msg = lStrings.getString("http.method_delete_not_supported");
 74         if (protocol.endsWith("1.1")) {
 75             resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);
 76         } else {
 77             resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);
 78         }
 79     }
 80     private static Method[] getAllDeclaredMethods(Class c) {
 81 
 82         if (c.equals(javax.servlet.http.HttpServlet.class)) {
 83             return null;
 84         }
 85 
 86         Method[] parentMethods = getAllDeclaredMethods(c.getSuperclass());
 87         Method[] thisMethods = c.getDeclaredMethods();
 88         
 89         if ((parentMethods != null) && (parentMethods.length > 0)) {
 90             Method[] allMethods =
 91                 new Method[parentMethods.length + thisMethods.length];
 92             System.arraycopy(parentMethods, 0, allMethods, 0,
 93                              parentMethods.length);
 94             System.arraycopy(thisMethods, 0, allMethods, parentMethods.length,
 95                              thisMethods.length);
 96 
 97             thisMethods = allMethods;
 98         }
 99 
100         return thisMethods;
101     }
102 protected void doOptions(HttpServletRequest req, HttpServletResponse resp)
103         throws ServletException, IOException {
104 
105         Method[] methods = getAllDeclaredMethods(this.getClass());
106         
107         boolean ALLOW_GET = false;
108         boolean ALLOW_HEAD = false;
109         boolean ALLOW_POST = false;
110         boolean ALLOW_PUT = false;
111         boolean ALLOW_DELETE = false;
112         boolean ALLOW_TRACE = true;
113         boolean ALLOW_OPTIONS = true;
114         
115         for (int i=0; i<methods.length; i++) {
116             Method m = methods[i];
117             
118             if (m.getName().equals("doGet")) {
119                 ALLOW_GET = true;
120                 ALLOW_HEAD = true;
121             }
122             if (m.getName().equals("doPost")) 
123                 ALLOW_POST = true;
124             if (m.getName().equals("doPut"))
125                 ALLOW_PUT = true;
126             if (m.getName().equals("doDelete"))
127                 ALLOW_DELETE = true;
128         }
129         
130         String allow = null;
131         if (ALLOW_GET)
132             if (allow==null) allow=METHOD_GET;
133         if (ALLOW_HEAD)
134             if (allow==null) allow=METHOD_HEAD;
135             else allow += ", " + METHOD_HEAD;
136         if (ALLOW_POST)
137             if (allow==null) allow=METHOD_POST;
138             else allow += ", " + METHOD_POST;
139         if (ALLOW_PUT)
140             if (allow==null) allow=METHOD_PUT;
141             else allow += ", " + METHOD_PUT;
142         if (ALLOW_DELETE)
143             if (allow==null) allow=METHOD_DELETE;
144             else allow += ", " + METHOD_DELETE;
145         if (ALLOW_TRACE)
146             if (allow==null) allow=METHOD_TRACE;
147             else allow += ", " + METHOD_TRACE;
148         if (ALLOW_OPTIONS)
149             if (allow==null) allow=METHOD_OPTIONS;
150             else allow += ", " + METHOD_OPTIONS;
151         
152         resp.setHeader("Allow", allow);
153     }
154     protected void doTrace(HttpServletRequest req, HttpServletResponse resp) 
155         throws ServletException, IOException
156     {
157         
158         int responseLength;
159         
160         String CRLF = "\r\n";
161         String responseString = "TRACE "+ req.getRequestURI()+
162             " " + req.getProtocol();
163         
164         Enumeration reqHeaderEnum = req.getHeaderNames();
165         
166         while( reqHeaderEnum.hasMoreElements() ) {
167             String headerName = (String)reqHeaderEnum.nextElement();
168             responseString += CRLF + headerName + ": " +
169                 req.getHeader(headerName); 
170         }
171         
172         responseString += CRLF;
173         
174         responseLength = responseString.length();
175         
176         resp.setContentType("message/http");
177         resp.setContentLength(responseLength);
178         ServletOutputStream out = resp.getOutputStream();
179         out.print(responseString);        
180         out.close();
181         return;
182     }                
183 
184 protected void service(HttpServletRequest req, HttpServletResponse resp)
185         throws ServletException, IOException {
186 
187         String method = req.getMethod();
188 
189         if (method.equals(METHOD_GET)) {
190             long lastModified = getLastModified(req);
191             if (lastModified == -1) {
192                 // servlet doesn't support if-modified-since, no reason
193                 // to go through further expensive logic
194                 doGet(req, resp);
195             } else {
196                 long ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
197                 if (ifModifiedSince < (lastModified / 1000 * 1000)) {
198                     // If the servlet mod time is later, call doGet()
199                     // Round down to the nearest second for a proper compare
200                     // A ifModifiedSince of -1 will always be less
201                     maybeSetLastModified(resp, lastModified);
202                     doGet(req, resp);
203                 } else {
204                     resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
205                 }
206             }
207 
208         } else if (method.equals(METHOD_HEAD)) {
209             long lastModified = getLastModified(req);
210             maybeSetLastModified(resp, lastModified);
211             doHead(req, resp);
212 
213         } else if (method.equals(METHOD_POST)) {
214             doPost(req, resp);
215             
216         } else if (method.equals(METHOD_PUT)) {
217             doPut(req, resp);        
218             
219         } else if (method.equals(METHOD_DELETE)) {
220             doDelete(req, resp);
221             
222         } else if (method.equals(METHOD_OPTIONS)) {
223             doOptions(req,resp);
224             
225         } else if (method.equals(METHOD_TRACE)) {
226             doTrace(req,resp);
227             
228         } else {
229             //
230             // Note that this means NO servlet supports whatever
231             // method was requested, anywhere on this server.
232             //
233 
234             String errMsg = lStrings.getString("http.method_not_implemented");
235             Object[] errArgs = new Object[1];
236             errArgs[0] = method;
237             errMsg = MessageFormat.format(errMsg, errArgs);
238             
239             resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);
240         }
241     }
242 private void maybeSetLastModified(HttpServletResponse resp,
243                                       long lastModified) {
244         if (resp.containsHeader(HEADER_LASTMOD))
245             return;
246         if (lastModified >= 0)
247             resp.setDateHeader(HEADER_LASTMOD, lastModified);
248     }
249    public void service(ServletRequest req, ServletResponse res)
250         throws ServletException, IOException {
251 
252         HttpServletRequest  request;
253         HttpServletResponse response;
254         
255         try {
256             request = (HttpServletRequest) req;
257             response = (HttpServletResponse) res;
258         } catch (ClassCastException e) {
259             throw new ServletException("non-HTTP request or response");
260         }
261         service(request, response);
262     }
263 }
264 
265 
266 /*
267  * A response wrapper for use in (dumb) "HEAD" support.
268  * This just swallows that body, counting the bytes in order to set
269  * the content length appropriately.  All other methods delegate to the
270  * wrapped HTTP Servlet Response object.
271  */
272 // file private
273 class NoBodyResponse extends HttpServletResponseWrapper {
274     private NoBodyOutputStream                noBody;
275     private PrintWriter                        writer;
276     private boolean                        didSetContentLength;
277 
278     // file private
279     NoBodyResponse(HttpServletResponse r) {
280         super(r);
281         noBody = new NoBodyOutputStream();
282     }
283 
284     // file private
285     void setContentLength() {
286         if (!didSetContentLength)
287           super.setContentLength(noBody.getContentLength());
288     }
289 
290 
291     // SERVLET RESPONSE interface methods
292 
293     public void setContentLength(int len) {
294         super.setContentLength(len);
295         didSetContentLength = true;
296     }
297 
298     public ServletOutputStream getOutputStream() throws IOException {
299         return noBody;
300     }
301 
302     public PrintWriter getWriter() throws UnsupportedEncodingException {
303 
304         if (writer == null) {
305             OutputStreamWriter w;
306 
307             w = new OutputStreamWriter(noBody, getCharacterEncoding());
308             writer = new PrintWriter(w);
309         }
310         return writer;
311     }
312 }
313 
314 
315 /*
316  * Servlet output stream that gobbles up all its data.
317  */
318  
319 // file private
320 class NoBodyOutputStream extends ServletOutputStream {
321 
322     private static final String LSTRING_FILE =
323         "javax.servlet.http.LocalStrings";
324     private static ResourceBundle lStrings =
325         ResourceBundle.getBundle(LSTRING_FILE);
326 
327     private int                contentLength = 0;
328 
329     // file private
330     NoBodyOutputStream() {}
331 
332     // file private
333     int getContentLength() {
334         return contentLength;
335     }
336 
337     public void write(int b) {
338         contentLength++;
339     }
340 
341     public void write(byte buf[], int offset, int len)
342         throws IOException
343     {
344         if (len >= 0) {
345             contentLength += len;
346         } else {
347             // XXX
348             // isn't this really an IllegalArgumentException?
349             
350             String msg = lStrings.getString("err.io.negativelength");
351             throw new IOException(msg);
352         }
353     }
354 }
View Code

    3). 实际开发中, 直接继承 HttpServlet, 并根据请求方式复写 doXxx() 方法即可. 

    4). 优点: 直接由针对性的覆盖 doXxx() 方法; 直接使用 HttpServletRequest 和  HttpServletResponse, 不再需要强转.

转载于:https://www.cnblogs.com/Vincent-NMT/p/6060959.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值