tomcat《一》
1 2 | 验证:Tomcat猜想 是不是由一个个Socket组装的Servlet |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | */ protected class Acceptor extends AbstractEndpoint.Acceptor { @Override public void run() { int errorDelay = 0 ; // Loop until we receive a shutdown command while (running) { //判断云运行状态 // Loop if endpoint is paused while (paused && running) { state = AcceptorState.PAUSED; try { Thread.sleep( 50 ); } catch (InterruptedException e) { // Ignore } } if (!running) { break ; } state = AcceptorState.RUNNING; try { //if we have reached max connections, wait countUpOrAwaitConnection(); Socket socket = null ; try { // Accept the next incoming connection from the server // socket 一个工厂循环创建socket socket = serverSocketFactory.acceptSocket(serverSocket); } catch (IOException ioe) { countDownConnection(); // Introduce delay if necessary errorDelay = handleExceptionWithDelay(errorDelay); // re-throw throw ioe; } // Successful accept, reset the error delay errorDelay = 0 ; // Configure the socket if (running && !paused && setSocketOptions(socket)) { // Hand this socket off to an appropriate processor if (!processSocket(socket)) { countDownConnection(); // Close socket right away closeSocket(socket); } } else { countDownConnection(); // Close socket right away closeSocket(socket); } } catch (IOException x) { if (running) { log.error(sm.getString( "endpoint.accept.fail" ), x); } } catch (NullPointerException npe) { if (running) { log.error(sm.getString( "endpoint.accept.fail" ), npe); } } catch (Throwable t) { ExceptionUtils.handleThrowable(t); log.error(sm.getString( "endpoint.accept.fail" ), t); } } state = AcceptorState.ENDED; } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | public class DefaultServerSocketFactory implements ServerSocketFactory { @Override public ServerSocket createSocket ( int port) throws IOException { return new ServerSocket (port); } @Override public ServerSocket createSocket ( int port, int backlog) throws IOException { return new ServerSocket (port, backlog); } @Override public ServerSocket createSocket ( int port, int backlog, InetAddress ifAddress) throws IOException { return new ServerSocket (port, backlog, ifAddress); } ...... |
Tomcat架构猜想,server.xml中每一个标签对应一个类,
接下来先分析Contex到官网发现:
The Context element represents a web application,
which is run within a particular virtual host.
Each web application is based on a Web Application Archive (WAR) file,
or a corresponding directory containing the corresponding unpacked contents
第一句可以发现一个Contetx就是一个web项目。
那么疑问来了,web是不是把一个个Servlet进行组装呢?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | 源码: public class StandardContext extends ContainerBase implements Context, NotificationEmitter StandardContext 实现了Context重写的方法如下 public boolean loadOnStartup(Container[] children) { TreeMap<Integer, ArrayList<Wrapper>> map = new TreeMap(); for ( int i = 0 ; i < children.length; ++i) { Wrapper wrapper = (Wrapper)children[i]; int loadOnStartup = wrapper.getLoadOnStartup(); if (loadOnStartup >= 0 ) { Integer key = loadOnStartup; ArrayList<Wrapper> list = (ArrayList)map.get(key); if (list == null ) { list = new ArrayList(); map.put(key, list); } list.add(wrapper); } } |
1 | Conetxt添加了servlet,但是StandContext里这个方法加载的是Wrapper.接下来看Wrapper是否是等于Servlet,源码中使用了包装器模式进行了加强 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | ContextConfig类的 854 行左右的这个方法 configureContext在 990 行左右的源码 while (var31.hasNext()) { ServletDef servlet = (ServletDef)var31.next(); //使用包装器的方法 Wrapper wrapper = this .context.createWrapper(); //使用包装器的方法把Servlet与Wrapper进行转化 if (servlet.getLoadOnStartup() != null ) { wrapper.setLoadOnStartup(servlet.getLoadOnStartup()); } if (servlet.getEnabled() != null ) { //使用包装器的方法把Servlet与Wrapper进行转化 wrapper.setEnabled(servlet.getEnabled()); } //使用包装器的方法把Servlet与Wrapper进行转化 wrapper.setName(servlet.getServletName()); Map<String, String> params = servlet.getParameterMap(); var7 = params.entrySet().iterator(); while (var7.hasNext()) { Entry<String, String> entry = (Entry)var7.next(); //使用包装器的方法把Servlet与Wrapper进行转化 wrapper.addInitParameter((String)entry.getKey(), (String)entry.getValue()); } wrapper.setRunAs(servlet.getRunAs()); Set<SecurityRoleRef> roleRefs = servlet.getSecurityRoleRefs(); Iterator var33 = roleRefs.iterator(); while (var33.hasNext()) { SecurityRoleRef roleRef = (SecurityRoleRef)var33.next(); wrapper.addSecurityReference(roleRef.getName(), roleRef.getLink()); } //使用包装器的方法把Servlet与Wrapper进行转化 wrapper.setServletClass(servlet.getServletClass()); MultipartDef multipartdef = servlet.getMultipartDef(); if (multipartdef != null ) { if (multipartdef.getMaxFileSize() != null && multipartdef.getMaxRequestSize() != null && multipartdef.getFileSizeThreshold() != null ) { wrapper.setMultipartConfigElement( new MultipartConfigElement(multipartdef.getLocation(), Long.parseLong(multipartdef.getMaxFileSize()), Long.parseLong(multipartdef.getMaxRequestSize()), Integer.parseInt(multipartdef.getFileSizeThreshold()))); } else { wrapper.setMultipartConfigElement( new MultipartConfigElement(multipartdef.getLocation())); } } if (servlet.getAsyncSupported() != null ) { //使用包装器的方法把Servlet与Wrapper进行转化 wrapper.setAsyncSupported(servlet.getAsyncSupported()); } //使用包装器的方法把Servlet与Wrapper进行转化 wrapper.setOverridable(servlet.isOverridable()); //使用包装器的方法把Servlet与Wrapper进行转化 最终添加 this .context.addChild(wrapper); } |
本文来自博客园,作者:余生请多指教ANT,转载请注明原文链接:https://www.cnblogs.com/wangbiaohistory/p/15916481.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
2021-02-20 nacos在nginx下集群以及数据库问题
2021-02-20 nacos配置《一》