《How Tomcat Works》读书笔记(三)--Connector(连接器)
这是《How Tomcat Works》第三四章的读书笔记。主要写了Tomcat4.0默认的连接器(Connector)的处理流程,后面Tomcat的连接器改为Coyote。
1. 概述
1.1 架构
- HttpConector:监听Http请求、维护HttpProcessor对象池、处理Http请求(调用HttpProcessor对象进行处理)
- HttpProcessor:解析请求(解析连接、解析请求行、解析请求头等等)、调用容器进行处理
- Request:表示Http请求,实现了org.apache.catalina.Request接口。
- Response:表示Http响应,实现了org.apache.catalina.Response接口。
其中Request、Response就是代表Http请求、Http响应,实现了Servlet编程中HttpServletRequest、HttpServletResponse接口,这样符合Java EE编程标准。只是Tomcat在这里使用了许多的类、接口等等(如:RequestBase、HttpRequestImpl、RequestFacade),这样做就像Java Util包中哪些类库一样,反正看起来好复杂。
1.2 HttpProcessor处理逻辑
只是展示逻辑,省略一些具体的处理方式,省略了try-catch等等。
1 /** 2 * Process an incoming HTTP request on the Socket that has been assigned 3 * to this Processor. Any exceptions that occur during processing must be 4 * swallowed and dealt with. 5 * 6 * @param socket The socket on which we are connected to the client 7 */ 8 private void process(Socket socket) { 9 boolean ok = true; 10 boolean finishResponse = true; 11 SocketInputStream input = null; 12 13 // Construct and initialize the objects we will need 14 // 构造对象,这里省略的许多的try-catch 15 input = new SocketInputStream(socket.getInputStream(), connector.getBufferSize()); 16 // Http/1.1中新特性:长连接 17 keepAlive = true; 18 while (!stopped && ok && keepAlive) { 19 finishResponse = true; 20 request.setStream(input); 21 request.setResponse(response); 22 output = socket.getOutputStream(); 23 response.setStream(output); 24 response.setRequest(request); 25 ((HttpServletResponse) response.getResponse()).setHeader("Server", Constants.ServerInfo); 26 27 // Parse the incoming request 28 // 解析请求数据 29 // 解析连接 30 parseConnection(socket); 31 // 解析请求行 32 parseRequest(input, output); 33 if (!request.getRequest().getProtocol().startsWith("HTTP/0")) 34 //解析请求头 35 parseHeaders(input); 36 if (http11) { 37 // Sending a request acknowledge back to the client if 38 // requested. 39 ackRequest(output); 40 // If the protocol is HTTP/1.1, chunking is allowed. 41 if (connector.isChunkingAllowed()) 42 response.setAllowChunking(true); 43 } 44 45 // Ask our Container to process this request 46 // 调用Servlet容器处理请求 47 ((HttpServletResponse) response).addDateHeader("Date", System.currentTimeMillis()); 48 connector.getContainer().invoke(request, response); 49 50 // Finish up the handling of the request 51 response.finishResponse(); 52 request.finishRequest(); 53 54 // Recycling the request and the response objects 55 // 回收Request、Response对象:把该对象的状态复原使得下一次请求有自己独有的状态 56 request.recycle(); 57 response.recycle(); 58 } 59 }
2. 一些解释
2.1 有状态的对象线程池
有状态的对象线程池:池中每个对象有一个自己的线程,每个对象有自己的状态(域)。
Connector(连接器)中HttpConnector接受请求,调用HttpProcessor对象处理请求。HttpConnector管理一系列的HttpProcessor对象,每个HttpProcessor对象有自己单独的后台线程,这样每次都使用一个线程处理请求。
HttpConnector在最开始就启动池中所有的HttpProcessor对象,然后有请求来时从池中拿一个HttpProcessor对象进行处理。
1 public void run() { 2 // Loop until we receive a shutdown command 3 while (!stopped) { 4 // Accept the next incoming connection from the server socket 5 Socket socket = null; 6 // Hand this socket off to an appropriate processor 7 // 从池中拿一个HttpProcessor 8 HttpProcessor processor = createProcessor(); 9 // 调用HttpProcessor进行处理 10 processor.assign(socket); 11 } 12 }
HttpProcessor对象一开始就全部启动,等待HttpConnector分配socket进行处理。
1 public void run() { 2 // Process requests until we receive a shutdown signal 3 while (!stopped) { 4 // Wait for the next socket to be assigned 5 // 在这里HttpProcessor对象会阻塞直到HttpConnector分配一个socket 6 Socket socket = await(); 7 if (socket == null) 8 continue; 9 // Process the request from this socket 10 // 进行处理 11 process(socket); 12 // Finish up this request 13 // 处理完成,把该HttpProcessor放回HttpProcessor对象池中 14 connector.recycle(this); 15 } 16 }
HttpProcessor对象一开始就全部启动,然后会被阻塞(如上所示)直到HttpConnector分配socket。await()与assign(Socket socket)方法如下:
1 /** 2 * The socket we are currently processing a request for. This object 3 * is used for inter-thread communication only. 4 */ 5 private Socket socket = null; 6 7 /** 8 * Is there a new socket available? 9 */ 10 private boolean available = false; 11 12 /** 13 * Process an incoming TCP/IP connection on the specified socket. Any 14 * exception that occurs during processing must be logged and swallowed. 15 * NOTE: This method is called from our Connector's thread. We 16 * must assign it to our own thread so that multiple simultaneous 17 * requests can be handled. 18 * 19 * @param socket TCP socket to process 20 */ 21 synchronized void assign(Socket socket) { 22 // Wait for the Processor to get the previous Socket 23 // 如果已经分配,则等待 24 while (available) { 25 try { 26 wait(); 27 } catch (InterruptedException e) { 28 } 29 } 30 // Store the newly available Socket and notify our thread、 31 // 分配socket 32 this.socket = socket; 33 available = true; 34 notifyAll(); 35 } 36 37 /** 38 * Await a newly assigned Socket from our Connector, or null 39 * if we are supposed to shut down. 40 */ 41 private synchronized Socket await() { 42 // Wait for the Connector to provide a new Socket 43 // 如果没有分配,则等待 44 while (!available) { 45 try { 46 wait(); 47 } catch (InterruptedException e) { 48 } 49 } 50 // Notify the Connector that we have received this Socket 51 // 把分配的socket返回 52 Socket socket = this.socket; 53 available = false; 54 notifyAll(); 55 return socket; 56 }
最后每一次的Request、Response对象状态是不一样的,所以在处理完完成后,需要把Request、Response对象状态还原。
1 // Recycling the request and the response objects 2 request.recycle(); 3 response.recycle();
2.2 解析处理
HttpProcessor解析过程是一个耗时的过程,尤其是解析请求参数、Cookies时,所有Tomcat中设计为仅仅我们需要使用Parameter、Cookies时才解析。我们以Parameter为例:
在需要使用Parameter方法时(如:getParameter()方法)时,就验证是否需要解析,如果没有解析就解析,否则直接使用。
1 /** 2 * The parsed parameters for this request. This is populated only if 3 * parameter information is requested via one of the 4 * getParameter() family of method calls. The key is the 5 * parameter name, while the value is a String array of values for this 6 * parameter. 7 * 8 * IMPLEMENTATION NOTE - Once the parameters for a 9 * particular request are parsed and stored here, they are not modified. 10 * Therefore, application level access to the parameters need not be 11 * synchronized. 12 * 存放Parameter,继承HashMap,与HashMap基本无异 13 */ 14 protected ParameterMap parameters = null; 15 16 /** 17 * Have the parameters for this request been parsed yet? 18 * 是否已经解析 19 */ 20 protected boolean parsed = false; 21 22 /** 23 * Parse the parameters of this request, if it has not already occurred. 24 * If parameters are present in both the query string and the request 25 * content, they are merged. 26 */ 27 protected void parseParameters() { 28 if (parsed) 29 return; 30 ParameterMap results = parameters; 31 // 具体解析逻辑就不给出来了 32 33 // Store the final results 34 parsed = true; 35 parameters = results; 36 } 37 38 public String getParameter(String name) { 39 parseParameters(); 40 String values[] = (String[]) parameters.get(name); 41 if (values != null) 42 return (values[0]); 43 else 44 return (null); 45 }
3. 代码
逻辑基本一致,但是自己省略了需要的具体逻辑,如仅仅解析了RequestURL等等。然后许多与Request的有关的类,我仅仅使用了HttpRequest全部代替了。
Container、Connector接口:
1 package note2; 2 3 import javax.servlet.http.HttpServletRequest; 4 import javax.servlet.http.HttpServletResponse; 5 6 /** 7 * Created by kanyuxia on 2017/4/27. 8 * 模拟org.apache.catalina.Connector接口 9 */ 10 public interface Connector { 11 /** 12 * Return the Container used for processing requests received by this 13 * Connector. 14 */ 15 Container getContainer(); 16 17 /** 18 * Set the Container used for processing requests received by this 19 * Connector. 20 * 21 * @param container The new Container to use 22 */ 23 void setContainer(Container container); 24 25 /** 26 * Return the scheme that will be assigned to requests received 27 * through this connector. Default value is "http". 28 */ 29 String getScheme(); 30 31 /** 32 * Set the scheme that will be assigned to requests received through 33 * this connector. 34 * 35 * @param scheme The new scheme 36 */ 37 void setScheme(String scheme); 38 39 /** 40 * Create (or allocate) and return a Request object suitable for 41 * specifying the contents of a Request to the responsible Container. 42 */ 43 HttpServletRequest createRequest(); 44 45 /** 46 * Create (or allocate) and return a Response object suitable for 47 * receiving the contents of a Response from the responsible Container. 48 */ 49 HttpServletResponse createResponse(); 50 51 /** 52 * Invoke a pre-startup initialization. This is used to allow connectors 53 * to bind to restricted ports under Unix operating environments. 54 */ 55 void initialize(); 56 57 } 58 59 package note2; 60 61 import javax.servlet.ServletException; 62 import java.io.IOException; 63 64 /** 65 * Created by kanyuxia on 2017/4/27. 66 * 模拟org.apache.catalina.Container接口 67 */ 68 public interface Container { 69 /** 70 * Process the specified Request, and generate the corresponding Response, 71 * according to the design of this particular Container. 72 * 73 * @param request Request to be processed 74 * @param response Response to be produced 75 * 76 * @exception IOException if an input/output error occurred while 77 * processing 78 * @exception ServletException if a ServletException was thrown 79 * while processing this request 80 */ 81 void invoke(HttpRequest request, HttpResponse response) throws IOException, ServletException; 82 }
Request、Response相关类:
1 package note2; 2 3 import javax.servlet.*; 4 import javax.servlet.http.*; 5 import java.io.BufferedReader; 6 import java.io.IOException; 7 import java.io.InputStream; 8 import java.io.UnsupportedEncodingException; 9 import java.security.Principal; 10 import java.util.*; 11 12 /** 13 * Created by kanyuxia on 2017/4/26. 14 * Http请求对象 15 */ 16 public class HttpRequest implements HttpServletRequest { 17 18 // ---------------------------------Http Request Infomations 19 /** 20 * 存放Http request headers 21 */ 22 private HashMap<String, ArrayList<String>> headers = new HashMap<>(); 23 24 /** 25 * 存放Http request cookies 26 */ 27 private ArrayList<Cookie> cookies = new ArrayList<>(); 28 29 /** 30 * 存放Http请求参数:Query String or Form datas. 31 * 只有当Servlet取参数时,才解析 32 */ 33 private ParameterMap<String, String[]> parameterMap = null; 34 35 /** 36 * Have the parameters for this request been parsed yet? 37 * 是否解析了Http Parameters 38 */ 39 private boolean parameterPared = false; 40 41 /** 42 * The request URI associated with this request. 43 * 请求URL地址 44 */ 45 private String requestURI = null; 46 47 48 /** 49 * The input stream associated with this Request. 50 */ 51 private InputStream input = null; 52 53 54 // ---------------------------------------Servlet some infomations 55 56 /** 57 * The request attributes for this request. 58 */ 59 private final HashMap<String, Object> attributes = new HashMap<>(); 60 61 /** 62 * The Connector through which this Request was received. 63 */ 64 private Connector connector = null; 65 66 67 // --------------------------------------Some methods 68 /** 69 * 添加HTTP header 70 * @param name header name 71 * @param value header value 72 */ 73 public void addHeader(String name, String value) { 74 name = name.toLowerCase(); 75 ArrayList<String> values = headers.get(name); 76 if (values != null) { 77 values.add(value); 78 } 79 values = new ArrayList<>(); 80 headers.put(name, values); 81 } 82 83 /** 84 * 返回门面类 85 * @return RequestFacade 86 */ 87 public HttpServletRequest getRequest() { 88 return new HttpRequestFacade(this); 89 } 90 91 /** 92 * 添加HTTP cookie 93 * @param cookie http cookie 94 */ 95 public void addCookie(Cookie cookie) { 96 cookies.add(cookie); 97 } 98 99 /** 100 * 解析HTTP Parameters,如果已经解析则返回。 101 */ 102 public void parseParameters() { 103 if (parameterPared) { 104 return; 105 } 106 parameterMap = new ParameterMap<>(); 107 parameterMap.setLocked(false); 108 109 // 解析Query String or Form data 110 111 parameterMap.setLocked(true); 112 } 113 114 /** 115 * 添加HTTP Parameter 116 * @param name Http Parameter name 117 * @param values Http Parameter values 118 */ 119 public void addParameter(String name, String values[]) { 120 parameterMap.put(name, values); 121 } 122 123 124 /** 125 * Release all object references, and initialize instance variables, in 126 * preparation for reuse of this object. 127 * 清空所有数据 128 */ 129 public void recycle() { 130 headers.clear(); 131 cookies.clear(); 132 if (parameterMap != null) { 133 parameterMap.setLocked(false); 134 parameterMap.clear(); 135 } 136 parameterPared = false; 137 requestURI = null; 138 input = null; 139 attributes.clear(); 140 } 141 142 //---------------------------some setter、getter methods 143 144 public Connector getConnector() { 145 return connector; 146 } 147 148 public void setConnector(Connector connector) { 149 this.connector = connector; 150 } 151 152 public void setInput(InputStream input) { 153 this.input = input; 154 } 155 156 public InputStream getInput() { 157 return input; 158 } 159 160 public void setRequestURI(String requestURI) { 161 this.requestURI = requestURI; 162 } 163 164 @Override 165 public String getAuthType() { 166 return null; 167 } 168 169 @Override 170 public Cookie[] getCookies() { 171 return new Cookie[0]; 172 } 173 174 @Override 175 public long getDateHeader(String name) { 176 return 0; 177 } 178 179 @Override 180 public String getHeader(String name) { 181 return null; 182 } 183 184 @Override 185 public Enumeration<String> getHeaders(String name) { 186 return null; 187 } 188 189 @Override 190 public Enumeration<String> getHeaderNames() { 191 return null; 192 } 193 194 @Override 195 public int getIntHeader(String name) { 196 return 0; 197 } 198 199 @Override 200 public String getMethod() { 201 return null; 202 } 203 204 @Override 205 public String getPathInfo() { 206 return null; 207 } 208 209 @Override 210 public String getPathTranslated() { 211 return null; 212 } 213 214 @Override 215 public String getContextPath() { 216 return null; 217 } 218 219 @Override 220 public String getQueryString() { 221 return null; 222 } 223 224 @Override 225 public String getRemoteUser() { 226 return null; 227 } 228 229 @Override 230 public boolean isUserInRole(String role) { 231 return false; 232 } 233 234 @Override 235 public Principal getUserPrincipal() { 236 return null; 237 } 238 239 @Override 240 public String getRequestedSessionId() { 241 return null; 242 } 243 244 @Override 245 public String getRequestURI() { 246 return requestURI; 247 } 248 249 @Override 250 public StringBuffer getRequestURL() { 251 return null; 252 } 253 254 @Override 255 public String getServletPath() { 256 return null; 257 } 258 259 @Override 260 public HttpSession getSession(boolean create) { 261 return null; 262 } 263 264 @Override 265 public HttpSession getSession() { 266 return null; 267 } 268 269 @Override 270 public String changeSessionId() { 271 return null; 272 } 273 274 @Override 275 public boolean isRequestedSessionIdValid() { 276 return false; 277 } 278 279 @Override 280 public boolean isRequestedSessionIdFromCookie() { 281 return false; 282 } 283 284 @Override 285 public boolean isRequestedSessionIdFromURL() { 286 return false; 287 } 288 289 @Override 290 public boolean isRequestedSessionIdFromUrl() { 291 return false; 292 } 293 294 @Override 295 public boolean authenticate(HttpServletResponse response) throws IOException, ServletException { 296 return false; 297 } 298 299 @Override 300 public void login(String username, String password) throws ServletException { 301 302 } 303 304 @Override 305 public void logout() throws ServletException { 306 307 } 308 309 @Override 310 public Collection<Part> getParts() throws IOException, ServletException { 311 return null; 312 } 313 314 @Override 315 public Part getPart(String name) throws IOException, ServletException { 316 return null; 317 } 318 319 @Override 320 public <T extends HttpUpgradeHandler> T upgrade(Class<T> handlerClass) throws IOException, ServletException { 321 return null; 322 } 323 324 @Override 325 public Object getAttribute(String name) { 326 return null; 327 } 328 329 @Override 330 public Enumeration<String> getAttributeNames() { 331 return null; 332 } 333 334 @Override 335 public String getCharacterEncoding() { 336 return null; 337 } 338 339 @Override 340 public void setCharacterEncoding(String env) throws UnsupportedEncodingException { 341 342 } 343 344 @Override 345 public int getContentLength() { 346 return 0; 347 } 348 349 @Override 350 public long getContentLengthLong() { 351 return 0; 352 } 353 354 @Override 355 public String getContentType() { 356 return null; 357 } 358 359 @Override 360 public ServletInputStream getInputStream() throws IOException { 361 return null; 362 } 363 364 @Override 365 public String getParameter(String name) { 366 parseParameters(); 367 return parameterMap.get(name)[0]; 368 } 369 370 @Override 371 public Enumeration<String> getParameterNames() { 372 parseParameters(); 373 return new Enumerator<>(parameterMap.keySet()); 374 } 375 376 @Override 377 public String[] getParameterValues(String name) { 378 parseParameters(); 379 return parameterMap.get(name); 380 } 381 382 @Override 383 public Map<String, String[]> getParameterMap() { 384 parseParameters(); 385 return parameterMap; 386 } 387 388 @Override 389 public String getProtocol() { 390 return null; 391 } 392 393 @Override 394 public String getScheme() { 395 return null; 396 } 397 398 @Override 399 public String getServerName() { 400 return null; 401 } 402 403 @Override 404 public int getServerPort() { 405 return 0; 406 } 407 408 @Override 409 public BufferedReader getReader() throws IOException { 410 return null; 411 } 412 413 @Override 414 public String getRemoteAddr() { 415 return null; 416 } 417 418 @Override 419 public String getRemoteHost() { 420 return null; 421 } 422 423 @Override 424 public void setAttribute(String name, Object o) { 425 426 } 427 428 @Override 429 public void removeAttribute(String name) { 430 431 } 432 433 @Override 434 public Locale getLocale() { 435 return null; 436 } 437 438 @Override 439 public Enumeration<Locale> getLocales() { 440 return null; 441 } 442 443 @Override 444 public boolean isSecure() { 445 return false; 446 } 447 448 @Override 449 public RequestDispatcher getRequestDispatcher(String path) { 450 return null; 451 } 452 453 @Override 454 public String getRealPath(String path) { 455 return null; 456 } 457 458 @Override 459 public int getRemotePort() { 460 return 0; 461 } 462 463 @Override 464 public String getLocalName() { 465 return null; 466 } 467 468 @Override 469 public String getLocalAddr() { 470 return null; 471 } 472 473 @Override 474 public int getLocalPort() { 475 return 0; 476 } 477 478 @Override 479 public ServletContext getServletContext() { 480 return null; 481 } 482 483 @Override 484 public AsyncContext startAsync() throws IllegalStateException { 485 return null; 486 } 487 488 @Override 489 public AsyncContext startAsync(ServletRequest servletRequest, ServletResponse servletResponse) throws IllegalStateException { 490 return null; 491 } 492 493 @Override 494 public boolean isAsyncStarted() { 495 return false; 496 } 497 498 @Override 499 public boolean isAsyncSupported() { 500 return false; 501 } 502 503 @Override 504 public AsyncContext getAsyncContext() { 505 return null; 506 } 507 508 @Override 509 public DispatcherType getDispatcherType() { 510 return null; 511 } 512 } 513 514 package note2; 515 516 import javax.servlet.ServletOutputStream; 517 import javax.servlet.ServletResponse; 518 import javax.servlet.http.Cookie; 519 import javax.servlet.http.HttpServletResponse; 520 import java.io.IOException; 521 import java.io.OutputStream; 522 import java.io.PrintWriter; 523 import java.util.ArrayList; 524 import java.util.Collection; 525 import java.util.HashMap; 526 import java.util.Locale; 527 528 /** 529 * Created by kanyuxia on 2017/4/26. 530 * Http响应对象 531 */ 532 public class HttpResponse implements HttpServletResponse { 533 // ----------------------Some Response Information 534 /** 535 * 存放Http response headers 536 */ 537 private HashMap<String, ArrayList<String>> headers = new HashMap<>(); 538 539 /** 540 * 存放Http response cookies 541 */ 542 private ArrayList<Cookie> cookies = new ArrayList<>(); 543 /** 544 * The Connector through which this Response was received. 545 */ 546 private Connector connector = null; 547 548 private OutputStream output = null; 549 550 private HttpRequest httpRequest = null; 551 552 // ------------------some methods 553 554 public void recycle() { 555 headers.clear(); 556 cookies.clear(); 557 output = null; 558 httpRequest = null; 559 } 560 561 public HttpServletResponse getResponse() { 562 return new HttpResponseFacade(this); 563 } 564 565 // ------------------some setter、getter methods 566 public Connector getConnector() { 567 return connector; 568 } 569 570 public void setConnector(Connector connector) { 571 this.connector = connector; 572 } 573 574 public void setOutput(OutputStream output) { 575 this.output = output; 576 } 577 578 public HttpRequest getHttpRequest() { 579 return httpRequest; 580 } 581 582 public void setHttpRequest(HttpRequest httpRequest) { 583 this.httpRequest = httpRequest; 584 } 585 586 @Override 587 public void addCookie(Cookie cookie) { 588 589 } 590 591 @Override 592 public boolean containsHeader(String name) { 593 return false; 594 } 595 596 @Override 597 public String encodeURL(String url) { 598 return null; 599 } 600 601 @Override 602 public String encodeRedirectURL(String url) { 603 return null; 604 } 605 606 @Override 607 public String encodeUrl(String url) { 608 return null; 609 } 610 611 @Override 612 public String encodeRedirectUrl(String url) { 613 return null; 614 } 615 616 @Override 617 public void sendError(int sc, String msg) throws IOException { 618 619 } 620 621 @Override 622 public void sendError(int sc) throws IOException { 623 624 } 625 626 @Override 627 public void sendRedirect(String location) throws IOException { 628 629 } 630 631 @Override 632 public void setDateHeader(String name, long date) { 633 634 } 635 636 @Override 637 public void addDateHeader(String name, long date) { 638 639 } 640 641 @Override 642 public void setHeader(String name, String value) { 643 644 } 645 646 @Override 647 public void addHeader(String name, String value) { 648 649 } 650 651 @Override 652 public void setIntHeader(String name, int value) { 653 654 } 655 656 @Override 657 public void addIntHeader(String name, int value) { 658 659 } 660 661 @Override 662 public void setStatus(int sc) { 663 664 } 665 666 @Override 667 public void setStatus(int sc, String sm) { 668 669 } 670 671 @Override 672 public int getStatus() { 673 return 0; 674 } 675 676 @Override 677 public String getHeader(String name) { 678 return null; 679 } 680 681 @Override 682 public Collection<String> getHeaders(String name) { 683 return null; 684 } 685 686 @Override 687 public Collection<String> getHeaderNames() { 688 return null; 689 } 690 691 @Override 692 public String getCharacterEncoding() { 693 return null; 694 } 695 696 @Override 697 public String getContentType() { 698 return null; 699 } 700 701 @Override 702 public ServletOutputStream getOutputStream() throws IOException { 703 return null; 704 } 705 706 @Override 707 public PrintWriter getWriter() throws IOException { 708 return new PrintWriter(output); 709 } 710 711 @Override 712 public void setCharacterEncoding(String charset) { 713 714 } 715 716 @Override 717 public void setContentLength(int len) { 718 719 } 720 721 @Override 722 public void setContentLengthLong(long len) { 723 724 } 725 726 @Override 727 public void setContentType(String type) { 728 729 } 730 731 @Override 732 public void setBufferSize(int size) { 733 734 } 735 736 @Override 737 public int getBufferSize() { 738 return 0; 739 } 740 741 @Override 742 public void flushBuffer() throws IOException { 743 744 } 745 746 @Override 747 public void resetBuffer() { 748 749 } 750 751 @Override 752 public boolean isCommitted() { 753 return false; 754 } 755 756 @Override 757 public void reset() { 758 759 } 760 761 @Override 762 public void setLocale(Locale loc) { 763 764 } 765 766 @Override 767 public Locale getLocale() { 768 return null; 769 } 770 } 771 772 package note2; 773 774 import javax.servlet.*; 775 import javax.servlet.http.*; 776 import java.io.BufferedReader; 777 import java.io.IOException; 778 import java.io.UnsupportedEncodingException; 779 import java.security.Principal; 780 import java.util.Collection; 781 import java.util.Enumeration; 782 import java.util.Locale; 783 import java.util.Map; 784 785 /** 786 * Created by kanyuxia on 2017/5/3. 787 */ 788 public class HttpRequestFacade implements HttpServletRequest { 789 790 private HttpServletRequest httpServletRequest; 791 792 HttpRequestFacade(HttpServletRequest httpServletRequest) { 793 this.httpServletRequest = httpServletRequest; 794 } 795 796 @Override 797 public Object getAttribute(String name) { 798 return httpServletRequest.getAttribute(name); 799 } 800 801 @Override 802 public Enumeration<String> getAttributeNames() { 803 return httpServletRequest.getAttributeNames(); 804 } 805 806 @Override 807 public String getCharacterEncoding() { 808 return httpServletRequest.getCharacterEncoding(); 809 } 810 811 @Override 812 public void setCharacterEncoding(String env) throws UnsupportedEncodingException { 813 httpServletRequest.setCharacterEncoding(env); 814 } 815 816 @Override 817 public int getContentLength() { 818 return httpServletRequest.getContentLength(); 819 } 820 821 @Override 822 public long getContentLengthLong() { 823 return httpServletRequest.getContentLengthLong(); 824 } 825 826 @Override 827 public String getContentType() { 828 return httpServletRequest.getContentType(); 829 } 830 831 @Override 832 public ServletInputStream getInputStream() throws IOException { 833 return httpServletRequest.getInputStream(); 834 } 835 836 @Override 837 public String getParameter(String name) { 838 return httpServletRequest.getParameter(name); 839 } 840 841 @Override 842 public Enumeration<String> getParameterNames() { 843 return httpServletRequest.getParameterNames(); 844 } 845 846 @Override 847 public String[] getParameterValues(String name) { 848 return httpServletRequest.getParameterValues(name); 849 } 850 851 @Override 852 public Map<String, String[]> getParameterMap() { 853 return httpServletRequest.getParameterMap(); 854 } 855 856 @Override 857 public String getProtocol() { 858 return httpServletRequest.getProtocol(); 859 } 860 861 @Override 862 public String getScheme() { 863 return httpServletRequest.getScheme(); 864 } 865 866 @Override 867 public String getServerName() { 868 return httpServletRequest.getServerName(); 869 } 870 871 @Override 872 public int getServerPort() { 873 return httpServletRequest.getServerPort(); 874 } 875 876 @Override 877 public BufferedReader getReader() throws IOException { 878 return httpServletRequest.getReader(); 879 } 880 881 @Override 882 public String getRemoteAddr() { 883 return httpServletRequest.getRemoteAddr(); 884 } 885 886 @Override 887 public String getRemoteHost() { 888 return httpServletRequest.getRemoteHost(); 889 } 890 891 @Override 892 public void setAttribute(String name, Object o) { 893 httpServletRequest.setAttribute(name, o); 894 } 895 896 @Override 897 public void removeAttribute(String name) { 898 httpServletRequest.removeAttribute(name); 899 } 900 901 @Override 902 public Locale getLocale() { 903 return httpServletRequest.getLocale(); 904 } 905 906 @Override 907 public Enumeration<Locale> getLocales() { 908 return httpServletRequest.getLocales(); 909 } 910 911 @Override 912 public boolean isSecure() { 913 return httpServletRequest.isSecure(); 914 } 915 916 @Override 917 public RequestDispatcher getRequestDispatcher(String path) { 918 return httpServletRequest.getRequestDispatcher(path); 919 } 920 921 @Override 922 public String getRealPath(String path) { 923 return httpServletRequest.getRealPath(path); 924 } 925 926 @Override 927 public int getRemotePort() { 928 return httpServletRequest.getRemotePort(); 929 } 930 931 @Override 932 public String getLocalName() { 933 return httpServletRequest.getLocalName(); 934 } 935 936 @Override 937 public String getLocalAddr() { 938 return httpServletRequest.getLocalAddr(); 939 } 940 941 @Override 942 public int getLocalPort() { 943 return httpServletRequest.getLocalPort(); 944 } 945 946 @Override 947 public ServletContext getServletContext() { 948 return httpServletRequest.getServletContext(); 949 } 950 951 @Override 952 public AsyncContext startAsync() throws IllegalStateException { 953 return httpServletRequest.startAsync(); 954 } 955 956 @Override 957 public AsyncContext startAsync(ServletRequest servletRequest, ServletResponse servletResponse) throws IllegalStateException { 958 return servletRequest.startAsync(); 959 } 960 961 @Override 962 public boolean isAsyncStarted() { 963 return httpServletRequest.isAsyncStarted(); 964 } 965 966 @Override 967 public boolean isAsyncSupported() { 968 return httpServletRequest.isAsyncSupported(); 969 } 970 971 @Override 972 public AsyncContext getAsyncContext() { 973 return httpServletRequest.getAsyncContext(); 974 } 975 976 @Override 977 public DispatcherType getDispatcherType() { 978 return httpServletRequest.getDispatcherType(); 979 } 980 981 @Override 982 public String getAuthType() { 983 return httpServletRequest.getAuthType(); 984 } 985 986 @Override 987 public Cookie[] getCookies() { 988 return httpServletRequest.getCookies(); 989 } 990 991 @Override 992 public long getDateHeader(String name) { 993 return httpServletRequest.getDateHeader(name); 994 } 995 996 @Override 997 public String getHeader(String name) { 998 return httpServletRequest.getHeader(name); 999 } 1000 1001 @Override 1002 public Enumeration<String> getHeaders(String name) { 1003 return httpServletRequest.getHeaders(name); 1004 } 1005 1006 @Override 1007 public Enumeration<String> getHeaderNames() { 1008 return httpServletRequest.getHeaderNames(); 1009 } 1010 1011 @Override 1012 public int getIntHeader(String name) { 1013 return httpServletRequest.getIntHeader(name); 1014 } 1015 1016 @Override 1017 public String getMethod() { 1018 return httpServletRequest.getMethod(); 1019 } 1020 1021 @Override 1022 public String getPathInfo() { 1023 return httpServletRequest.getPathInfo(); 1024 } 1025 1026 @Override 1027 public String getPathTranslated() { 1028 return httpServletRequest.getPathTranslated(); 1029 } 1030 1031 @Override 1032 public String getContextPath() { 1033 return httpServletRequest.getContextPath(); 1034 } 1035 1036 @Override 1037 public String getQueryString() { 1038 return httpServletRequest.getQueryString(); 1039 } 1040 1041 @Override 1042 public String getRemoteUser() { 1043 return httpServletRequest.getRemoteUser(); 1044 } 1045 1046 @Override 1047 public boolean isUserInRole(String role) { 1048 return httpServletRequest.isUserInRole(role); 1049 } 1050 1051 @Override 1052 public Principal getUserPrincipal() { 1053 return httpServletRequest.getUserPrincipal(); 1054 } 1055 1056 @Override 1057 public String getRequestedSessionId() { 1058 return httpServletRequest.getRequestedSessionId(); 1059 } 1060 1061 @Override 1062 public String getRequestURI() { 1063 return httpServletRequest.getRequestURI(); 1064 } 1065 1066 @Override 1067 public StringBuffer getRequestURL() { 1068 return httpServletRequest.getRequestURL(); 1069 } 1070 1071 @Override 1072 public String getServletPath() { 1073 return httpServletRequest.getServletPath(); 1074 } 1075 1076 @Override 1077 public HttpSession getSession(boolean create) { 1078 return httpServletRequest.getSession(); 1079 } 1080 1081 @Override 1082 public HttpSession getSession() { 1083 return httpServletRequest.getSession(); 1084 } 1085 1086 @Override 1087 public String changeSessionId() { 1088 return httpServletRequest.changeSessionId(); 1089 } 1090 1091 @Override 1092 public boolean isRequestedSessionIdValid() { 1093 return httpServletRequest.isRequestedSessionIdValid(); 1094 } 1095 1096 @Override 1097 public boolean isRequestedSessionIdFromCookie() { 1098 return httpServletRequest.isRequestedSessionIdFromCookie(); 1099 } 1100 1101 @Override 1102 public boolean isRequestedSessionIdFromURL() { 1103 return httpServletRequest.isRequestedSessionIdFromURL(); 1104 } 1105 1106 @Override 1107 public boolean isRequestedSessionIdFromUrl() { 1108 return httpServletRequest.isRequestedSessionIdFromUrl(); 1109 } 1110 1111 @Override 1112 public boolean authenticate(HttpServletResponse response) throws IOException, ServletException { 1113 return httpServletRequest.authenticate(response); 1114 } 1115 1116 @Override 1117 public void login(String username, String password) throws ServletException { 1118 httpServletRequest.login(username, password); 1119 } 1120 1121 @Override 1122 public void logout() throws ServletException { 1123 httpServletRequest.logout(); 1124 } 1125 1126 @Override 1127 public Collection<Part> getParts() throws IOException, ServletException { 1128 return httpServletRequest.getParts(); 1129 } 1130 1131 @Override 1132 public Part getPart(String name) throws IOException, ServletException { 1133 return httpServletRequest.getPart(name); 1134 } 1135 1136 @Override 1137 public <T extends HttpUpgradeHandler> T upgrade(Class<T> handlerClass) throws IOException, ServletException { 1138 return httpServletRequest.upgrade(handlerClass); 1139 } 1140 } 1141 1142 package note2; 1143 1144 import javax.servlet.ServletOutputStream; 1145 import javax.servlet.http.Cookie; 1146 import javax.servlet.http.HttpServletResponse; 1147 import java.io.IOException; 1148 import java.io.PrintWriter; 1149 import java.util.Collection; 1150 import java.util.Locale; 1151 1152 /** 1153 * Created by kanyuxia on 2017/5/3. 1154 */ 1155 public class HttpResponseFacade implements HttpServletResponse { 1156 private HttpServletResponse httpServletResponse; 1157 1158 HttpResponseFacade(HttpServletResponse httpServletResponse) { 1159 this.httpServletResponse = httpServletResponse; 1160 } 1161 @Override 1162 public String getCharacterEncoding() { 1163 return httpServletResponse.getCharacterEncoding(); 1164 } 1165 1166 @Override 1167 public String getContentType() { 1168 return httpServletResponse.getContentType(); 1169 } 1170 1171 @Override 1172 public ServletOutputStream getOutputStream() throws IOException { 1173 return httpServletResponse.getOutputStream(); 1174 } 1175 1176 @Override 1177 public PrintWriter getWriter() throws IOException { 1178 return httpServletResponse.getWriter(); 1179 } 1180 1181 @Override 1182 public void setCharacterEncoding(String charset) { 1183 httpServletResponse.setCharacterEncoding(charset); 1184 } 1185 1186 @Override 1187 public void setContentLength(int len) { 1188 httpServletResponse.setContentLength(len); 1189 } 1190 1191 @Override 1192 public void setContentLengthLong(long len) { 1193 httpServletResponse.setContentLengthLong(len); 1194 } 1195 1196 @Override 1197 public void setContentType(String type) { 1198 httpServletResponse.setContentType(type); 1199 } 1200 1201 @Override 1202 public void setBufferSize(int size) { 1203 httpServletResponse.setBufferSize(size); 1204 } 1205 1206 @Override 1207 public int getBufferSize() { 1208 return httpServletResponse.getBufferSize(); 1209 } 1210 1211 @Override 1212 public void flushBuffer() throws IOException { 1213 httpServletResponse.flushBuffer(); 1214 } 1215 1216 @Override 1217 public void resetBuffer() { 1218 httpServletResponse.resetBuffer(); 1219 } 1220 1221 @Override 1222 public boolean isCommitted() { 1223 return httpServletResponse.isCommitted(); 1224 } 1225 1226 @Override 1227 public void reset() { 1228 httpServletResponse.reset(); 1229 } 1230 1231 @Override 1232 public void setLocale(Locale loc) { 1233 httpServletResponse.setLocale(loc); 1234 } 1235 1236 @Override 1237 public Locale getLocale() { 1238 return httpServletResponse.getLocale(); 1239 } 1240 1241 @Override 1242 public void addCookie(Cookie cookie) { 1243 httpServletResponse.addCookie(cookie); 1244 } 1245 1246 @Override 1247 public boolean containsHeader(String name) { 1248 return httpServletResponse.containsHeader(name); 1249 } 1250 1251 @Override 1252 public String encodeURL(String url) { 1253 return httpServletResponse.encodeURL(url); 1254 } 1255 1256 @Override 1257 public String encodeRedirectURL(String url) { 1258 return httpServletResponse.encodeRedirectURL(url); 1259 } 1260 1261 @Override 1262 public String encodeUrl(String url) { 1263 return httpServletResponse.encodeUrl(url); 1264 } 1265 1266 @Override 1267 public String encodeRedirectUrl(String url) { 1268 return httpServletResponse.encodeRedirectURL(url); 1269 } 1270 1271 @Override 1272 public void sendError(int sc, String msg) throws IOException { 1273 httpServletResponse.sendError(sc, msg); 1274 } 1275 1276 @Override 1277 public void sendError(int sc) throws IOException { 1278 httpServletResponse.sendError(sc); 1279 } 1280 1281 @Override 1282 public void sendRedirect(String location) throws IOException { 1283 httpServletResponse.sendRedirect(location); 1284 } 1285 1286 @Override 1287 public void setDateHeader(String name, long date) { 1288 httpServletResponse.setDateHeader(name, date); 1289 } 1290 1291 @Override 1292 public void addDateHeader(String name, long date) { 1293 httpServletResponse.addDateHeader(name, date); 1294 } 1295 1296 @Override 1297 public void setHeader(String name, String value) { 1298 httpServletResponse.setHeader(name, value); 1299 } 1300 1301 @Override 1302 public void addHeader(String name, String value) { 1303 httpServletResponse.addHeader(name, value); 1304 } 1305 1306 @Override 1307 public void setIntHeader(String name, int value) { 1308 httpServletResponse.setIntHeader(name, value); 1309 } 1310 1311 @Override 1312 public void addIntHeader(String name, int value) { 1313 httpServletResponse.addIntHeader(name, value); 1314 } 1315 1316 @Override 1317 public void setStatus(int sc) { 1318 httpServletResponse.setStatus(sc); 1319 } 1320 1321 @Override 1322 public void setStatus(int sc, String sm) { 1323 httpServletResponse.setStatus(sc, sm); 1324 } 1325 1326 @Override 1327 public int getStatus() { 1328 return httpServletResponse.getStatus(); 1329 } 1330 1331 @Override 1332 public String getHeader(String name) { 1333 return httpServletResponse.getHeader(name); 1334 } 1335 1336 @Override 1337 public Collection<String> getHeaders(String name) { 1338 return httpServletResponse.getHeaders(name); 1339 } 1340 1341 @Override 1342 public Collection<String> getHeaderNames() { 1343 return httpServletResponse.getHeaderNames(); 1344 } 1345 }
工具类:
1 package note2; 2 3 import java.util.Collection; 4 import java.util.Enumeration; 5 import java.util.Iterator; 6 import java.util.Map; 7 8 /** 9 * Created by kanyuxia on 2017/4/27. 10 */ 11 public class Enumerator<E> implements Enumeration<E> { 12 private Iterator<E> iterator = null; 13 14 public Enumerator(Collection<E> collection) { 15 this(collection.iterator()); 16 } 17 18 public Enumerator(Iterator<E> iterator) { 19 super(); 20 this.iterator = iterator; 21 } 22 23 public Enumerator(Map<?, E> map) { 24 this(map.values().iterator()); 25 } 26 27 @Override 28 public boolean hasMoreElements() { 29 return iterator.hasNext(); 30 } 31 32 @Override 33 public E nextElement() { 34 return (E) iterator.next(); 35 } 36 } 37 38 39 package note2; 40 41 import java.util.HashMap; 42 import java.util.Map; 43 44 /** 45 * Extended implementation of <strong>HashMap</strong> that includes a 46 * <code>locked</code> property. This class can be used to safely expose 47 * Catalina internal parameter map objects to user classes without having 48 * to clone them in order to avoid modifications. When first created, a 49 * <code>ParmaeterMap</code> instance is not locked. 50 * 51 * 存放Http参数:Query String or Form Data 52 * Created by kanyuxia on 2017/4/27. 53 */ 54 public class ParameterMap<K, V> extends HashMap<K, V> { 55 private static final long serialVersionUID = -7752723814131658494L; 56 57 /** 58 * 一些构造函数 59 */ 60 public ParameterMap() { 61 super(); 62 } 63 64 public ParameterMap(int initialCapacity) { 65 super(initialCapacity); 66 } 67 68 public ParameterMap(int initialCapaticity, float loadFactory) { 69 super(initialCapaticity, loadFactory); 70 } 71 72 public ParameterMap(Map<K, V> map) { 73 super(map); 74 } 75 76 /** 77 * The current lock state of this parameter map. 78 * ParameterMap是否锁住。 79 */ 80 private boolean locked = false; 81 82 public boolean isLocked() { 83 return locked; 84 } 85 86 public void setLocked(boolean locked) { 87 this.locked = locked; 88 } 89 90 @Override 91 public void clear() { 92 if (locked) { 93 throw new IllegalStateException("parameterMap.locked"); 94 } 95 super.clear(); 96 } 97 98 @Override 99 public V put(K key, V value) { 100 if (locked) { 101 throw new IllegalStateException("parameterMap.locked"); 102 } 103 return super.put(key, value); 104 } 105 106 @Override 107 public void putAll(Map<? extends K, ? extends V> m) { 108 if (locked) { 109 throw new IllegalStateException("parameterMap.locked"); 110 } 111 super.putAll(m); 112 } 113 114 @Override 115 public boolean remove(Object key, Object value) { 116 if (locked) { 117 throw new IllegalStateException("parameterMap.locked"); 118 } 119 return super.remove(key, value); 120 } 121 }
HttpConnector类:
1 package note2; 2 3 import javax.servlet.http.HttpServletRequest; 4 import javax.servlet.http.HttpServletResponse; 5 import java.io.IOException; 6 import java.net.ServerSocket; 7 import java.net.Socket; 8 import java.util.Stack; 9 import java.util.Vector; 10 11 /** 12 * Created by kanyuxia on 2017/4/26. 13 * Http连接器。 14 */ 15 public class HttpConnector implements Runnable,Connector { 16 /** 17 * The Container used for processing requests received by this Connector. 18 * Servlet容器 19 */ 20 private Container container = null; 21 22 /** 23 * The current number of processors that have been created. 24 * 当前已经创建的HttpProcessor 25 */ 26 private int curProcessors = 0; 27 28 /** 29 * The minimum number of processors to start at initialization time. 30 * HttpProcessor对象池最小对象数 31 */ 32 private int minProcessors = 5; 33 34 /** 35 * The maximum number of processors allowed, or <0 for unlimited. 36 * HttpProcessor对象池最大对象数 37 */ 38 private int maxProcessors = 20; 39 40 /** 41 * The port number on which we listen for HTTP requests. 42 * 服务器端口号 43 */ 44 private int port = 10086; 45 46 /** 47 * The set of processors that have been created but are not currently 48 * being used to process a request. 49 * 存放已经创建但未被使用的Http处理器对象 50 */ 51 private final Stack<HttpProcessor> processors = new Stack<>(); 52 53 /** 54 * The set of processors that have ever been created. 55 * 存放已经创建的Http处理器 56 */ 57 private Vector<HttpProcessor> created = new Vector<>(); 58 59 /** 60 * The request scheme that will be set on all requests received 61 * through this connector. 62 * 服务器处理请求模式(协议) 63 */ 64 private String scheme = "http"; 65 66 /** 67 * The server socket through which we listen for incoming TCP connections. 68 * 服务器ServerSocket 69 */ 70 private ServerSocket serverSocket = null; 71 72 /** 73 * The background thread that listens for incoming TCP/IP connections and 74 * hands them off to an appropriate processor. 75 * 启动Http连接器,监听Http请求,把socket分发给HttpProcessor进行处理。 76 */ 77 public void run() { 78 while (true) { 79 Socket socket = null; 80 try { 81 socket = serverSocket.accept(); 82 } catch (IOException e) { 83 e.printStackTrace(); 84 } 85 HttpProcessor processor = createProcessor(); 86 if (processor != null) { 87 processor.assign(socket); 88 } 89 } 90 } 91 92 /** 93 * Create (or allocate) and return an available processor for use in 94 * processing a specific HTTP request, if possible. If the maximum 95 * allowed processors have already been created and are in use, return 96 * <code>null</code> instead. 97 * 创建HttpProcessor:1. 从栈中拿 2. new一个 3. 返回null 98 */ 99 public HttpProcessor createProcessor() { 100 synchronized (processors) { 101 if (processors.size() > 0) { 102 return processors.pop(); 103 } 104 if (maxProcessors > 0 && curProcessors < maxProcessors) { 105 return newProcessor(); 106 } else { 107 if (maxProcessors < 0) { 108 return newProcessor(); 109 } 110 return null; 111 } 112 } 113 } 114 115 /** 116 * Initialize this connector (create ServerSocket here!) 117 * 创建ServerSocket,在原HttpConnector中使用ServerSocketFactory创建,这里就直接创建 118 */ 119 public void initialize() { 120 try { 121 serverSocket = new ServerSocket(port); 122 } catch (IOException e) { 123 e.printStackTrace(); 124 } 125 } 126 127 /** 128 * Begin processing requests via this Connector. 129 * 启动Http连接器,并创建HttpProcessor线程对象池 130 */ 131 public void start() { 132 // 启动Http连接器 133 Thread thread = new Thread(this); 134 thread.setDaemon(true); 135 thread.start(); 136 // 创建最小HttpProcessor线程对象池 137 while (curProcessors < minProcessors) { 138 if (maxProcessors > 0 && curProcessors >= maxProcessors) { 139 break; 140 } 141 HttpProcessor processor = newProcessor(); 142 recycle(processor); 143 } 144 } 145 146 /** 147 * Create and return a new processor suitable for processing HTTP 148 * requests and returning the corresponding responses. 149 * 创建HttpProcessor对象,并使用运行它(它运行在一个单独的后台线程中) 150 */ 151 private HttpProcessor newProcessor() { 152 HttpProcessor processor = new HttpProcessor(this, curProcessors++); 153 created.addElement(processor); 154 processor.start(); 155 return processor; 156 } 157 158 /** 159 * Recycle the specified Processor so that it can be used again. 160 * 回收已经没有使用的HttpProcessor 161 * @param processor The processor to be recycled 162 */ 163 void recycle(HttpProcessor processor) { 164 processors.push(processor); 165 } 166 167 @Override 168 public HttpServletRequest createRequest() { 169 HttpRequest httpRequest = new HttpRequest(); 170 httpRequest.setConnector(this); 171 return httpRequest; 172 } 173 174 @Override 175 public HttpServletResponse createResponse() { 176 HttpResponse httpResponse = new HttpResponse(); 177 httpResponse.setConnector(this); 178 return httpResponse; 179 } 180 181 @Override 182 public Container getContainer() { 183 return container; 184 } 185 186 @Override 187 public void setContainer(Container container) { 188 this.container = container; 189 } 190 191 @Override 192 public String getScheme() { 193 return scheme; 194 } 195 196 @Override 197 public void setScheme(String scheme) { 198 this.scheme = scheme; 199 } 200 201 public void setMaxProcessors(int maxProcessors) { 202 this.maxProcessors = maxProcessors; 203 } 204 205 public int getMaxProcessors() { 206 return maxProcessors; 207 } 208 209 public void setMinProcessors(int minProcessors) { 210 this.minProcessors = minProcessors; 211 } 212 213 public int getMinProcessors() { 214 return minProcessors; 215 } 216 217 public int getPort() { 218 return port; 219 } 220 221 public void setPort(int port) { 222 this.port = port; 223 } 224 }
HttpProcessor类:
1 package note2; 2 3 import javax.servlet.ServletException; 4 import java.io.*; 5 import java.net.Socket; 6 7 /** 8 * Created by kanyuxia on 2017/4/26. 9 * Http处理器 10 */ 11 public class HttpProcessor implements Runnable { 12 13 /** 14 * The HttpConnector with which this processor is associated. 15 */ 16 private HttpConnector connector = null; 17 18 /** 19 * Is there a new socket available? 20 * 是否有新的socket可用 21 */ 22 private boolean available = false; 23 24 /** 25 * The socket we are currently processing a request for. This object 26 * is used for inter-thread communication only. 27 */ 28 private Socket socket = null; 29 30 /** 31 * The identifier of this processor, unique per connector. 32 */ 33 private int id = 0; 34 35 /** 36 * The HTTP request object we will pass to our associated container. 37 */ 38 private HttpRequest httpRequest = null; 39 40 /** 41 * The HTTP response object we will pass to our associated container. 42 */ 43 private HttpResponse httpResponse = null; 44 45 46 /** 47 * Construct a new HttpProcessor associated with the specified connector. 48 * 49 * @param connector HttpConnector that owns this processor 50 * @param id Identifier of this HttpProcessor (unique per connector) 51 */ 52 public HttpProcessor(HttpConnector connector, int id) { 53 this.connector = connector; 54 this.id = id; 55 this.httpRequest = (HttpRequest) connector.createRequest(); 56 this.httpResponse = (HttpResponse) connector.createResponse(); 57 } 58 59 60 /** 61 * Start the background thread we will use for request processing. 62 * 启动一个后台线程运行HttpProcessor 63 */ 64 public void start() { 65 Thread thread = new Thread(this); 66 thread.setDaemon(true); 67 thread.start(); 68 } 69 70 71 /** 72 * The background thread that listens for incoming TCP/IP connections and 73 * hands them off to an appropriate processor. 74 * 等待HttpConnector分配socket,然后处理该scoket,最后通知HttpConnector回收该HttpProcessor 75 */ 76 public void run() { 77 while (true) { 78 // Wait for the next socket to be assigned 79 Socket socket = await(); 80 if (socket == null) { 81 continue; 82 } 83 System.out.println(Thread.currentThread().getName()); 84 // Process the request from this socket 85 process(socket); 86 87 // Finish up this request 88 connector.recycle(this); 89 } 90 } 91 92 /** 93 * Process an incoming HTTP request on the Socket that has been assigned 94 * to this Processor. Any exceptions that occur during processing must be 95 * swallowed and dealt with. 96 * 处理HttpConector分配的socket:1. 解析请求 2. 处理请求(调用容器处理) 97 * @param socket The socket on which we are connected to the client 98 */ 99 private void process(Socket socket) { 100 InputStream input = null; 101 OutputStream output = null; 102 try { 103 input = socket.getInputStream(); 104 output = socket.getOutputStream(); 105 } catch (IOException e) { 106 e.printStackTrace(); 107 } 108 httpRequest.setInput(input); 109 httpResponse.setOutput(output); 110 httpResponse.setHttpRequest(httpRequest); 111 // Parse the incoming request 112 parseConnection(socket); 113 parseRequest(input, output); 114 parseHeader(input, output); 115 116 // Ask our Container to process this request 117 try { 118 connector.getContainer().invoke(httpRequest, httpResponse); 119 } catch (IOException e) { 120 e.printStackTrace(); 121 } catch (ServletException e) { 122 e.printStackTrace(); 123 } 124 125 // 126 httpRequest.recycle(); 127 httpResponse.recycle(); 128 } 129 130 /** 131 * Parse and record the connection parameters related to this request. 132 * 解析连接 133 * @param socket The socket on which we are connected 134 */ 135 private void parseConnection(Socket socket) { 136 } 137 138 /** 139 * Parse the incoming HTTP request and set the corresponding HTTP request 140 * properties. 141 * 解析请求行 142 * @param input The input stream attached to our socket 143 * @param output The output stream of the socket 144 */ 145 private void parseRequest(InputStream input, OutputStream output) { 146 // 在这里仅仅解析了requestURI 147 BufferedInputStream inputStream = new BufferedInputStream(input); 148 StringBuilder stringBuilder = new StringBuilder(1024); 149 byte[] buffer = new byte[1024]; 150 int b = 0; 151 try { 152 b = inputStream.read(buffer); 153 } catch (IOException e) { 154 e.printStackTrace(); 155 } 156 for (int i = 0; i < b; i++) { 157 stringBuilder.append((char) buffer[i]); 158 } 159 int begin = stringBuilder.indexOf(" ") + 1; 160 int end = stringBuilder.indexOf(" ", begin); 161 String requestURI = stringBuilder.substring(begin, end); 162 httpRequest.setRequestURI(requestURI); 163 } 164 165 /** 166 * Parse the incoming HTTP request headers, and set the appropriate 167 * request headers. 168 * 解析请求头 169 * @param input The input stream connected to our socket 170 */ 171 private void parseHeader(InputStream input, OutputStream output) { 172 173 } 174 175 /** 176 * Process an incoming TCP/IP connection on the specified socket. Any 177 * exception that occurs during processing must be logged and swallowed. 178 * <b>NOTE</b>: This method is called from our Connector's thread. We 179 * must assign it to our own thread so that multiple simultaneous 180 * requests can be handled. 181 * HttpConnector分配一个新的socket 182 * @param socket TCP socket to process 183 */ 184 public void assign(Socket socket) { 185 synchronized (this) { 186 // Wait for the Processor to get the previous Socket 187 while (available) { 188 try { 189 wait(); 190 } catch (InterruptedException e) { 191 e.printStackTrace(); 192 } 193 } 194 195 // Store the newly available Socket and notify our thread 196 this.socket = socket; 197 available = true; 198 notifyAll(); 199 } 200 } 201 202 /** 203 * Await a newly assigned Socket from our Connector, or <code>null</code> 204 * if we are supposed to shut down. 205 * 等待HttpConenctor分配一个新的socket 206 */ 207 private Socket await() { 208 synchronized (this) { 209 // Wait for the Connector to provide a new Socket 210 while (!available) { 211 try { 212 wait(); 213 } catch (InterruptedException e) { 214 e.printStackTrace(); 215 } 216 } 217 218 // Notify the Connector that we have received this Socket 219 available = false; 220 notifyAll(); 221 return socket; 222 } 223 } 224 }
SimpleContainer类:
1 package note2; 2 3 import note1.HttpServer; 4 5 import javax.servlet.Servlet; 6 import javax.servlet.ServletException; 7 import java.io.File; 8 import java.io.IOException; 9 import java.net.URL; 10 import java.net.URLClassLoader; 11 import java.net.URLStreamHandler; 12 13 /** 14 * Created by kanyuxia on 2017/5/3. 15 */ 16 public class SimpleContainer implements Container { 17 18 @SuppressWarnings("unchecked") 19 public void invoke(HttpRequest request, HttpResponse response) throws IOException, ServletException { 20 String servletName = request.getRequestURI().substring(request.getRequestURI().lastIndexOf("/") + 1); 21 // 创建URLClassLoader 22 URLClassLoader classLoader = null; 23 try { 24 // 创建URL 25 URL[] urls = new URL[1]; 26 File classPath = new File(HttpServer.SERVLET_ROOT); 27 String repository = (new URL("file", null, classPath.getCanonicalPath() + File.separator)).toString(); 28 URLStreamHandler streamHandler = null; 29 urls[0] = new URL(null, repository, streamHandler); 30 classLoader = new URLClassLoader(urls); 31 } catch (IOException e) { 32 System.out.println(); 33 } 34 Class<Servlet> servletClass = null; 35 try { 36 servletClass = (Class<Servlet>) classLoader.loadClass(servletName); 37 } catch (ClassNotFoundException e) { 38 e.printStackTrace(); 39 } 40 Servlet servlet = null; 41 try { 42 servlet = servletClass.newInstance(); 43 } catch (InstantiationException e) { 44 e.printStackTrace(); 45 } catch (IllegalAccessException e) { 46 e.printStackTrace(); 47 } 48 servlet.service(request.getRequest(), response.getResponse()); 49 } 50 }
BootStrap启动类:
1 package note2; 2 3 /** 4 * Created by kanyuxia on 2017/5/3. 5 */ 6 public class BootStrap { 7 public static void main(String[] args) { 8 HttpConnector httpConnector = new HttpConnector(); 9 httpConnector.setContainer(new SimpleContainer()); 10 httpConnector.initialize(); 11 httpConnector.start(); 12 } 13 }