JSPday05(Servlet)

Servlet是什么

  Servlet就是一个类,试运行在服务器端的一个程序。当jsp翻译之后就是Servlet。Servlet自身为了能够提高更好的并发性,所以将自身设计为了单实例、多线程的一个类,所以会有线程安全性问题。一般解决方式:
  1.将所有的具有一定的危险性的字段放置在方法之中。
  2.将doXXX方法加入Synchronization(及其不推荐 这会造成无法并发执行)

Servlet架构

  

Servlet接口

源码:

通过对该接口进行观察,发现在接口下面包含了几个重要的方法:
  init():当前Servlet初始化
  service(ServletRequest,ServletResponse) :完成
  请求的服务响应,处理请求
  destroy(): 销毁Servlet 

ServletConfig接口

源码:

  通过观察该接口,能够发现其中的方法主要作用就是获取到Servlet名称、获取上下文、获取初始化参数及获取所有参数的名称的枚举。

GenericServlet

源码:

 1 //
 2 // Source code recreated from a .class file by IntelliJ IDEA
 3 // (powered by Fernflower decompiler)
 4 //
 5 
 6 package javax.servlet;
 7 
 8 import java.io.IOException;
 9 import java.io.Serializable;
10 import java.util.Enumeration;
11 import java.util.ResourceBundle;
12 
13 public abstract class GenericServlet implements Servlet, ServletConfig, Serializable {
14     private static final String LSTRING_FILE = "javax.servlet.LocalStrings";
15     private static ResourceBundle lStrings = ResourceBundle.getBundle("javax.servlet.LocalStrings");
16     private transient ServletConfig config;
17 
18     public GenericServlet() {
19     }
20 
21     public void destroy() {
22     }
23 
24     public String getInitParameter(String name) {
25         ServletConfig sc = this.getServletConfig();
26         if (sc == null) {
27             throw new IllegalStateException(lStrings.getString("err.servlet_config_not_initialized"));
28         } else {
29             return sc.getInitParameter(name);
30         }
31     }
32 
33     public Enumeration<String> getInitParameterNames() {
34         ServletConfig sc = this.getServletConfig();
35         if (sc == null) {
36             throw new IllegalStateException(lStrings.getString("err.servlet_config_not_initialized"));
37         } else {
38             return sc.getInitParameterNames();
39         }
40     }
41 
42     public ServletConfig getServletConfig() {
43         return this.config;
44     }
45 
46     public ServletContext getServletContext() {
47         ServletConfig sc = this.getServletConfig();
48         if (sc == null) {
49             throw new IllegalStateException(lStrings.getString("err.servlet_config_not_initialized"));
50         } else {
51             return sc.getServletContext();
52         }
53     }
54 
55     public String getServletInfo() {
56         return "";
57     }
58 
59     public void init(ServletConfig config) throws ServletException {
60         this.config = config;
61         this.init();
62     }
63 
64     public void init() throws ServletException {
65     }
66 
67     public void log(String msg) {
68         this.getServletContext().log(this.getServletName() + ": " + msg);
69     }
70 
71     public void log(String message, Throwable t) {
72         this.getServletContext().log(this.getServletName() + ": " + message, t);
73     }
74 
75     public abstract void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;
76 
77     public String getServletName() {
78         ServletConfig sc = this.getServletConfig();
79         if (sc == null) {
80             throw new IllegalStateException(lStrings.getString("err.servlet_config_not_initialized"));
81         } else {
82             return sc.getServletName();
83         }
84     }
85 }
View Code
通过观察源代码,发现该抽象类实现了ServletConfig下的接口所声明的方法,而Servlet接口下的方法,都下沉到子类HttpServlet之中了。 

HttpServlet 

源码:

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

  该类中实现了Servlet接口中的一些方法,同时声明处理了大量的HTTP请求相关信息。

 除了实现了doXXX方法之外,还重点实现了service方法,该方法的作用通过源码可以发现,就是处理所有请求的主方法,在该方法中通过使用request.getMethod()获取到请求的方式,然后调用对应的doXXX来处理。

Servlet生命周期

  实例化对象,Servlet本就是一个单例设计的对象,所以全局只有1个

  init()初始化,能够获取到初始化一些参数,对Servlet进行一些初始设置。

  service()进行处理请求以及响应服务

  destroy():在容器关闭或清空内存时,会调用该方法,执行后销毁当前的servlet方法

   

使用Servlet完成控制层

   将原有的JSP中的控制层代码转移到Servlet中。需要考虑Servlet自身的特性以及请求的方式,是Get还是Post,在其中request、response、application都不是内置对象,需要自己手动获取。

  手动获取session对象:

  手动获取application

   作为控制层需要完成的任务:

    验证数据

    封装数据对象

    承上启下的请求和响应的处理

登录Servlet代码演示:

原文地址:https://www.cnblogs.com/heureuxl/p/13706177.html