一个较丰满的servlet web server,由简化的conector、HttpProcessor、bootstrap 和简单servelt处理器构成(1代码清单)

代码结构:

该目录未能显示项目根下的webroot文件夹,此文件夹存放servlet程序员编译的servlet.class文件和静态资源。

      

  •  BootStrap
package sub.startup;

import sub.connector.http.HttpConnector;

public final class Bootstrap {
  public static void main(String[] args) {//之前是一个server,现在是有启动和连接器代理
    HttpConnector connector = new HttpConnector();
    connector.start();
  }
}
View Code
  • HttpConnector
 1 package sub.connector.http;
 2 
 3 import java.io.IOException;
 4 import java.net.InetAddress;
 5 import java.net.ServerSocket;
 6 import java.net.Socket;
 7 
 8 public class HttpConnector implements Runnable {//开启了线程机制
 9 
10   boolean stopped;//默认false
11   private String scheme = "http";
12 
13   public String getScheme() {
14     return scheme;
15   }
16 
17   public void run() {
18     ServerSocket serverSocket = null;
19     int port = 8080;
20     try {
21       serverSocket =  new ServerSocket(port, 1, InetAddress.getByName("192.168.1.100"));//绑定自己的ip
22     }
23     catch (IOException e) {
24       e.printStackTrace();
25       System.exit(1);
26     }
27     while (!stopped) {
28       // Accept the next incoming connection from the server socket
29       Socket socket = null;
30       try {
31         socket = serverSocket.accept();
32         System.out.println("服务器接受到请求");
33       }
34       catch (Exception e) {
35         continue;
36       }
37       // Hand this socket off to an HttpProcessor
38       HttpProcessor processor = new HttpProcessor(this);
39       processor.process(socket);
40       System.out.println("进入Http解析程序");
41     }
42   }
43 
44   public void start() {
45     Thread thread = new Thread(this);
46     thread.start();
47   }
48 }
View Code
  • HttpProcessor
  1 package sub.connector.http;
  2 
  3 import sub.ServletProcessor;
  4 import sub.StaticResourceProcessor;
  5 import java.net.Socket;
  6 import java.io.OutputStream;
  7 import java.io.IOException;
  8 import javax.servlet.ServletException;
  9 import javax.servlet.http.Cookie;
 10 import org.apache.catalina.util.RequestUtil;
 11 import org.apache.catalina.util.StringManager;
 12 
 13 /* this class used to be called HttpServer  取代了原来的HttpServer类*/
 14 /**
 15  * 原来的HttpServer除去等待请求的任务以外,就是创建res/req并“初始化”,req对象的创建,头部,行部的初始化和处理,req形同一个entity,但是请求体的解析在哪里?
 16  * 并调用加载servlet的processor类(负责servlet的加载处理),使其动态加载servlet并传递res/req
 17  * 如何获得请求体?
 18  * */
 19 public class HttpProcessor {
 20 
 21   public HttpProcessor(HttpConnector connector) {
 22     this.connector = connector;
 23   }
 24   /**
 25    * The HttpConnector with which this processor is associated.
 26    */
 27   private HttpConnector connector = null;
 28   private HttpRequest request;
 29   private HttpRequestLine requestLine = new HttpRequestLine();
 30   private HttpResponse response;
 31 
 32   protected String method = null;
 33   protected String queryString = null;
 34 
 35   /**
 36    * The string manager for this package.
 37    */
 38   protected StringManager sm =
 39     StringManager.getManager("sub.connector.http");//读取标签文件中的信息,用来打印日志,指定包,供本包使用。
 40 
 41   public void process(Socket socket) { //负责创建res/req
 42     SocketInputStream input = null;
 43     OutputStream output = null;
 44     try {
 45       input = new SocketInputStream(socket.getInputStream(), 2048);
 46       output = socket.getOutputStream();
 47 
 48       // create HttpRequest object and parse  
 49       request = new HttpRequest(input);
 50 
 51       // create HttpResponse object
 52       response = new HttpResponse(output);
 53       response.setRequest(request);    //响应对象的诸多属性,为什么不需要初始化?除了响应体之外。
 54   
 55       response.setHeader("Server", "Pyrmont Servlet Container");  
 56       parseRequest(input, output); //解析请求行
 57       parseHeaders(input);         //解析请求头
 58       
 59       //check if this is a request for a servlet or a static resource
 60       //a request for a servlet begins with "/servlet/"
 61       if (request.getRequestURI().startsWith("/servlet/")) {
 62         ServletProcessor processor = new ServletProcessor();
 63         processor.process(request, response);
 64       }
 65       else {
 66         StaticResourceProcessor processor = new StaticResourceProcessor();
 67         processor.process(request, response);
 68       }
 69 
 70       // Close the socket
 71       socket.close();
 72       // no shutdown for this application
 73     }
 74     catch (Exception e) {
 75       e.printStackTrace();
 76     }
 77   }
 78 
 79   /**
 80    * 该方法类似于初始化或构造方法的延伸,根据目的是使属性得到值。
 81    * This method is the simplified version of the similar method in
 82    * org.apache.catalina.connector.http.HttpProcessor.
 83    * However, this method only parses some "easy" headers, such as
 84    * "cookie", "content-length", and "content-type", and ignore other headers.
 85    * @param input The input stream connected to our socket
 86    *
 87    * @exception IOException if an input/output error occurs
 88    * @exception ServletException if a parsing error occurs
 89    */
 90   private void parseHeaders(SocketInputStream input)
 91     throws IOException, ServletException {//旧版本中该输入流有现成的方法获取头部信息。从关系来看,request更类似一个entity类
 92     while (true) {
 93       HttpHeader header = new HttpHeader();
 94 
 95       // Read the next header
 96       input.readHeader(header);
 97       if (header.nameEnd == 0) {
 98         if (header.valueEnd == 0) {
 99           return;
100         }
101         else {
102           throw new ServletException
103             (sm.getString("httpProcessor.parseHeaders.colon"));
104         }
105       }
106 
107       String name = new String(header.name, 0, header.nameEnd);
108       String value = new String(header.value, 0, header.valueEnd);
109       request.addHeader(name, value); 
110       // do something for some headers, ignore others.
111       if (name.equals("cookie")) {
112         Cookie cookies[] = RequestUtil.parseCookieHeader(value);//从header中获得cookie
113         for (int i = 0; i < cookies.length; i++) {
114           if (cookies[i].getName().equals("jsessionid")) {
115             // Override anything requested in the URL
116             if (!request.isRequestedSessionIdFromCookie()) {
117               // Accept only the first session id cookie
118               request.setRequestedSessionId(cookies[i].getValue());
119               request.setRequestedSessionCookie(true);
120               request.setRequestedSessionURL(false);
121             }
122           }
123           request.addCookie(cookies[i]);   //request添加cookie对象,以上是cookie对象赋值。
124         }
125       }
126       else if (name.equals("content-length")) {
127         int n = -1;
128         try {
129           n = Integer.parseInt(value);
130         }
131         catch (Exception e) {
132           throw new ServletException(sm.getString("httpProcessor.parseHeaders.contentLength"));
133         }
134         request.setContentLength(n);     //设置content-length
135       }
136       else if (name.equals("content-type")) {
137         request.setContentType(value);
138       }
139     } //end while
140   }
141 
142 
143   private void parseRequest(SocketInputStream input, OutputStream output)
144     throws IOException, ServletException {//解析请求行,input对象可以直接获取这些属性值。
145 
146     // Parse the incoming request line  
147     input.readRequestLine(requestLine);
148     String method =
149       new String(requestLine.method, 0, requestLine.methodEnd);
150     String uri = null;
151     String protocol = new String(requestLine.protocol, 0, requestLine.protocolEnd);
152 
153     // Validate the incoming request line
154     if (method.length() < 1) {
155       throw new ServletException("Missing HTTP request method");
156     }
157     else if (requestLine.uriEnd < 1) {
158       throw new ServletException("Missing HTTP request URI");
159     }
160     // Parse any query parameters out of the request URI
161     int question = requestLine.indexOf("?");
162     if (question >= 0) {
163       request.setQueryString(new String(requestLine.uri, question + 1,
164         requestLine.uriEnd - question - 1));
165       uri = new String(requestLine.uri, 0, question);
166     }
167     else {
168       request.setQueryString(null);
169       uri = new String(requestLine.uri, 0, requestLine.uriEnd);
170     }
171 
172 
173     // Checking for an absolute URI (with the HTTP protocol)
174     if (!uri.startsWith("/")) {
175       int pos = uri.indexOf("://");
176       // Parsing out protocol and host name
177       if (pos != -1) {
178         pos = uri.indexOf('/', pos + 3);
179         if (pos == -1) {
180           uri = "";
181         }
182         else {
183           uri = uri.substring(pos);
184         }
185       }
186       
187     }
188 
189     // Parse any requested session ID out of the request URI 从请求URI中解析所请求的会话ID
190     String match = ";jsessionid=";
191     int semicolon = uri.indexOf(match);
192     if (semicolon >= 0) {
193       String rest = uri.substring(semicolon + match.length());
194       int semicolon2 = rest.indexOf(';');
195       if (semicolon2 >= 0) {
196         request.setRequestedSessionId(rest.substring(0, semicolon2));
197         rest = rest.substring(semicolon2);
198       }
199       else {
200         request.setRequestedSessionId(rest);
201         rest = "";
202       }
203       request.setRequestedSessionURL(true);
204       uri = uri.substring(0, semicolon) + rest;
205     }
206     else {
207       request.setRequestedSessionId(null);
208       request.setRequestedSessionURL(false);
209     }
210 
211     // Normalize URI (using String operations at the moment)  规范化请求uri
212     String normalizedUri = normalize(uri);
213 
214     // Set the corresponding request properties 设置相应的请求属性
215     ((HttpRequest) request).setMethod(method);
216     request.setProtocol(protocol);
217     if (normalizedUri != null) {
218       ((HttpRequest) request).setRequestURI(normalizedUri);
219     }
220     else {
221       ((HttpRequest) request).setRequestURI(uri);
222     }
223 
224     if (normalizedUri == null) {
225       throw new ServletException("Invalid URI: " + uri + "'");
226     }
227   }
228 
229   /**
230    * Return a context-relative path, beginning with a "/", that represents
231    * the canonical version of the specified path after ".." and "." elements
232    * are resolved out.  If the specified path attempts to go outside the
233    * boundaries of the current context (i.e. too many ".." path elements
234    * are present), return <code>null</code> instead.
235    *
236    * @param path Path to be normalized
237    */
238   protected String normalize(String path) {
239     if (path == null)
240       return null;
241     // Create a place for the normalized path
242     String normalized = path;
243 
244     // Normalize "/%7E" and "/%7e" at the beginning to "/~"
245     if (normalized.startsWith("/%7E") || normalized.startsWith("/%7e"))
246       normalized = "/~" + normalized.substring(4);
247 
248     // Prevent encoding '%', '/', '.' and '\', which are special reserved
249     // characters
250     if ((normalized.indexOf("%25") >= 0)
251       || (normalized.indexOf("%2F") >= 0)
252       || (normalized.indexOf("%2E") >= 0)
253       || (normalized.indexOf("%5C") >= 0)
254       || (normalized.indexOf("%2f") >= 0)
255       || (normalized.indexOf("%2e") >= 0)
256       || (normalized.indexOf("%5c") >= 0)) {
257       return null;
258     }
259 
260     if (normalized.equals("/."))
261       return "/";
262 
263     // Normalize the slashes and add leading slash if necessary
264     if (normalized.indexOf('\\') >= 0)
265       normalized = normalized.replace('\\', '/');
266     if (!normalized.startsWith("/"))
267       normalized = "/" + normalized;
268 
269     // Resolve occurrences of "//" in the normalized path
270     while (true) {
271       int index = normalized.indexOf("//");
272       if (index < 0)
273         break;
274       normalized = normalized.substring(0, index) +
275         normalized.substring(index + 1);
276     }
277 
278     // Resolve occurrences of "/./" in the normalized path
279     while (true) {
280       int index = normalized.indexOf("/./");
281       if (index < 0)
282         break;
283       normalized = normalized.substring(0, index) +
284         normalized.substring(index + 2);
285     }
286 
287     // Resolve occurrences of "/../" in the normalized path
288     while (true) {
289       int index = normalized.indexOf("/../");
290       if (index < 0)
291         break;
292       if (index == 0)
293         return (null);  // Trying to go outside our context
294       int index2 = normalized.lastIndexOf('/', index - 1);
295       normalized = normalized.substring(0, index2) +
296         normalized.substring(index + 3);
297     }
298 
299     // Declare occurrences of "/..." (three or more dots) to be invalid
300     // (on some Windows platforms this walks the directory tree!!!)
301     if (normalized.indexOf("/...") >= 0)
302       return (null);
303 
304     // Return the normalized path that we have completed
305     return (normalized);
306 
307   }
308 
309 }
View Code
  • HttpRequest
  1 package sub.connector.http;
  2 
  3 /** this class copies methods from org.apache.catalina.connector.HttpRequestBase
  4  *  and org.apache.catalina.connector.http.HttpRequestImpl.
  5  *  The HttpRequestImpl class employs a pool of HttpHeader objects for performance
  6  *  These two classes will be explained in Chapter 4.
  7  */
  8 import sub.connector.RequestStream;
  9 
 10 
 11 
 12 import javax.servlet.http.HttpServletRequest;
 13 import javax.servlet.http.HttpServletResponse;
 14 import javax.servlet.http.HttpSession;
 15 import javax.servlet.http.HttpUpgradeHandler;
 16 import javax.servlet.http.Part;
 17 import javax.servlet.http.Cookie;
 18 import javax.servlet.AsyncContext;
 19 import javax.servlet.DispatcherType;
 20 import javax.servlet.RequestDispatcher;
 21 import javax.servlet.ServletContext;
 22 import javax.servlet.ServletException;
 23 import javax.servlet.ServletInputStream;
 24 import javax.servlet.ServletRequest;
 25 import javax.servlet.ServletResponse;
 26 
 27 import java.security.Principal;
 28 import java.io.InputStream;
 29 import java.io.InputStreamReader;
 30 import java.io.IOException;
 31 import java.io.BufferedReader;
 32 import java.io.UnsupportedEncodingException;
 33 import java.net.InetAddress;
 34 import java.net.Socket;
 35 import java.text.ParseException;
 36 import java.text.SimpleDateFormat;
 37 import java.util.ArrayList;
 38 import java.util.Collection;
 39 import java.util.Date;
 40 import java.util.Enumeration;
 41 import java.util.HashMap;
 42 import java.util.Locale;
 43 import java.util.Map;
 44 import org.apache.catalina.util.Enumerator;
 45 import org.apache.catalina.util.ParameterMap;
 46 import org.apache.catalina.util.RequestUtil;
 47 /**request在servet程序员使用之前解析还是使用时解析更好?
 48  * 如果是前者,就应该在servletProcessor中类似于初始化那样,全部解析,然后程序员可以直接get;
 49  * 若后者,则需要在get中包含解析过程。        
 50  * */
 51 public class HttpRequest implements HttpServletRequest {
 52 
 53   private String contentType;
 54   private int contentLength;
 55   private InetAddress inetAddress;
 56   private InputStream input;
 57   private String method;
 58   private String protocol;
 59   private String queryString;
 60   private String requestURI;
 61   private String serverName;
 62   private int serverPort;
 63   private Socket socket;
 64   private boolean requestedSessionCookie;
 65   private String requestedSessionId;
 66   private boolean requestedSessionURL;
 67 
 68   /**
 69    * The request attributes for this request. 该当前请求的请求属性
 70    */
 71   protected HashMap attributes = new HashMap();
 72   /**
 73    * The authorization credentials sent with this Request. 当前请求的授权证书
 74    */
 75   protected String authorization = null;
 76   /**
 77    * The context path for this request. 当前请求的上下文路径
 78    */
 79   protected String contextPath = "";
 80   /**
 81    * The set of cookies associated with this Request. 与请求关联的一组cookie(浏览器会自行发送cookie)
 82    */
 83   protected ArrayList cookies = new ArrayList();
 84   /**
 85    * An empty collection to use for returning empty Enumerations.  Do not
 86    * add any elements to this collection!
 87    */
 88   protected static ArrayList empty = new ArrayList();
 89   /**
 90    * The set of SimpleDateFormat formats to use in getDateHeader().
 91    */
 92   protected SimpleDateFormat formats[] = {
 93     new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US),
 94     new SimpleDateFormat("EEEEEE, dd-MMM-yy HH:mm:ss zzz", Locale.US),
 95     new SimpleDateFormat("EEE MMMM d HH:mm:ss yyyy", Locale.US)
 96   };
 97 
 98   /**
 99    * The HTTP headers associated with this Request, keyed by name.  The
100    * values are ArrayLists of the corresponding header values. 用map保存header信息。
101    */
102   protected HashMap headers = new HashMap();
103   /**
104    * The parsed parameters for this request.  This is populated only if
105    * parameter information is requested via one of the
106    * <code>getParameter()</code> family of method calls.  The key is the
107    * parameter name, while the value is a String array of values for this
108    * parameter.
109    * <p>
110    * <strong>IMPLEMENTATION NOTE</strong> - Once the parameters for a
111    * particular request are parsed and stored here, they are not modified.
112    * Therefore, application level access to the parameters need not be
113    * synchronized.
114    */
115   protected ParameterMap parameters = null; //hashmap的子类
116 
117   /**
118    * Have the parameters for this request been parsed yet?
119    */
120   protected boolean parsed = false;
121   protected String pathInfo = null;
122 
123   /**
124    * The reader that has been returned by <code>getReader</code>, if any.
125    */
126   protected BufferedReader reader = null;
127 
128   /**
129    * The ServletInputStream that has been returned by
130    * <code>getInputStream()</code>, if any.
131    */
132   protected ServletInputStream stream = null;
133 
134   public HttpRequest(InputStream input) {
135     this.input = input;
136   }
137 
138   public void addHeader(String name, String value) {  //header包含所有的请求key-value
139     name = name.toLowerCase();
140     synchronized (headers) {
141       ArrayList values = (ArrayList) headers.get(name);
142       if (values == null) {
143         values = new ArrayList();
144         headers.put(name, values);
145       }
146       values.add(value);
147     }
148   }
149 
150   /**
151    * Parse the parameters of this request, if it has not already occurred.
152    * If parameters are present in both the query string and the request
153    * content, they are merged. 一个“过程”
154    */
155   protected void parseParameters() {//解析并把参数存进parameters中
156     if (parsed) 
157       return;  
158     ParameterMap results = parameters;  //参数集合?
159     if (results == null)
160       results = new ParameterMap();
161     results.setLocked(false);
162     String encoding = getCharacterEncoding();
163     if (encoding == null)
164       encoding = "ISO-8859-1"; 
165 
166     // Parse any parameters specified in the query string 解析查询字符串中指定的任何参数
167     String queryString = getQueryString();
168     try {
169       RequestUtil.parseParameters(results, queryString, encoding);//没有输入流,怎么就把请求参数解析出来的??
170     }
171     catch (UnsupportedEncodingException e) {
172       ;
173     }
174 
175     // Parse any parameters specified in the input stream 解析输入流中指定的任何参数
176     String contentType = getContentType();
177     if (contentType == null)
178       contentType = "";
179     int semicolon = contentType.indexOf(';');
180     if (semicolon >= 0) {
181       contentType = contentType.substring(0, semicolon).trim();
182     }
183     else {
184       contentType = contentType.trim();
185     }
186     if ("POST".equals(getMethod()) && (getContentLength() > 0)
187       && "application/x-www-form-urlencoded".equals(contentType)) {//post请求方式下解析请求参数
188       try {
189         int max = getContentLength();
190         int len = 0;
191         byte buf[] = new byte[getContentLength()];
192         ServletInputStream is = getInputStream();
193         while (len < max) {
194           int next = is.read(buf, len, max - len);
195           if (next < 0 ) {
196             break;
197           }
198           len += next;
199         }
200         is.close();
201         if (len < max) {
202           throw new RuntimeException("Content length mismatch");
203         }
204         RequestUtil.parseParameters(results, buf, encoding);
205       }
206       catch (UnsupportedEncodingException ue) {
207         ;
208       }
209       catch (IOException e) {
210         throw new RuntimeException("Content read fail");
211       }
212     }
213 
214     // Store the final results
215     results.setLocked(true);
216     parsed = true;
217     parameters = results;
218   }
219 
220   public void addCookie(Cookie cookie) {
221     synchronized (cookies) {
222       cookies.add(cookie);
223     }
224   }
225 
226   /**
227    * Create and return a ServletInputStream to read the content
228    * associated with this Request.  The default implementation creates an
229    * instance of RequestStream associated with this request, but this can
230    * be overridden if necessary.
231    *
232    * @exception IOException if an input/output error occurs
233    */
234   public ServletInputStream createInputStream() throws IOException {
235     return (new RequestStream(this));
236   }
237 
238   public InputStream getStream() {
239     return input;
240   }
241   public void setContentLength(int length) {
242     this.contentLength = length;
243   }
244 
245   public void setContentType(String type) {
246     this.contentType = type;
247   }
248 
249   public void setInet(InetAddress inetAddress) {
250     this.inetAddress = inetAddress;
251   }
252 
253   public void setContextPath(String path) {
254     if (path == null)
255       this.contextPath = "";
256     else
257       this.contextPath = path;
258   }
259 
260   public void setMethod(String method) {
261     this.method = method;
262   }
263 
264   public void setPathInfo(String path) {
265     this.pathInfo = path;
266   }
267 
268   public void setProtocol(String protocol) {
269     this.protocol = protocol;
270   }
271 
272   public void setQueryString(String queryString) {
273     this.queryString = queryString;
274   }
275 
276   public void setRequestURI(String requestURI) {
277     this.requestURI = requestURI;
278   }
279   /**
280    * Set the name of the server (virtual host) to process this request.
281    *
282    * @param name The server name
283    */
284   public void setServerName(String name) {
285     this.serverName = name;
286   }
287   /**
288    * Set the port number of the server to process this request.
289    *
290    * @param port The server port
291    */
292   public void setServerPort(int port) {
293     this.serverPort = port;
294   }
295 
296   public void setSocket(Socket socket) {
297     this.socket = socket;
298   }
299 
300   /**
301    * Set a flag indicating whether or not the requested session ID for this
302    * request came in through a cookie.  This is normally called by the
303    * HTTP Connector, when it parses the request headers.
304    *
305    * @param flag The new flag
306    */
307   public void setRequestedSessionCookie(boolean flag) {
308     this.requestedSessionCookie = flag;
309   }
310 
311   public void setRequestedSessionId(String requestedSessionId) {
312     this.requestedSessionId = requestedSessionId;
313   }
314 
315   public void setRequestedSessionURL(boolean flag) {
316     requestedSessionURL = flag;
317   }
318 
319   /* implementation of the HttpServletRequest*/
320   public Object getAttribute(String name) {
321     synchronized (attributes) {
322       return (attributes.get(name));
323     }
324   }
325 
326   public Enumeration getAttributeNames() {
327     synchronized (attributes) {
328       return (new Enumerator(attributes.keySet()));
329     }
330   }
331 
332   public String getAuthType() {
333     return null;
334   }
335 
336   public String getCharacterEncoding() {
337     return null;
338   }
339 
340   public int getContentLength() {
341     return contentLength ;
342   }
343 
344   public String getContentType() {
345     return contentType;
346   }
347 
348   public String getContextPath() {
349     return contextPath;
350   }
351 
352   public Cookie[] getCookies() {
353     synchronized (cookies) {
354       if (cookies.size() < 1)
355         return (null);
356       Cookie results[] = new Cookie[cookies.size()];
357       return ((Cookie[]) cookies.toArray(results));
358     }
359   }
360 
361   public long getDateHeader(String name) {
362     String value = getHeader(name);
363     if (value == null)
364       return (-1L);
365 
366     // Work around a bug in SimpleDateFormat in pre-JDK1.2b4
367     // (Bug Parade bug #4106807)
368     value += " ";
369 
370     // Attempt to convert the date header in a variety of formats
371     for (int i = 0; i < formats.length; i++) {
372       try {
373         Date date = formats[i].parse(value);
374         return (date.getTime());
375       }
376       catch (ParseException e) {
377         ;
378       }
379     }
380     throw new IllegalArgumentException(value);
381   }
382 
383   public String getHeader(String name) {
384     name = name.toLowerCase();
385     synchronized (headers) {
386       ArrayList values = (ArrayList) headers.get(name);
387       if (values != null)
388         return ((String) values.get(0));
389       else
390         return null;
391     }
392   }
393 
394   public Enumeration getHeaderNames() {
395     synchronized (headers) {
396       return (new Enumerator(headers.keySet()));
397     }
398   }
399 
400   public Enumeration getHeaders(String name) {
401     name = name.toLowerCase();
402     synchronized (headers) {
403       ArrayList values = (ArrayList) headers.get(name);
404       if (values != null)
405         return (new Enumerator(values));
406       else
407         return (new Enumerator(empty));
408     }
409   }
410 
411   public ServletInputStream getInputStream() throws IOException {
412     if (reader != null)
413       throw new IllegalStateException("getInputStream has been called");
414 
415     if (stream == null)
416       stream = createInputStream();
417     return (stream);
418   }
419 
420   public int getIntHeader(String name) {
421     String value = getHeader(name);
422     if (value == null)
423       return (-1);
424     else
425       return (Integer.parseInt(value));
426   }
427 
428   public Locale getLocale() {
429     return null;
430   }
431 
432   public Enumeration getLocales() {
433     return null;
434   }
435 
436   public String getMethod() {
437     return method;
438   }
439 
440   public String getParameter(String name) {//在组件程序员获取参数时会包含解析过程!
441     parseParameters();
442     String values[] = (String[]) parameters.get(name);
443     if (values != null)
444       return (values[0]);
445     else
446       return (null);
447   }
448 
449   public Map getParameterMap() {
450     parseParameters();
451     return (this.parameters);
452   }
453 
454   public Enumeration getParameterNames() {
455     parseParameters();
456     return (new Enumerator(parameters.keySet()));
457   }
458 
459   public String[] getParameterValues(String name) {
460     parseParameters();
461     String values[] = (String[]) parameters.get(name);
462     if (values != null)
463       return (values);
464     else
465       return null;
466   }
467 
468   public String getPathInfo() {
469     return pathInfo;
470   }
471 
472   public String getPathTranslated() {
473     return null;
474   }
475 
476   public String getProtocol() {
477     return protocol;
478   }
479 
480   public String getQueryString() {
481     return queryString;
482   }
483 
484   public BufferedReader getReader() throws IOException {
485     if (stream != null)
486       throw new IllegalStateException("getInputStream has been called.");
487     if (reader == null) {
488       String encoding = getCharacterEncoding();
489       if (encoding == null)
490         encoding = "ISO-8859-1";
491       InputStreamReader isr =
492         new InputStreamReader(createInputStream(), encoding);
493         reader = new BufferedReader(isr);
494     }
495     return (reader);
496   }
497 
498   public String getRealPath(String path) {
499     return null;
500   }
501 
502   public String getRemoteAddr() {
503     return null;
504   }
505 
506   public String getRemoteHost() {
507     return null;
508   }
509 
510   public String getRemoteUser() {
511     return null;
512   }
513 
514   public RequestDispatcher getRequestDispatcher(String path) {
515     return null;
516   }
517 
518   public String getScheme() {
519    return null;
520   }
521 
522   public String getServerName() {
523     return null;
524   }
525 
526   public int getServerPort() {
527     return 0;
528   }
529 
530   public String getRequestedSessionId() {
531     return null;
532   }
533 
534   public String getRequestURI() {
535     return requestURI;
536   }
537 
538   public StringBuffer getRequestURL() {
539     return null;
540   }
541 
542   public HttpSession getSession() {
543     return null;
544   }
545 
546   public HttpSession getSession(boolean create) {
547     return null;
548   }
549 
550   public String getServletPath() {
551     return null;
552   }
553 
554   public Principal getUserPrincipal() {
555     return null;
556   }
557 
558   public boolean isRequestedSessionIdFromCookie() {
559     return false;
560   }
561 
562   public boolean isRequestedSessionIdFromUrl() {
563     return isRequestedSessionIdFromURL();
564   }
565 
566   public boolean isRequestedSessionIdFromURL() {
567     return false;
568   }
569 
570   public boolean isRequestedSessionIdValid() {
571     return false;
572   }
573 
574   public boolean isSecure() {
575     return false;
576   }
577 
578   public boolean isUserInRole(String role) {
579     return false;
580   }
581 
582   public void removeAttribute(String attribute) {
583   }
584 
585   public void setAttribute(String key, Object value) {
586   }
587 
588   /**
589    * Set the authorization credentials sent with this request.
590    *
591    * @param authorization The new authorization credentials
592    */
593   public void setAuthorization(String authorization) {
594     this.authorization = authorization;
595   }
596 
597   public void setCharacterEncoding(String encoding) throws UnsupportedEncodingException {
598   }
599 
600 @Override
601 public long getContentLengthLong() {
602     // TODO Auto-generated method stub
603     return 0;
604 }
605 
606 @Override
607 public int getRemotePort() {
608     // TODO Auto-generated method stub
609     return 0;
610 }
611 
612 @Override
613 public String getLocalName() {
614     // TODO Auto-generated method stub
615     return null;
616 }
617 
618 @Override
619 public String getLocalAddr() {
620     // TODO Auto-generated method stub
621     return null;
622 }
623 
624 @Override
625 public int getLocalPort() {
626     // TODO Auto-generated method stub
627     return 0;
628 }
629 
630 @Override
631 public ServletContext getServletContext() {
632     // TODO Auto-generated method stub
633     return null;
634 }
635 
636 @Override
637 public AsyncContext startAsync() throws IllegalStateException {
638     // TODO Auto-generated method stub
639     return null;
640 }
641 
642 @Override
643 public AsyncContext startAsync(ServletRequest arg0, ServletResponse arg1) throws IllegalStateException {
644     // TODO Auto-generated method stub
645     return null;
646 }
647 
648 @Override
649 public boolean isAsyncStarted() {
650     // TODO Auto-generated method stub
651     return false;
652 }
653 
654 @Override
655 public boolean isAsyncSupported() {
656     // TODO Auto-generated method stub
657     return false;
658 }
659 
660 @Override
661 public AsyncContext getAsyncContext() {
662     // TODO Auto-generated method stub
663     return null;
664 }
665 
666 @Override
667 public DispatcherType getDispatcherType() {
668     // TODO Auto-generated method stub
669     return null;
670 }
671 
672 @Override
673 public String changeSessionId() {
674     // TODO Auto-generated method stub
675     return null;
676 }
677 
678 @Override
679 public boolean authenticate(HttpServletResponse arg0) throws IOException, ServletException {
680     // TODO Auto-generated method stub
681     return false;
682 }
683 
684 @Override
685 public void login(String arg0, String arg1) throws ServletException {
686     // TODO Auto-generated method stub
687     
688 }
689 
690 @Override
691 public void logout() throws ServletException {
692     // TODO Auto-generated method stub
693     
694 }
695 
696 @Override
697 public Collection<Part> getParts() throws IOException, ServletException {
698     // TODO Auto-generated method stub
699     return null;
700 }
701 
702 @Override
703 public Part getPart(String arg0) throws IOException, ServletException {
704     // TODO Auto-generated method stub
705     return null;
706 }
707 
708 @Override
709 public <T extends HttpUpgradeHandler> T upgrade(Class<T> arg0) throws IOException, ServletException {
710     // TODO Auto-generated method stub
711     return null;
712 }
713 }
View Code
  • HttpResponse
  1 import sub.ServletProcessor;
  2 import sub.StaticResourceProcessor;
  3 import java.net.Socket;
  4 import java.io.OutputStream;
  5 import java.io.IOException;
  6 import javax.servlet.ServletException;
  7 import javax.servlet.http.Cookie;
  8 import org.apache.catalina.util.RequestUtil;
  9 import org.apache.catalina.util.StringManager;
 10 
 11 /* this class used to be called HttpServer  取代了原来的HttpServer类*/
 12 /**
 13  * 原来的HttpServer除去等待请求的任务以外,就是创建res/req并“初始化”,req对象的创建,头部,行部的初始化和处理,req形同一个entity,但是请求体的解析在哪里?
 14  * 并调用加载servlet的processor类(负责servlet的加载处理),使其动态加载servlet并传递res/req
 15  * 如何获得请求体?
 16  * */
 17 public class HttpProcessor {
 18 
 19   public HttpProcessor(HttpConnector connector) {
 20     this.connector = connector;
 21   }
 22   /**
 23    * The HttpConnector with which this processor is associated.
 24    */
 25   private HttpConnector connector = null;
 26   private HttpRequest request;
 27   private HttpRequestLine requestLine = new HttpRequestLine();
 28   private HttpResponse response;
 29 
 30   protected String method = null;
 31   protected String queryString = null;
 32 
 33   /**
 34    * The string manager for this package.
 35    */
 36   protected StringManager sm =
 37     StringManager.getManager("sub.connector.http");//读取标签文件中的信息,用来打印日志,指定包,供本包使用。
 38 
 39   public void process(Socket socket) { //负责创建res/req
 40     SocketInputStream input = null;
 41     OutputStream output = null;
 42     try {
 43       input = new SocketInputStream(socket.getInputStream(), 2048);
 44       output = socket.getOutputStream();
 45 
 46       // create HttpRequest object and parse  
 47       request = new HttpRequest(input);
 48 
 49       // create HttpResponse object
 50       response = new HttpResponse(output);
 51       response.setRequest(request);    //响应对象的诸多属性,为什么不需要初始化?除了响应体之外。
 52   
 53       response.setHeader("Server", "Pyrmont Servlet Container");  
 54       parseRequest(input, output); //解析请求行
 55       parseHeaders(input);         //解析请求头
 56       
 57       //check if this is a request for a servlet or a static resource
 58       //a request for a servlet begins with "/servlet/"
 59       if (request.getRequestURI().startsWith("/servlet/")) {
 60         ServletProcessor processor = new ServletProcessor();
 61         processor.process(request, response);
 62       }
 63       else {
 64         StaticResourceProcessor processor = new StaticResourceProcessor();
 65         processor.process(request, response);
 66       }
 67 
 68       // Close the socket
 69       socket.close();
 70       // no shutdown for this application
 71     }
 72     catch (Exception e) {
 73       e.printStackTrace();
 74     }
 75   }
 76 
 77   /**
 78    * 该方法类似于初始化或构造方法的延伸,根据目的是使属性得到值。
 79    * This method is the simplified version of the similar method in
 80    * org.apache.catalina.connector.http.HttpProcessor.
 81    * However, this method only parses some "easy" headers, such as
 82    * "cookie", "content-length", and "content-type", and ignore other headers.
 83    * @param input The input stream connected to our socket
 84    *
 85    * @exception IOException if an input/output error occurs
 86    * @exception ServletException if a parsing error occurs
 87    */
 88   private void parseHeaders(SocketInputStream input)
 89     throws IOException, ServletException {//旧版本中该输入流有现成的方法获取头部信息。从关系来看,request更类似一个entity类
 90     while (true) {
 91       HttpHeader header = new HttpHeader();
 92 
 93       // Read the next header
 94       input.readHeader(header);
 95       if (header.nameEnd == 0) {
 96         if (header.valueEnd == 0) {
 97           return;
 98         }
 99         else {
100           throw new ServletException
101             (sm.getString("httpProcessor.parseHeaders.colon"));
102         }
103       }
104 
105       String name = new String(header.name, 0, header.nameEnd);
106       String value = new String(header.value, 0, header.valueEnd);
107       request.addHeader(name, value); 
108       // do something for some headers, ignore others.
109       if (name.equals("cookie")) {
110         Cookie cookies[] = RequestUtil.parseCookieHeader(value);//从header中获得cookie
111         for (int i = 0; i < cookies.length; i++) {
112           if (cookies[i].getName().equals("jsessionid")) {
113             // Override anything requested in the URL
114             if (!request.isRequestedSessionIdFromCookie()) {
115               // Accept only the first session id cookie
116               request.setRequestedSessionId(cookies[i].getValue());
117               request.setRequestedSessionCookie(true);
118               request.setRequestedSessionURL(false);
119             }
120           }
121           request.addCookie(cookies[i]);   //request添加cookie对象,以上是cookie对象赋值。
122         }
123       }
124       else if (name.equals("content-length")) {
125         int n = -1;
126         try {
127           n = Integer.parseInt(value);
128         }
129         catch (Exception e) {
130           throw new ServletException(sm.getString("httpProcessor.parseHeaders.contentLength"));
131         }
132         request.setContentLength(n);     //设置content-length
133       }
134       else if (name.equals("content-type")) {
135         request.setContentType(value);
136       }
137     } //end while
138   }
139 
140 
141   private void parseRequest(SocketInputStream input, OutputStream output)
142     throws IOException, ServletException {//解析请求行,input对象可以直接获取这些属性值。
143 
144     // Parse the incoming request line  
145     input.readRequestLine(requestLine);
146     String method =
147       new String(requestLine.method, 0, requestLine.methodEnd);
148     String uri = null;
149     String protocol = new String(requestLine.protocol, 0, requestLine.protocolEnd);
150 
151     // Validate the incoming request line
152     if (method.length() < 1) {
153       throw new ServletException("Missing HTTP request method");
154     }
155     else if (requestLine.uriEnd < 1) {
156       throw new ServletException("Missing HTTP request URI");
157     }
158     // Parse any query parameters out of the request URI
159     int question = requestLine.indexOf("?");
160     if (question >= 0) {
161       request.setQueryString(new String(requestLine.uri, question + 1,
162         requestLine.uriEnd - question - 1));
163       uri = new String(requestLine.uri, 0, question);
164     }
165     else {
166       request.setQueryString(null);
167       uri = new String(requestLine.uri, 0, requestLine.uriEnd);
168     }
169 
170 
171     // Checking for an absolute URI (with the HTTP protocol)
172     if (!uri.startsWith("/")) {
173       int pos = uri.indexOf("://");
174       // Parsing out protocol and host name
175       if (pos != -1) {
176         pos = uri.indexOf('/', pos + 3);
177         if (pos == -1) {
178           uri = "";
179         }
180         else {
181           uri = uri.substring(pos);
182         }
183       }
184       
185     }
186 
187     // Parse any requested session ID out of the request URI 从请求URI中解析所请求的会话ID
188     String match = ";jsessionid=";
189     int semicolon = uri.indexOf(match);
190     if (semicolon >= 0) {
191       String rest = uri.substring(semicolon + match.length());
192       int semicolon2 = rest.indexOf(';');
193       if (semicolon2 >= 0) {
194         request.setRequestedSessionId(rest.substring(0, semicolon2));
195         rest = rest.substring(semicolon2);
196       }
197       else {
198         request.setRequestedSessionId(rest);
199         rest = "";
200       }
201       request.setRequestedSessionURL(true);
202       uri = uri.substring(0, semicolon) + rest;
203     }
204     else {
205       request.setRequestedSessionId(null);
206       request.setRequestedSessionURL(false);
207     }
208 
209     // Normalize URI (using String operations at the moment)  规范化请求uri
210     String normalizedUri = normalize(uri);
211 
212     // Set the corresponding request properties 设置相应的请求属性
213     ((HttpRequest) request).setMethod(method);
214     request.setProtocol(protocol);
215     if (normalizedUri != null) {
216       ((HttpRequest) request).setRequestURI(normalizedUri);
217     }
218     else {
219       ((HttpRequest) request).setRequestURI(uri);
220     }
221 
222     if (normalizedUri == null) {
223       throw new ServletException("Invalid URI: " + uri + "'");
224     }
225   }
226 
227   /**
228    * Return a context-relative path, beginning with a "/", that represents
229    * the canonical version of the specified path after ".." and "." elements
230    * are resolved out.  If the specified path attempts to go outside the
231    * boundaries of the current context (i.e. too many ".." path elements
232    * are present), return <code>null</code> instead.
233    *
234    * @param path Path to be normalized
235    */
236   protected String normalize(String path) {
237     if (path == null)
238       return null;
239     // Create a place for the normalized path
240     String normalized = path;
241 
242     // Normalize "/%7E" and "/%7e" at the beginning to "/~"
243     if (normalized.startsWith("/%7E") || normalized.startsWith("/%7e"))
244       normalized = "/~" + normalized.substring(4);
245 
246     // Prevent encoding '%', '/', '.' and '\', which are special reserved
247     // characters
248     if ((normalized.indexOf("%25") >= 0)
249       || (normalized.indexOf("%2F") >= 0)
250       || (normalized.indexOf("%2E") >= 0)
251       || (normalized.indexOf("%5C") >= 0)
252       || (normalized.indexOf("%2f") >= 0)
253       || (normalized.indexOf("%2e") >= 0)
254       || (normalized.indexOf("%5c") >= 0)) {
255       return null;
256     }
257 
258     if (normalized.equals("/."))
259       return "/";
260 
261     // Normalize the slashes and add leading slash if necessary
262     if (normalized.indexOf('\\') >= 0)
263       normalized = normalized.replace('\\', '/');
264     if (!normalized.startsWith("/"))
265       normalized = "/" + normalized;
266 
267     // Resolve occurrences of "//" in the normalized path
268     while (true) {
269       int index = normalized.indexOf("//");
270       if (index < 0)
271         break;
272       normalized = normalized.substring(0, index) +
273         normalized.substring(index + 1);
274     }
275 
276     // Resolve occurrences of "/./" in the normalized path
277     while (true) {
278       int index = normalized.indexOf("/./");
279       if (index < 0)
280         break;
281       normalized = normalized.substring(0, index) +
282         normalized.substring(index + 2);
283     }
284 
285     // Resolve occurrences of "/../" in the normalized path
286     while (true) {
287       int index = normalized.indexOf("/../");
288       if (index < 0)
289         break;
290       if (index == 0)
291         return (null);  // Trying to go outside our context
292       int index2 = normalized.lastIndexOf('/', index - 1);
293       normalized = normalized.substring(0, index2) +
294         normalized.substring(index + 3);
295     }
296 
297     // Declare occurrences of "/..." (three or more dots) to be invalid
298     // (on some Windows platforms this walks the directory tree!!!)
299     if (normalized.indexOf("/...") >= 0)
300       return (null);
301 
302     // Return the normalized path that we have completed
303     return (normalized);
304 
305   }
306 
307 }
代码清单
  • HttpReuqestFacaed
  • HtppResponseFacaed
  1 package sub.connector.http;
  2 
  3 import java.io.IOException;
  4 
  5 import java.io.PrintWriter;
  6 import java.util.Collection;
  7 import java.util.Locale;
  8 import javax.servlet.ServletOutputStream;
  9 import javax.servlet.http.Cookie;
 10 import javax.servlet.http.HttpServletResponse;
 11 
 12 public class HttpResponseFacade implements HttpServletResponse {
 13   private HttpServletResponse response;
 14   public HttpResponseFacade(HttpResponse response) {
 15     this.response = response;
 16   }
 17 
 18   /** implementation of HttpServletResponse  */
 19   public void addCookie(Cookie cookie) {
 20     response.addCookie(cookie);
 21   }
 22 
 23   public void addDateHeader(String name, long value) {
 24     response.addDateHeader(name, value);
 25   }
 26 
 27   public void addHeader(String name, String value) {
 28     response.addHeader(name, value);
 29   }
 30 
 31   public void addIntHeader(String name, int value) {
 32     response.addIntHeader(name, value);
 33   }
 34 
 35   public boolean containsHeader(String name) {
 36     return response.containsHeader(name);
 37   }
 38 
 39   public String encodeRedirectURL(String url) {
 40     return response.encodeRedirectURL(url);
 41   }
 42 
 43   public String encodeRedirectUrl(String url) {
 44     return response.encodeRedirectUrl(url);
 45   }
 46 
 47   public String encodeUrl(String url) {
 48     return response.encodeUrl(url);
 49   }
 50 
 51   public String encodeURL(String url) {
 52     return response.encodeURL(url);
 53   }
 54 
 55   public void flushBuffer() throws IOException {
 56      response.flushBuffer();
 57   }
 58 
 59   public int getBufferSize() {
 60     return response.getBufferSize();
 61   }
 62 
 63   public String getCharacterEncoding() {
 64     return response.getCharacterEncoding();
 65   }
 66 
 67   public Locale getLocale() {
 68     return response.getLocale();
 69   }
 70 
 71   public ServletOutputStream getOutputStream() throws IOException {
 72     return response.getOutputStream();
 73   }
 74 
 75   public PrintWriter getWriter() throws IOException {
 76     return response.getWriter();
 77   }
 78 
 79   public boolean isCommitted() {
 80     return response.isCommitted();
 81   }
 82 
 83   public void reset() {
 84     response.reset();
 85   }
 86 
 87   public void resetBuffer() {
 88     response.resetBuffer();
 89   }
 90 
 91   public void sendError(int sc) throws IOException {
 92     response.sendError(sc);
 93   }
 94 
 95   public void sendError(int sc, String message) throws IOException {
 96     response.sendError(sc, message);
 97   }
 98 
 99   public void sendRedirect(String location) throws IOException {
100     response.sendRedirect(location);
101   }
102 
103   public void setBufferSize(int size) {
104     response.setBufferSize(size);
105   }
106 
107   public void setContentLength(int length) {
108     response.setContentLength(length);
109   }
110 
111   public void setContentType(String type) {
112     response.setContentType(type);
113   }
114 
115   public void setDateHeader(String name, long value) {
116     response.setDateHeader(name, value);
117   }
118 
119   public void setHeader(String name, String value) {
120     response.setHeader(name, value);
121   }
122 
123   public void setIntHeader(String name, int value) {
124     response.setIntHeader(name, value);
125   }
126 
127   public void setLocale(Locale locale) {
128     response.setLocale(locale);
129   }
130 
131   public void setStatus(int sc) {
132     response.setStatus(sc);
133   }
134 
135   public void setStatus(int sc, String message) {
136     response.setStatus(sc, message);
137   }
138 
139 @Override
140 public String getContentType() {
141     // TODO Auto-generated method stub
142     return null;
143 }
144 
145 @Override
146 public void setCharacterEncoding(String arg0) {
147     // TODO Auto-generated method stub
148     
149 }
150 
151 @Override
152 public void setContentLengthLong(long arg0) {
153     // TODO Auto-generated method stub
154     
155 }
156 
157 @Override
158 public int getStatus() {
159     // TODO Auto-generated method stub
160     return 0;
161 }
162 
163 @Override
164 public String getHeader(String arg0) {
165     // TODO Auto-generated method stub
166     return null;
167 }
168 
169 @Override
170 public Collection<String> getHeaders(String arg0) {
171     // TODO Auto-generated method stub
172     return null;
173 }
174 
175 @Override
176 public Collection<String> getHeaderNames() {
177     // TODO Auto-generated method stub
178     return null;
179 }
180 }
代码清单
  • ScoketInputStream
  1 package sub.connector.http;
  2 
  3 import java.io.IOException;
  4 
  5 
  6 import java.io.InputStream;
  7 import java.io.EOFException;
  8 import org.apache.catalina.util.StringManager;
  9 
 10 /**
 11  * Extends InputStream to be more efficient reading lines during HTTP
 12  * header processing.
 13  *
 14  * @author <a href="mailto:remm@apache.org">Remy Maucherat</a>
 15  * @deprecated
 16  */
 17 public class SocketInputStream extends InputStream {
 18 
 19 
 20     // -------------------------------------------------------------- Constants
 21 
 22 
 23     /**
 24      * CR.
 25      */
 26     private static final byte CR = (byte) '\r';
 27 
 28 
 29     /**
 30      * LF.
 31      */
 32     private static final byte LF = (byte) '\n';
 33 
 34 
 35     /**
 36      * SP.
 37      */
 38     private static final byte SP = (byte) ' ';
 39 
 40 
 41     /**
 42      * HT.
 43      */
 44     private static final byte HT = (byte) '\t';
 45 
 46 
 47     /**
 48      * COLON.
 49      */
 50     private static final byte COLON = (byte) ':';
 51 
 52 
 53     /**
 54      * Lower case offset.
 55      */
 56     private static final int LC_OFFSET = 'A' - 'a';
 57 
 58 
 59     /**
 60      * Internal buffer.
 61      */
 62     protected byte buf[];
 63 
 64 
 65     /**
 66      * Last valid byte.
 67      */
 68     protected int count;
 69 
 70 
 71     /**
 72      * Position in the buffer.
 73      */
 74     protected int pos;
 75 
 76 
 77     /**
 78      * Underlying input stream.
 79      */
 80     protected InputStream is;
 81 
 82 
 83     // ----------------------------------------------------------- Constructors
 84 
 85 
 86     /**
 87      * Construct a servlet input stream associated with the specified socket
 88      * input.
 89      *
 90      * @param is socket input stream
 91      * @param bufferSize size of the internal buffer
 92      */
 93     public SocketInputStream(InputStream is, int bufferSize) {
 94 
 95         this.is = is;
 96         buf = new byte[bufferSize];
 97 
 98     }
 99 
100 
101     // -------------------------------------------------------------- Variables
102 
103 
104     /**
105      * The string manager for this package.
106      */
107     protected static StringManager sm =
108         StringManager.getManager(Constants.Package);
109 
110 
111     // ----------------------------------------------------- Instance Variables
112 
113 
114     // --------------------------------------------------------- Public Methods
115 
116 
117     /**
118      * Read the request line, and copies it to the given buffer. This
119      * function is meant to be used during the HTTP request header parsing.
120      * Do NOT attempt to read the request body using it.
121      *
122      * @param requestLine Request line object
123      * @throws IOException If an exception occurs during the underlying socket
124      * read operations, or if the given buffer is not big enough to accomodate
125      * the whole line.
126      */
127     public void readRequestLine(HttpRequestLine requestLine)
128         throws IOException {
129 
130         // Recycling check
131         if (requestLine.methodEnd != 0)
132             requestLine.recycle();
133 
134         // Checking for a blank line
135         int chr = 0;
136         do { // Skipping CR or LF
137             try {
138                 chr = read();
139             } catch (IOException e) {
140                 chr = -1;
141             }
142         } while ((chr == CR) || (chr == LF));
143         if (chr == -1)
144             throw new EOFException
145                 (sm.getString("requestStream.readline.error"));
146         pos--;
147 
148         // Reading the method name
149 
150         int maxRead = requestLine.method.length;
151         int readStart = pos;
152         int readCount = 0;
153 
154         boolean space = false;
155 
156         while (!space) {
157             // if the buffer is full, extend it
158             if (readCount >= maxRead) {
159                 if ((2 * maxRead) <= HttpRequestLine.MAX_METHOD_SIZE) {
160                     char[] newBuffer = new char[2 * maxRead];
161                     System.arraycopy(requestLine.method, 0, newBuffer, 0,
162                                      maxRead);
163                     requestLine.method = newBuffer;
164                     maxRead = requestLine.method.length;
165                 } else {
166                     throw new IOException
167                         (sm.getString("requestStream.readline.toolong"));
168                 }
169             }
170             // We're at the end of the internal buffer
171             if (pos >= count) {
172                 int val = read();
173                 if (val == -1) {
174                     throw new IOException
175                         (sm.getString("requestStream.readline.error"));
176                 }
177                 pos = 0;
178                 readStart = 0;
179             }
180             if (buf[pos] == SP) {
181                 space = true;
182             }
183             requestLine.method[readCount] = (char) buf[pos];
184             readCount++;
185             pos++;
186         }
187 
188         requestLine.methodEnd = readCount - 1;
189 
190         // Reading URI
191 
192         maxRead = requestLine.uri.length;
193         readStart = pos;
194         readCount = 0;
195 
196         space = false;
197 
198         boolean eol = false;
199 
200         while (!space) {
201             // if the buffer is full, extend it
202             if (readCount >= maxRead) {
203                 if ((2 * maxRead) <= HttpRequestLine.MAX_URI_SIZE) {
204                     char[] newBuffer = new char[2 * maxRead];
205                     System.arraycopy(requestLine.uri, 0, newBuffer, 0,
206                                      maxRead);
207                     requestLine.uri = newBuffer;
208                     maxRead = requestLine.uri.length;
209                 } else {
210                     throw new IOException
211                         (sm.getString("requestStream.readline.toolong"));
212                 }
213             }
214             // We're at the end of the internal buffer
215             if (pos >= count) {
216                 int val = read();
217                 if (val == -1)
218                     throw new IOException
219                         (sm.getString("requestStream.readline.error"));
220                 pos = 0;
221                 readStart = 0;
222             }
223             if (buf[pos] == SP) {
224                 space = true;
225             } else if ((buf[pos] == CR) || (buf[pos] == LF)) {
226                 // HTTP/0.9 style request
227                 eol = true;
228                 space = true;
229             }
230             requestLine.uri[readCount] = (char) buf[pos];
231             readCount++;
232             pos++;
233         }
234 
235         requestLine.uriEnd = readCount - 1;
236 
237         // Reading protocol
238 
239         maxRead = requestLine.protocol.length;
240         readStart = pos;
241         readCount = 0;
242 
243         while (!eol) {
244             // if the buffer is full, extend it
245             if (readCount >= maxRead) {
246                 if ((2 * maxRead) <= HttpRequestLine.MAX_PROTOCOL_SIZE) {
247                     char[] newBuffer = new char[2 * maxRead];
248                     System.arraycopy(requestLine.protocol, 0, newBuffer, 0,
249                                      maxRead);
250                     requestLine.protocol = newBuffer;
251                     maxRead = requestLine.protocol.length;
252                 } else {
253                     throw new IOException
254                         (sm.getString("requestStream.readline.toolong"));
255                 }
256             }
257             // We're at the end of the internal buffer
258             if (pos >= count) {
259                 // Copying part (or all) of the internal buffer to the line
260                 // buffer
261                 int val = read();
262                 if (val == -1)
263                     throw new IOException
264                         (sm.getString("requestStream.readline.error"));
265                 pos = 0;
266                 readStart = 0;
267             }
268             if (buf[pos] == CR) {
269                 // Skip CR.
270             } else if (buf[pos] == LF) {
271                 eol = true;
272             } else {
273                 requestLine.protocol[readCount] = (char) buf[pos];
274                 readCount++;
275             }
276             pos++;
277         }
278 
279         requestLine.protocolEnd = readCount;
280 
281     }
282 
283 
284     /**
285      * Read a header, and copies it to the given buffer. This
286      * function is meant to be used during the HTTP request header parsing.
287      * Do NOT attempt to read the request body using it.
288      *
289      * @param requestLine Request line object
290      * @throws IOException If an exception occurs during the underlying socket
291      * read operations, or if the given buffer is not big enough to accomodate
292      * the whole line.
293      */
294     public void readHeader(HttpHeader header)
295         throws IOException {
296 
297         // Recycling check
298         if (header.nameEnd != 0)
299             header.recycle();
300 
301         // Checking for a blank line
302         int chr = read();
303         if ((chr == CR) || (chr == LF)) { // Skipping CR
304             if (chr == CR)
305                 read(); // Skipping LF
306             header.nameEnd = 0;
307             header.valueEnd = 0;
308             return;
309         } else {
310             pos--;
311         }
312 
313         // Reading the header name
314 
315         int maxRead = header.name.length;
316         int readStart = pos;
317         int readCount = 0;
318 
319         boolean colon = false;
320 
321         while (!colon) {
322             // if the buffer is full, extend it
323             if (readCount >= maxRead) {
324                 if ((2 * maxRead) <= HttpHeader.MAX_NAME_SIZE) {
325                     char[] newBuffer = new char[2 * maxRead];
326                     System.arraycopy(header.name, 0, newBuffer, 0, maxRead);
327                     header.name = newBuffer;
328                     maxRead = header.name.length;
329                 } else {
330                     throw new IOException
331                         (sm.getString("requestStream.readline.toolong"));
332                 }
333             }
334             // We're at the end of the internal buffer
335             if (pos >= count) {
336                 int val = read();
337                 if (val == -1) {
338                     throw new IOException
339                         (sm.getString("requestStream.readline.error"));
340                 }
341                 pos = 0;
342                 readStart = 0;
343             }
344             if (buf[pos] == COLON) {
345                 colon = true;
346             }
347             char val = (char) buf[pos];
348             if ((val >= 'A') && (val <= 'Z')) {
349                 val = (char) (val - LC_OFFSET);
350             }
351             header.name[readCount] = val;
352             readCount++;
353             pos++;
354         }
355 
356         header.nameEnd = readCount - 1;
357 
358         // Reading the header value (which can be spanned over multiple lines)
359 
360         maxRead = header.value.length;
361         readStart = pos;
362         readCount = 0;
363 
364         int crPos = -2;
365 
366         boolean eol = false;
367         boolean validLine = true;
368 
369         while (validLine) {
370 
371             boolean space = true;
372 
373             // Skipping spaces
374             // Note : Only leading white spaces are removed. Trailing white
375             // spaces are not.
376             while (space) {
377                 // We're at the end of the internal buffer
378                 if (pos >= count) {
379                     // Copying part (or all) of the internal buffer to the line
380                     // buffer
381                     int val = read();
382                     if (val == -1)
383                         throw new IOException
384                             (sm.getString("requestStream.readline.error"));
385                     pos = 0;
386                     readStart = 0;
387                 }
388                 if ((buf[pos] == SP) || (buf[pos] == HT)) {
389                     pos++;
390                 } else {
391                     space = false;
392                 }
393             }
394 
395             while (!eol) {
396                 // if the buffer is full, extend it
397                 if (readCount >= maxRead) {
398                     if ((2 * maxRead) <= HttpHeader.MAX_VALUE_SIZE) {
399                         char[] newBuffer = new char[2 * maxRead];
400                         System.arraycopy(header.value, 0, newBuffer, 0,
401                                          maxRead);
402                         header.value = newBuffer;
403                         maxRead = header.value.length;
404                     } else {
405                         throw new IOException
406                             (sm.getString("requestStream.readline.toolong"));
407                     }
408                 }
409                 // We're at the end of the internal buffer
410                 if (pos >= count) {
411                     // Copying part (or all) of the internal buffer to the line
412                     // buffer
413                     int val = read();
414                     if (val == -1)
415                         throw new IOException
416                             (sm.getString("requestStream.readline.error"));
417                     pos = 0;
418                     readStart = 0;
419                 }
420                 if (buf[pos] == CR) {
421                 } else if (buf[pos] == LF) {
422                     eol = true;
423                 } else {
424                     // FIXME : Check if binary conversion is working fine
425                     int ch = buf[pos] & 0xff;
426                     header.value[readCount] = (char) ch;
427                     readCount++;
428                 }
429                 pos++;
430             }
431 
432             int nextChr = read();
433 
434             if ((nextChr != SP) && (nextChr != HT)) {
435                 pos--;
436                 validLine = false;
437             } else {
438                 eol = false;
439                 // if the buffer is full, extend it
440                 if (readCount >= maxRead) {
441                     if ((2 * maxRead) <= HttpHeader.MAX_VALUE_SIZE) {
442                         char[] newBuffer = new char[2 * maxRead];
443                         System.arraycopy(header.value, 0, newBuffer, 0,
444                                          maxRead);
445                         header.value = newBuffer;
446                         maxRead = header.value.length;
447                     } else {
448                         throw new IOException
449                             (sm.getString("requestStream.readline.toolong"));
450                     }
451                 }
452                 header.value[readCount] = ' ';
453                 readCount++;
454             }
455 
456         }
457 
458         header.valueEnd = readCount;
459 
460     }
461 
462 
463     /**
464      * Read byte.
465      */
466     public int read()
467         throws IOException {
468         if (pos >= count) {
469             fill();
470             if (pos >= count)
471                 return -1;
472         }
473         return buf[pos++] & 0xff;
474     }
475 
476 
477     /**
478      *
479      */
480     /*
481     public int read(byte b[], int off, int len)
482         throws IOException {
483 
484     }
485     */
486 
487 
488     /**
489      *
490      */
491     /*
492     public long skip(long n)
493         throws IOException {
494 
495     }
496     */
497 
498 
499     /**
500      * Returns the number of bytes that can be read from this input
501      * stream without blocking.
502      */
503     public int available()
504         throws IOException {
505         return (count - pos) + is.available();
506     }
507 
508 
509     /**
510      * Close the input stream.
511      */
512     public void close()
513         throws IOException {
514         if (is == null)
515             return;
516         is.close();
517         is = null;
518         buf = null;
519     }
520 
521 
522     // ------------------------------------------------------ Protected Methods
523 
524 
525     /**
526      * Fill the internal buffer using data from the undelying input stream.
527      */
528     protected void fill()
529         throws IOException {
530         pos = 0;
531         count = 0;
532         int nRead = is.read(buf, 0, buf.length);
533         if (nRead > 0) {
534             count = nRead;
535         }
536     }
537 
538 
539 }
代码清单
  • HttpRequestLine
  1 package sub.connector.http;
  2 /**
  3  * HTTP request line enum type.
  4  *
  5  * @author Remy Maucherat
  6  * @version $Revision: 1.6 $ $Date: 2002/03/18 07:15:40 $
  7  * @deprecated
  8  */
  9 final class HttpRequestLine {
 10 
 11 
 12     // -------------------------------------------------------------- Constants
 13 
 14 
 15     public static final int INITIAL_METHOD_SIZE = 8;
 16     public static final int INITIAL_URI_SIZE = 64;
 17     public static final int INITIAL_PROTOCOL_SIZE = 8;
 18     public static final int MAX_METHOD_SIZE = 1024;
 19     public static final int MAX_URI_SIZE = 32768;
 20     public static final int MAX_PROTOCOL_SIZE = 1024;
 21 
 22 
 23     // ----------------------------------------------------------- Constructors
 24 
 25 
 26     public HttpRequestLine() {
 27 
 28         this(new char[INITIAL_METHOD_SIZE], 0, new char[INITIAL_URI_SIZE], 0,
 29              new char[INITIAL_PROTOCOL_SIZE], 0);
 30 
 31     }
 32 
 33 
 34     public HttpRequestLine(char[] method, int methodEnd,
 35                            char[] uri, int uriEnd,
 36                            char[] protocol, int protocolEnd) {
 37 
 38         this.method = method;
 39         this.methodEnd = methodEnd;
 40         this.uri = uri;
 41         this.uriEnd = uriEnd;
 42         this.protocol = protocol;
 43         this.protocolEnd = protocolEnd;
 44 
 45     }
 46 
 47 
 48     // ----------------------------------------------------- Instance Variables
 49 
 50 
 51     public char[] method;
 52     public int methodEnd;
 53     public char[] uri;
 54     public int uriEnd;
 55     public char[] protocol;
 56     public int protocolEnd;
 57 
 58 
 59     // ------------------------------------------------------------- Properties
 60 
 61 
 62     // --------------------------------------------------------- Public Methods
 63 
 64 
 65     /**
 66      * Release all object references, and initialize instance variables, in
 67      * preparation for reuse of this object.
 68      */
 69     public void recycle() {
 70 
 71         methodEnd = 0;
 72         uriEnd = 0;
 73         protocolEnd = 0;
 74 
 75     }
 76 
 77 
 78     /**
 79      * Test if the uri includes the given char array.
 80      */
 81     public int indexOf(char[] buf) {
 82         return indexOf(buf, buf.length);
 83     }
 84 
 85 
 86     /**
 87      * Test if the value of the header includes the given char array.
 88      */
 89     public int indexOf(char[] buf, int end) {
 90         char firstChar = buf[0];
 91         int pos = 0;
 92         while (pos < uriEnd) {
 93             pos = indexOf(firstChar, pos);
 94             if (pos == -1)
 95                 return -1;
 96             if ((uriEnd - pos) < end)
 97                 return -1;
 98             for (int i = 0; i < end; i++) {
 99                 if (uri[i + pos] != buf[i])
100                     break;
101                 if (i == (end-1))
102                     return pos;
103             }
104             pos++;
105         }
106         return -1;
107     }
108 
109 
110     /**
111      * Test if the value of the header includes the given string.
112      */
113     public int indexOf(String str) {
114         return indexOf(str.toCharArray(), str.length());
115     }
116 
117 
118     /**
119      * Returns the index of a character in the value.
120      */
121     public int indexOf(char c, int start) {
122         for (int i=start; i<uriEnd; i++) {
123             if (uri[i] == c)
124                 return i;
125         }
126         return -1;
127     }
128 
129 
130     // --------------------------------------------------------- Object Methods
131 
132 
133     public int hashCode() {
134         // FIXME
135         return 0;
136     }
137 
138 
139     public boolean equals(Object obj) {
140         return false;
141     }
142 
143 
144 }
代码清单
  • RequestStream
  1 package sub.connector;
  2 
  3 import sub.connector.http.Constants;
  4 
  5 
  6 
  7 
  8 import sub.connector.http.HttpRequest;
  9 import java.io.InputStream;
 10 import java.io.IOException;
 11 
 12 import javax.servlet.ReadListener;
 13 import javax.servlet.ServletInputStream;
 14 import org.apache.catalina.util.StringManager;
 15 
 16 
 17 /**
 18  * Convenience implementation of <b>ServletInputStream</b> that works with
 19  * the standard implementations of <b>Request</b>.  If the content length has
 20  * been set on our associated Request, this implementation will enforce
 21  * not reading more than that many bytes on the underlying stream.
 22  *
 23  * @author Craig R. McClanahan
 24  * @version $Revision: 1.6 $ $Date: 2002/03/18 07:15:39 $
 25  * @deprecated
 26  */
 27 
 28 public class RequestStream
 29     extends ServletInputStream {
 30 
 31 
 32     // ----------------------------------------------------------- Constructors
 33 
 34 
 35     /**
 36      * Construct a servlet input stream associated with the specified Request.
 37      *
 38      * @param request The associated request
 39      */
 40     public RequestStream(HttpRequest request) {
 41 
 42         super();
 43         closed = false;
 44         count = 0;
 45         length = request.getContentLength();
 46         stream = request.getStream();
 47 
 48     }
 49 
 50 
 51     // ----------------------------------------------------- Instance Variables
 52 
 53 
 54     /**
 55      * Has this stream been closed?
 56      */
 57     protected boolean closed = false;
 58 
 59 
 60     /**
 61      * The number of bytes which have already been returned by this stream.
 62      */
 63     protected int count = 0;
 64 
 65 
 66     /**
 67      * The content length past which we will not read, or -1 if there is
 68      * no defined content length.
 69      */
 70     protected int length = -1;
 71 
 72 
 73     /**
 74      * The localized strings for this package.
 75      */
 76     protected static StringManager sm =
 77         StringManager.getManager(Constants.Package);
 78 
 79 
 80     /**
 81      * The underlying input stream from which we should read data.
 82      */
 83     protected InputStream stream = null;
 84 
 85 
 86     // --------------------------------------------------------- Public Methods
 87 
 88 
 89     /**
 90      * Close this input stream.  No physical level I-O is performed, but
 91      * any further attempt to read from this stream will throw an IOException.
 92      * If a content length has been set but not all of the bytes have yet been
 93      * consumed, the remaining bytes will be swallowed.
 94      */
 95     public void close() throws IOException {
 96 
 97         if (closed)
 98             throw new IOException(sm.getString("requestStream.close.closed"));
 99 
100         if (length > 0) {
101             while (count < length) {
102                 int b = read();
103                 if (b < 0)
104                     break;
105             }
106         }
107 
108         closed = true;
109 
110     }
111 
112 
113 
114     /**
115      * Read and return a single byte from this input stream, or -1 if end of
116      * file has been encountered.
117      *
118      * @exception IOException if an input/output error occurs
119      */
120     public int read() throws IOException {
121 
122         // Has this stream been closed?
123         if (closed)
124             throw new IOException(sm.getString("requestStream.read.closed"));
125 
126         // Have we read the specified content length already?
127         if ((length >= 0) && (count >= length))
128             return (-1);        // End of file indicator
129 
130         // Read and count the next byte, then return it
131         int b = stream.read();
132         if (b >= 0)
133             count++;
134         return (b);
135 
136     }
137 
138 
139     /**
140      * Read some number of bytes from the input stream, and store them
141      * into the buffer array b.  The number of bytes actually read is
142      * returned as an integer.  This method blocks until input data is
143      * available, end of file is detected, or an exception is thrown.
144      *
145      * @param b The buffer into which the data is read
146      *
147      * @exception IOException if an input/output error occurs
148      */
149     public int read(byte b[]) throws IOException {
150 
151         return (read(b, 0, b.length));
152 
153     }
154 
155 
156     /**
157      * Read up to <code>len</code> bytes of data from the input stream
158      * into an array of bytes.  An attempt is made to read as many as
159      * <code>len</code> bytes, but a smaller number may be read,
160      * possibly zero.  The number of bytes actually read is returned as
161      * an integer.  This method blocks until input data is available,
162      * end of file is detected, or an exception is thrown.
163      *
164      * @param b The buffer into which the data is read
165      * @param off The start offset into array <code>b</code> at which
166      *  the data is written
167      * @param len The maximum number of bytes to read
168      *
169      * @exception IOException if an input/output error occurs
170      */
171     public int read(byte b[], int off, int len) throws IOException {
172 
173         int toRead = len;
174         if (length > 0) {
175             if (count >= length)
176                 return (-1);
177             if ((count + len) > length)
178                 toRead = length - count;
179         }
180         int actuallyRead = super.read(b, off, toRead);
181         return (actuallyRead);
182 
183     }
184 
185 
186 
187     @Override
188     public boolean isFinished() {
189         // TODO Auto-generated method stub
190         return false;
191     }
192 
193 
194 
195     @Override
196     public boolean isReady() {
197         // TODO Auto-generated method stub
198         return false;
199     }
200 
201 
202 
203     @Override
204     public void setReadListener(ReadListener arg0) {
205         // TODO Auto-generated method stub
206         
207     }
208 
209 
210 }
代码清单
  • ResponseStream
