Tomcat8.5.50

Tomcat 核心思想

servlet? web容器/servlet容器 tomcat是servlet的容器,每个请求是servlet ,每个servlet里面包含了request,response 

tomcat 包含了很多servlet  tomcat

使用Http11NioProtocol

 

Http11NioProtocol

<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />

 

 <Context path="/" docBase="/root/tomcat/apache-tomcat-8.0.30/fantasy" /> 以web项目为单位加载servlet

 Context: A Context represents a web application. (代表一个web项目)

看server.xml,每一个标签都有对应的java 类,其他源码也可以参照如此学习

Context:

public interface Context extends Container, ContextBind {
StandardContext

public boolean loadOnStartup(Container children[]) { // Collect "load on startup" servlets that need to be initialized 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) continue; Integer key = Integer.valueOf(loadOnStartup); ArrayList<Wrapper> list = map.get(key); if (list == null) { list = new ArrayList<>(); map.put(key, list); }
//将每个servlet添加到容器中 list.add(wrapper); }
// Load the collected "load on startup" servlets for (ArrayList<Wrapper> list : map.values()) { for (Wrapper wrapper : list) { try { wrapper.load(); } catch (ServletException e) { getLogger().error(sm.getString("standardContext.loadOnStartup.loadException", getName(), wrapper.getName()), StandardWrapper.getRootCause(e)); // NOTE: load errors (including a servlet that throws // UnavailableException from the init() method) are NOT // fatal to application startup // unless failCtxIfServletStartFails="true" is specified if(getComputedFailCtxIfServletStartFails()) { return false; } } } } return true; }

Wrapper 是否是Servlet?

public class ContextConfig implements LifecycleListener {
protected void webConfig() {
WebXmlParser webXmlParser = new WebXmlParser(context.getXmlNamespaceAware(),
context.getXmlValidation(), context.getXmlBlockExternal());

Set<WebXml> defaults = new HashSet<>();
defaults.add(getDefaultWebXmlFragment(webXmlParser));

WebXml webXml = createWebXml();

// Parse context level web.xml
InputSource contextWebXml = getContextWebXmlSource();
if (!webXmlParser.parseWebXml(contextWebXml, webXml, false)) {
ok = false;
}
 }   

//1 创建webXml

WebXml webXml = createWebXml();
public class WebXml {
//加载web.xml
private static final StringManager sm =
StringManager.getManager(Constants.PACKAGE_NAME);
}
public class Constants {

public static final String PACKAGE_NAME =
Constants.class.getPackage().getName();

public static final String WEB_XML_LOCATION = "/WEB-INF/web.xml";

}
getContextWebXmlSource
stream = servletContext.getResourceAsStream
(Constants.ApplicationWebXml);
try {
url = servletContext.getResource(
Constants.ApplicationWebXml);
} catch (MalformedURLException e) {
log.error(sm.getString("contextConfig.applicationUrl"));
}
Constants {

    public static final String Package = "org.apache.catalina.startup";

    public static final String ApplicationContextXml = "META-INF/context.xml";
//找到 web-inf/web.xml
public static final String ApplicationWebXml = "/WEB-INF/web.xml"; public static final String DefaultContextXml = "conf/context.xml"; public static final String DefaultWebXml = "conf/web.xml"; public static final String HostContextXml = "context.xml.default"; public static final String HostWebXml = "web.xml.default"; public static final String WarTracker = "/META-INF/war-tracker";
  // Step 9. Apply merged web.xml to Context
            if (ok) {
                configureContext(webXml);
            }
// 加载web.xml,将servlet 进行包装 ,包装为wrapper
for (ServletDef servlet : webxml.getServlets().values()) {
            Wrapper wrapper = context.createWrapper();
            // Description is ignored
            // Display name is ignored
            // Icons are ignored

            // jsp-file gets passed to the JSP Servlet as an init-param

            if (servlet.getLoadOnStartup() != null) {
                wrapper.setLoadOnStartup(servlet.getLoadOnStartup().intValue());
            }
            if (servlet.getEnabled() != null) {
                wrapper.setEnabled(servlet.getEnabled().booleanValue());
            }
            wrapper.setName(servlet.getServletName());
            Map<String,String> params = servlet.getParameterMap();
            for (Entry<String, String> entry : params.entrySet()) {
                wrapper.addInitParameter(entry.getKey(), entry.getValue());
            }
            wrapper.setRunAs(servlet.getRunAs());
            Set<SecurityRoleRef> roleRefs = servlet.getSecurityRoleRefs();
            for (SecurityRoleRef roleRef : roleRefs) {
                wrapper.addSecurityReference(
                        roleRef.getName(), roleRef.getLink());
            }
            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) {
                wrapper.setAsyncSupported(
                        servlet.getAsyncSupported().booleanValue());
            }
            wrapper.setOverridable(servlet.isOverridable());
            context.addChild(wrapper);
        }

监听端口

 <Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />
Connector查找监听端口

第一步 入口类:Bootstrap
//Bootstrap 当执行命令的时候执行的改方法
public static void main(String args[]) {

        synchronized (daemonLock) {
            if (daemon == null) {
                // Don't set daemon until init() has completed
                Bootstrap bootstrap = new Bootstrap();
                try {
                    bootstrap.init();
                } catch (Throwable t) {
                    handleThrowable(t);
                    t.printStackTrace();
                    return;
                }
                daemon = bootstrap;
            } else {
                // When running as a service the call to stop will be on a new
                // thread so make sure the correct class loader is used to
                // prevent a range of class not found exceptions.
                Thread.currentThread().setContextClassLoader(daemon.catalinaLoader);
            }
        }

        try {
            String command = "start";
            if (args.length > 0) {
                command = args[args.length - 1];
            }

            if (command.equals("startd")) {
                args[args.length - 1] = "start";
                daemon.load(args);
                daemon.start();
            } else if (command.equals("stopd")) {
                args[args.length - 1] = "stop";
                daemon.stop();
            } else if (command.equals("start")) {
                daemon.setAwait(true);
                daemon.load(args);
                daemon.start();
                if (null == daemon.getServer()) {
                    System.exit(1);
                }
            } else if (command.equals("stop")) {
                daemon.stopServer(args);
            } else if (command.equals("configtest")) {
                daemon.load(args);
                if (null == daemon.getServer()) {
                    System.exit(1);
                }
                System.exit(0);
            } else {
                log.warn("Bootstrap: command "" + command + "" does not exist.");
            }
        } catch (Throwable t) {
            // Unwrap the Exception for clearer error reporting
            if (t instanceof InvocationTargetException &&
                    t.getCause() != null) {
                t = t.getCause();
            }
            handleThrowable(t);
            t.printStackTrace();
            System.exit(1);
        }
    }

2 启动命令;

   if (command.equals("startd")) {
                args[args.length - 1] = "start";
// 加载 tomcat 下面的conf/server.xml daemon.load(args);
// 启动 基于对这些对象合作完成相应的功能 daemon.start();
}
 private void load(String[] arguments) throws Exception {

        // Call the load() method
        String methodName = "load";
        Object param[];
        Class<?> paramTypes[];
        if (arguments==null || arguments.length==0) {
            paramTypes = null;
            param = null;
        } else {
            paramTypes = new Class[1];
            paramTypes[0] = arguments.getClass();
            param = new Object[1];
            param[0] = arguments;
        }
        Method method =
            catalinaDaemon.getClass().getMethod(methodName, paramTypes);
        if (log.isDebugEnabled()) {
            log.debug("Calling startup class " + method);
        }
        method.invoke(catalinaDaemon, param);
    }
public class Catalina {
// Start a new server instance. 创建一个server对象
public void load() {} }
file = configFile();
//加载tomcat的server.xml文件
protected String configFile = "conf/server.xml";

// Start the new server 创建server并初始化 
try {
getServer().init();
}
//生命周期Lifecycle
//默认实现类:LifecycleBase
//initInternal()
//StandardServer->initInternal->globalNamingResources
// Initialize our defined Services 
//初始化services是
for (int i = 0; i < services.length; i++) {
//1 初始化service LifecycleBase->init->initInternal->StandardService->initInternal

     services[i].init();

//2 初始化Connector LifecycleBase->init->initInternal->Connector->initInternal

synchronized (connectorsLock) {
for (Connector connector : connectors) {
connector.init();
}
//3 初始化protocol protocolHandler.init()->AbstractProtocol.init()->endpoint.init()->AbstractEndpoint
if (bindOnInit) {
bind();
//选择不同的IO tomcat8 默认NIO tomcat7默认 BIO 在server.xml中的protocol="HTTP/1.1" 可以查看默认IO方式
在Connector 中构造函数public Connector(String protocol)->setProtocol 查看具体实现IO方式

bindState = BindState.BOUND_ON_INIT;
}

}

  

 Host发布方式

HostConfig -deployApps  

    protected void deployApps() {

        File appBase = host.getAppBaseFile();
        File configBase = host.getConfigBaseFile();
        String[] filteredAppPaths = filterAppPaths(appBase.list());
        // Deploy XML descriptors from configBase 基于xml发布
        deployDescriptors(configBase, configBase.list());
        // Deploy WARs 基于war发布
        deployWARs(appBase, filteredAppPaths);
        // Deploy expanded folders 文件夹方式发布
        deployDirectories(appBase, filteredAppPaths);

    }

 Digester解析 xml文件 

原文地址:https://www.cnblogs.com/fanBlog/p/12195878.html