基于之前案例的感性认识,Tomcat连接器源码解读。
Posted 10000miles
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于之前案例的感性认识,Tomcat连接器源码解读。相关的知识,希望对你有一定的参考价值。
背景:本篇的内容主体是Connector连接器,暂不明确其在Tomcat中与其他容器的关系,但可以前述案例为标的物,把Connector理解为运行在多线程下,等待获取客户端socket并交由HttpProcessor进行处理的Object。那么关注点就是在Tomcat中完整的Connector及其所关联的组件的关系,整个模块的相关流程。上篇中的疑问仍留,Response请求头 属性怎样填充?如何填充?不知道在这里有没有解答。
- catalina.jar包org.apache.catalina.Connector接口
1 package org.apache.catalina; 2 3 import org.apache.catalina.Container; 4 import org.apache.catalina.LifecycleException; 5 import org.apache.catalina.Request; 6 import org.apache.catalina.Response; 7 import org.apache.catalina.Service; 8 import org.apache.catalina.net.ServerSocketFactory; 9 10 public interface Connector { 11 Container getContainer(); 12 13 void setContainer(Container arg0); 14 15 boolean getEnableLookups(); 16 17 void setEnableLookups(boolean arg0); 18 19 ServerSocketFactory getFactory(); 20 21 void setFactory(ServerSocketFactory arg0); 22 23 String getInfo(); 24 25 int getRedirectPort(); 26 27 void setRedirectPort(int arg0); 28 29 String getScheme(); 30 31 void setScheme(String arg0); 32 33 boolean getSecure(); 34 35 void setSecure(boolean arg0); 36 37 Service getService(); 38 39 void setService(Service arg0); 40 41 Request createRequest(); 42 43 Response createResponse(); 44 45 void initialize() throws LifecycleException; 46 }
类关系:可以看到接口import了Container、Request、Response、Service、ServerSocketFactory,因此它们将或依赖或聚合在该类中,是该类分解出去的组成部分。它们将 在实现类中被其声明为属性;接口中定义的方法,由于版本问题源码中没有文档注释,Service/ServiceScoketFactory等在前述案例中没有使用到的类的具体作用不得 而知,仅仅是抽象层面的依赖关系,并不足以获取更多的信息。还需要有方法体,来分析对象之间的动态关系,下面是其实现类。
- catalina.jar包org.apache.catalina.connector.Http.HttpConnector类
1 package org.apache.catalina.connector.http; 2 3 import java.io.IOException; 4 import java.net.BindException; 5 import java.net.InetAddress; 6 import java.net.ServerSocket; 7 import java.net.Socket; 8 import java.security.AccessControlException; 9 import java.security.KeyManagementException; 10 import java.security.KeyStoreException; 11 import java.security.NoSuchAlgorithmException; 12 import java.security.UnrecoverableKeyException; 13 import java.security.cert.CertificateException; 14 import java.util.Stack; 15 import java.util.Vector; 16 import org.apache.catalina.Connector; 17 import org.apache.catalina.Container; 18 import org.apache.catalina.Lifecycle; 19 import org.apache.catalina.LifecycleException; 20 import org.apache.catalina.LifecycleListener; 21 import org.apache.catalina.Logger; 22 import org.apache.catalina.Request; 23 import org.apache.catalina.Response; 24 import org.apache.catalina.Service; 25 import org.apache.catalina.connector.http.HttpProcessor; 26 import org.apache.catalina.connector.http.HttpRequestImpl; 27 import org.apache.catalina.connector.http.HttpResponseImpl; 28 import org.apache.catalina.net.DefaultServerSocketFactory; 29 import org.apache.catalina.net.ServerSocketFactory; 30 import org.apache.catalina.util.LifecycleSupport; 31 import org.apache.catalina.util.StringManager; 32 33 public final class HttpConnector implements Connector, Lifecycle, Runnable { 34 private Service service = null; 35 private int acceptCount = 10; 36 private String address = null; 37 private int bufferSize = 2048; 38 protected Container container = null; 39 private Vector created = new Vector(); 40 private int curProcessors = 0; 41 private int debug = 0; 42 private boolean enableLookups = false; 43 private ServerSocketFactory factory = null; 44 private static final String info = "org.apache.catalina.connector.http.HttpConnector/1.0"; 45 protected LifecycleSupport lifecycle = new LifecycleSupport(this); 46 protected int minProcessors = 5; 47 private int maxProcessors = 20; 48 private int connectionTimeout = ‘?‘; 49 private int port = 8080; 50 private Stack processors = new Stack(); 51 private String proxyName = null; 52 private int proxyPort = 0; 53 private int redirectPort = 443; 54 private String scheme = "http"; 55 private boolean secure = false; 56 private ServerSocket serverSocket = null; 57 private StringManager sm = StringManager.getManager("org.apache.catalina.connector.http"); 58 private boolean initialized = false; 59 private boolean started = false; 60 private boolean stopped = false; 61 private Thread thread = null; 62 private String threadName = null; 63 private Object threadSync = new Object(); 64 private boolean allowChunking = true; 65 private boolean tcpNoDelay = true; 66 67 public Service getService() { 68 return this.service; 69 } 70 71 public void setService(Service service) { 72 this.service = service; 73 } 74 75 public int getConnectionTimeout() { 76 return this.connectionTimeout; 77 } 78 79 public void setConnectionTimeout(int connectionTimeout) { 80 this.connectionTimeout = connectionTimeout; 81 } 82 83 public int getAcceptCount() { 84 return this.acceptCount; 85 } 86 87 public void setAcceptCount(int count) { 88 this.acceptCount = count; 89 } 90 91 public boolean isChunkingAllowed() { 92 return this.allowChunking; 93 } 94 95 public boolean getAllowChunking() { 96 return this.isChunkingAllowed(); 97 } 98 99 public void setAllowChunking(boolean allowChunking) { 100 this.allowChunking = allowChunking; 101 } 102 103 public String getAddress() { 104 return this.address; 105 } 106 107 public void setAddress(String address) { 108 this.address = address; 109 } 110 111 public boolean isAvailable() { 112 return this.started; 113 } 114 115 public int getBufferSize() { 116 return this.bufferSize; 117 } 118 119 public void setBufferSize(int bufferSize) { 120 this.bufferSize = bufferSize; 121 } 122 123 public Container getContainer() { 124 return this.container; 125 } 126 127 public void setContainer(Container container) { 128 this.container = container; 129 } 130 131 public int getCurProcessors() { 132 return this.curProcessors; 133 } 134 135 public int getDebug() { 136 return this.debug; 137 } 138 139 public void setDebug(int debug) { 140 this.debug = debug; 141 } 142 143 public boolean getEnableLookups() { 144 return this.enableLookups; 145 } 146 147 public void setEnableLookups(boolean enableLookups) { 148 this.enableLookups = enableLookups; 149 } 150 151 public ServerSocketFactory getFactory() { 152 if (this.factory == null) { 153 synchronized (this) { 154 this.factory = new DefaultServerSocketFactory(); 155 } 156 } 157 158 return this.factory; 159 } 160 161 public void setFactory(ServerSocketFactory factory) { 162 this.factory = factory; 163 } 164 165 public String getInfo() { 166 return "org.apache.catalina.connector.http.HttpConnector/1.0"; 167 } 168 169 public int getMinProcessors() { 170 return this.minProcessors; 171 } 172 173 public void setMinProcessors(int minProcessors) { 174 this.minProcessors = minProcessors; 175 } 176 177 public int getMaxProcessors() { 178 return this.maxProcessors; 179 } 180 181 public void setMaxProcessors(int maxProcessors) { 182 this.maxProcessors = maxProcessors; 183 } 184 185 public int getPort() { 186 return this.port; 187 } 188 189 public void setPort(int port) { 190 this.port = port; 191 } 192 193 public String getProxyName() { 194 return this.proxyName; 195 } 196 197 public void setProxyName(String proxyName) { 198 this.proxyName = proxyName; 199 } 200 201 public int getProxyPort() { 202 return this.proxyPort; 203 } 204 205 public void setProxyPort(int proxyPort) { 206 this.proxyPort = proxyPort; 207 } 208 209 public int getRedirectPort() { 210 return this.redirectPort; 211 } 212 213 public void setRedirectPort(int redirectPort) { 214 this.redirectPort = redirectPort; 215 } 216 217 public String getScheme() { 218 return this.scheme; 219 } 220 221 public void setScheme(String scheme) { 222 this.scheme = scheme; 223 } 224 225 public boolean getSecure() { 226 return this.secure; 227 } 228 229 public void setSecure(boolean secure) { 230 this.secure = secure; 231 } 232 233 public boolean getTcpNoDelay() { 234 return this.tcpNoDelay; 235 } 236 237 public void setTcpNoDelay(boolean tcpNoDelay) { 238 this.tcpNoDelay = tcpNoDelay; 239 } 240 241 public Request createRequest() { 242 HttpRequestImpl request = new HttpRequestImpl(); 243 request.setConnector(this); 244 return request; 245 } 246 247 public Response createResponse() { 248 HttpResponseImpl response = new HttpResponseImpl(); 249 response.setConnector(this); 250 return response; 251 } 252 253 void recycle(HttpProcessor processor) { 254 this.processors.push(processor); 255 } 256 257 private HttpProcessor createProcessor() { 258 Stack arg0 = this.processors; 259 synchronized (arg0) { 260 HttpProcessor arg1; 261 if (this.processors.size() > 0) { 262 arg1 = (HttpProcessor) this.processors.pop(); 263 return arg1; 264 } else if (this.maxProcessors > 0 && this.curProcessors < this.maxProcessors) { 265 arg1 = this.newProcessor(); 266 return arg1; 267 } else if (this.maxProcessors < 0) { 268 arg1 = this.newProcessor(); 269 return arg1; 270 } else { 271 arg1 = null; 272 return arg1; 273 } 274 } 275 } 276 277 private void log(String message) { 278 Logger logger = this.container.getLogger(); 279 String localName = this.threadName; 280 if (localName == null) { 281 localName = "HttpConnector"; 282 } 283 284 if (logger != null) { 285 logger.log(localName + " " + message); 286 } else { 287 System.out.println(localName + " " + message); 288 } 289 290 } 291 292 private void log(String message, Throwable throwable) { 293 Logger logger = this.container.getLogger(); 294 String localName = this.threadName; 295 if (localName == null) { 296 localName = "HttpConnector"; 297 } 298 299 if (logger != null) { 300 logger.log(localName + " " + message, throwable); 301 } else { 302 System.out.println(localName + " " + message); 303 throwable.printStackTrace(System.out); 304 } 305 306 } 307 308 private HttpProcessor newProcessor() { 309 HttpProcessor processor = new HttpProcessor(this, this.curProcessors++); 310 if (processor instanceof Lifecycle) { 311 try { 312 processor.start(); 313 } catch (LifecycleException arg2) { 314 this.log("newProcessor", arg2); 315 return null; 316 } 317 } 318 319 this.created.addElement(processor); 320 return processor; 321 } 322 323 private ServerSocket open() throws IOException, KeyStoreException, NoSuchAlgorithmException, CertificateException, 324 UnrecoverableKeyException, KeyManagementException { 325 ServerSocketFactory factory = this.getFactory(); 326 if (this.address == null) { 327 this.log(this.sm.getString("httpConnector.allAddresses")); 328 329 try { 330 return factory.createSocket(this.port, this.acceptCount); 331 } catch (BindException arg4) { 332 throw new BindException(arg4.getMessage() + ":" + this.port); 333 } 334 } else { 335 try { 336 InetAddress e = InetAddress.getByName(this.address); 337 this.log(this.sm.getString("httpConnector.anAddress", this.address)); 338 339 try { 340 return factory.createSocket(this.port, this.acceptCount, e); 341 } catch (BindException arg5) { 342 throw new BindException(arg5.getMessage() + ":" + this.address + ":" + this.port); 343 } 344 } catch (Exception arg6) { 345 this.log(this.sm.getString("httpConnector.noAddress", this.address)); 346 347 try { 348 return factory.createSocket(this.port, this.acceptCount); 349 } catch (BindException arg3) { 350 throw new BindException(arg3.getMessage() + ":" + this.port); 351 } 352 } 353 } 354 } 355 356 public void run() { 357 while (true) { 358 Object socket; 359 if (!this.stopped) { 360 label81 : { 361 socket = null; 362 363 Socket socket1; 364 try { 365 socket1 = this.serverSocket.accept(); 366 if (this.connectionTimeout > 0) { 367 socket1.setSoTimeout(this.connectionTimeout); 368 } 369 370 socket1.setTcpNoDelay(this.tcpNoDelay); 371 } catch (AccessControlException arg19) { 372 this.log("socket accept security exception", arg19); 373 continue; 374 } catch (IOException arg20) { 375 IOException e = arg20; 376 377 try { 378 Object ioe = this.threadSync; 379 synchronized (ioe) { 380 if (this.started && !this.stopped) { 381 this.log("accept error: ", e); 382 } 383 384 if (!this.stopped) { 385 this.serverSocket.close(); 386 this.serverSocket = this.open(); 387 } 388 continue; 389 } 390 } catch (IOException arg12) { 391 this.log("socket reopen, io problem: ", arg12); 392 break label81; 393 } catch (KeyStoreException arg13) { 394 this.log("socket reopen, keystore problem: ", arg13); 395 break label81; 396 } catch (NoSuchAlgorithmException arg14) { 397 this.log("socket reopen, keystore algorithm problem: ", arg14); 398 break label81; 399 } catch (CertificateException arg15) { 400 this.log("socket reopen, certificate problem: ", arg15); 401 break label81; 402 } catch (UnrecoverableKeyException arg16) { 403 this.log("socket reopen, unrecoverable key: ", arg16); 404 break label81; 405 } catch (KeyManagementException arg17) { 406 this.log("socket reopen, key management problem: ", arg17); 407 break label81; 408 } 409 } 410 411 HttpProcessor processor = this.createProcessor(); 412 if (processor == null) { 413 try { 414 this.log(this.sm.getString("httpConnector.noProcessor")); 415 socket1.close(); 416 } catch (IOException arg18) { 417 ; 418 } 419 continue; 420 } 421 422 processor.assign(socket1); 423 continue; 424 } 425 } 426 427 socket = this.threadSync; 428 synchronized (socket) { 429 this.threadSync.notifyAll(); 430 return; 431 } 432 } 433 } 434 435 private void threadStart() { 436 this.log(this.sm.getString("httpConnector.starting")); 437 this.thread = new Thread(this, this.threadName); 438 this.thread.setDaemon(true); 439 this.thread.start(); 440 } 441 442 private void threadStop() { 443 this.log(this.sm.getString("httpConnector.stopping")); 444 this.stopped = true; 445 446 try { 447 this.threadSync.wait(5000L); 448 } catch (InterruptedException arg1) { 449 ; 450 } 451 452 this.thread = null; 453 } 454 455 public void addLifecycleListener(LifecycleListener listener) { 456 this.lifecycle.addLifecycleListener(listener); 457 } 458 459 public LifecycleListener[] findLifecycleListeners() { 460 return this.lifecycle.findLifecycleListeners(); 461 } 462 463 public void removeLifecycleListener(LifecycleListener listener) { 464 this.lifecycle.removeLifecycleListener(listener); 465 } 466 467 public void initialize() throws LifecycleException { 468 if (this.initialized) { 469 throw new LifecycleException(this.sm.getString("httpConnector.alreadyInitialized")); 470 } else { 471 this.initialized = true; 472 Object eRethrow = null; 473 474 try { 475 this.serverSocket = this.open(); 476 } catch (IOException arg7) { 477 this.log("httpConnector, io problem: ", arg7); 478 eRethrow = arg7; 479 } catch (KeyStoreException arg8) { 480 this.log("httpConnector, keystore problem: ", arg8); 481 eRethrow = arg8; 482 } catch (NoSuchAlgorithmException arg9) { 483 this.log("httpConnector, keystore algorithm problem: ", arg9); 484 eRethrow = arg9; 485 } catch (CertificateException arg10) { 486 this.log("httpConnector, certificate problem: ", arg10); 487 eRethrow = arg10; 488 } catch (UnrecoverableKeyException arg11) { 489 this.log("httpConnector, unrecoverable key: ", arg11); 490 eRethrow = arg11; 491 } catch (KeyManagementException arg12) { 492 this.log("httpConnector, key management problem: ", arg12); 493 eRethrow = arg12; 494 } 495 496 if (eRethrow != null) { 497 throw new LifecycleException(this.threadName + ".open", (Throwable) eRethrow); 498 } 499 } 500 } 501 502 public void start() throws LifecycleException { 503 if (this.started) { 504 throw new LifecycleException(this.sm.getString("httpConnector.alreadyStarted")); 505 } else { 506 this.threadName = "HttpConnector[" + this.port + "]"; 507 this.lifecycle.fireLifecycleEvent("start", (Object) null); 508 this.started = true; 509 this.threadStart(); 510 511 while (this.curProcessors < this.minProcessors 512 && (this.maxProcessors <= 0 || this.curProcessors < this.maxProcessors)) { 513 HttpProcessor processor = this.newProcessor(); 514 this.recycle(processor); 515 } 516 517 } 518 } 519 520 public void stop() throws LifecycleException { 521 if (!this.started) { 522 throw new LifecycleException(this.sm.getString("httpConnector.notStarted")); 523 } else { 524 this.lifecycle.fireLifecycleEvent("stop", (Object) null); 525 this.started = false; 526 527 for (int i = this.created.size() - 1; i >= 0; --i) { 528 HttpProcessor processor = (HttpProcessor) this.created.elementAt(i); 529 if (processor instanceof Lifecycle) { 530 try { 531 processor.stop(); 532 } catch (LifecycleException arg5) { 533 this.log("HttpConnector.stop", arg5); 534 } 535 } 536 } 537 538 Object arg7 = this.threadSync; 539 synchronized (arg7) { 540 if (this.serverSocket != null) { 541 try { 542 this.serverSocket.close(); 543 } catch (IOException arg4) { 544 ; 545 } 546 } 547 548 this.threadStop(); 549 } 550 551 this.serverSocket = null; 552 } 553 } 554 }
代码分析:由于没有main方法,仅从代码无法了解到程序的入口在哪里,现在只需要知道initialize()方法在启动服务器时会被调用.但是是谁调用?其他方法又归谁调用?
既然是实现lifycie接口并被在统一的生命周期中管理,初始化,启动,那么createRequest之类的公开方法又什么作用?
类关系:(HttpConnetor接口有很多实现类,但是这些都是静态关系,是为实现类下定义,或者是采用一些常见的模版模式来复用代码。这里忽略其他实现类,只关注该类。)
以上是关于基于之前案例的感性认识,Tomcat连接器源码解读。的主要内容,如果未能解决你的问题,请参考以下文章
Tomcat连接器Connector源码解读架构概览,如何设计?为什么这样设计?
Tomcat连接器Connector源码解读架构概览,如何设计?为什么这样设计?
并发系列五:基于两种案例来认识ReentrantLock源码解锁过程(公平锁)