代码清单
  • ResponseWriter
  1 package sub.connector;
  2 
  3 import java.io.OutputStreamWriter;
  4 import java.io.PrintWriter;
  5 
  6 /**
  7  * A subclass of PrintWriter that automatically flushes each time
  8  * a print() or println() method is called.
  9  */
 10 
 11 public class ResponseWriter extends PrintWriter {
 12 
 13   public ResponseWriter(OutputStreamWriter writer) {
 14     super(writer);
 15   }
 16 
 17   public void print(boolean b) {
 18     super.print(b);
 19     super.flush();
 20   }
 21 
 22   public void print(char c) {
 23     super.print(c);
 24     super.flush();
 25   }
 26 
 27   public void print(char ca[]) {
 28     super.print(ca);
 29     super.flush();
 30   }
 31 
 32   public void print(double d) {
 33     super.print(d);
 34     super.flush();
 35   }
 36 
 37   public void print(float f) {
 38     super.print(f);
 39     super.flush();
 40   }
 41 
 42   public void print(int i) {
 43     super.print(i);
 44     super.flush();
 45   }
 46 
 47   public void print(long l) {
 48     super.print(l);
 49     super.flush();
 50   }
 51 
 52   public void print(Object o) {
 53     super.print(o);
 54     super.flush();
 55   }
 56 
 57   public void print(String s) {
 58     super.print(s);
 59     super.flush();
 60   }
 61 
 62   public void println() {
 63     super.println();
 64     super.flush();
 65   }
 66 
 67   public void println(boolean b) {
 68     super.println(b);
 69     super.flush();
 70   }
 71 
 72   public void println(char c) {
 73     super.println(c);
 74     super.flush();
 75   }
 76 
 77   public void println(char ca[]) {
 78     super.println(ca);
 79     super.flush();
 80   }
 81 
 82   public void println(double d) {
 83     super.println(d);
 84     super.flush();
 85   }
 86 
 87   public void println(float f) {
 88     super.println(f);
 89     super.flush();
 90   }
 91 
 92   public void println(int i) {
 93     super.println(i);
 94     super.flush();
 95   }
 96 
 97   public void println(long l) {
 98     super.println(l);
 99     super.flush();
100   }
101 
102   public void println(Object o) {
103     super.println(o);
104     super.flush();
105   }
106 
107   public void println(String s) {
108     super.println(s);
109     super.flush();
110   }
111 
112   public void write(char c) {
113     super.write(c);
114     super.flush();
115   }
116 
117   public void write(char ca[]) {
118     super.write(ca);
119     super.flush();
120   }
121 
122   public void write(char ca[], int off, int len) {
123     super.write(ca, off, len);
124     super.flush();
125   }
126 
127   public void write(String s) {
128     super.write(s);
129     super.flush();
130   }
131 
132   public void write(String s, int off, int len) {
133     super.write(s, off, len);
134     super.flush();
135   }
136 }
代码清单
  • ServletProcessor
 1 package sub;
 2 import sub.connector.http.Constants;
 3 import sub.connector.http.HttpRequest;
 4 import sub.connector.http.HttpResponse;
 5 import sub.connector.http.HttpRequestFacade;
 6 import sub.connector.http.HttpResponseFacade;
 7 
 8 import java.io.File;
 9 import java.io.IOException;
10 import java.net.URL;
11 import java.net.URLClassLoader;
12 import java.net.URLStreamHandler;
13 import javax.servlet.Servlet;
14 /**
15  * servlet处理器负责动态加载servlet组件,并管理servlet的生命周期,传递res、req给其。
16  * */
17 public class ServletProcessor{
18 
19   public void process(HttpRequest request, HttpResponse response) {
20 
21     String uri = request.getRequestURI();
22     String servletName = uri.substring(uri.lastIndexOf("/") + 1);
23     URLClassLoader loader = null;
24     try {
25       // create a URLClassLoader
26       URL[] urls = new URL[1];
27       URLStreamHandler streamHandler = null;
28       File classPath = new File(Constants.WEB_ROOT);
29       String repository = (new URL("file", null, classPath.getCanonicalPath() + File.separator)).toString() ;
30       urls[0] = new URL(null, repository, streamHandler);
31       loader = new URLClassLoader(urls);
32     }
33     catch (IOException e) {
34       System.out.println(e.toString() );
35     }
36     Class myClass = null;
37     try {
38       myClass = loader.loadClass(servletName);
39     }
40     catch (ClassNotFoundException e) {
41       System.out.println(e.toString());
42     }
43     
44     Servlet servlet = null;
45 
46     try {
47       servlet = (Servlet) myClass.newInstance();
48       HttpRequestFacade requestFacade = new HttpRequestFacade(request);
49       HttpResponseFacade responseFacade = new HttpResponseFacade(response);
50       servlet.service(requestFacade, responseFacade);
51       ((HttpResponse) response).finishResponse();
52     }
53     catch (Exception e) {
54       System.out.println(e.toString());
55     }
56     catch (Throwable e) {
57       System.out.println(e.toString());
58     }
59   }
60 }
View Code
  • StaticResourceProcessor
 1 package sub;
 2 import sub.connector.http.HttpRequest;
 3 import sub.connector.http.HttpResponse;
 4 import java.io.IOException;
 5 
 6 public class StaticResourceProcessor {
 7 
 8   public void process(HttpRequest request, HttpResponse response) {
 9     try {
10       response.sendStaticResource();
11     }
12     catch (IOException e) {
13       e.printStackTrace();
14     }
15   }
16 
17 }
View Code
posted @ 2018-06-22 22:20  10000miles  阅读(244)  评论(0)    收藏  举报