StandardServer’s init method (which actually calls initInternal because it inherits from LifecycleBase, and the same for the methods that follow it), mainly calls the init method of Service, which is implemented as StandardService. (And of course scans for class loader (of course, will also scan the class loader for resources, ignored here)
java
1 2 3 4
for (Service service : services) { service.init(); }
The StandardService’s init method does a few things:
Endpoint is an interface, the abstract class for AbstractEndpoint, init method will call bindWithCleanup method, and then the internal will call the bind abstract method, different is the implementation of the class processing is not the same. Take NioEndpoint as an example: it mainly creates ServerSocketChannel and then binds the port.
There are three main steps in Catalina’s START method:
java
1 2 3 4 5 6 7
getServer().start();
if (shutdownHook == null) { shutdownHook = newCatalinaShutdownHook(); } Runtime.getRuntime().addShutdownHook(shutdownHook);
java
1 2 3 4
if (await) { await(); stop(); }
The start method of Server mainly calls the start method of Service, which is internally implemented as startInternal method because it inherits LifecycBase. Some of the following classes are analyzed in the same way.
java
1 2 3 4
for (Service service : services) { service.start(); }
Service’s start method, which does three main things.
Engine’s start method, which mainly calls the startInternal method of the parent class ContainerBase, does the following:
java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Container children[] = findChildren(); List> results = newArrayList<>(); for (Container child : children) { results.add(startStopExecutor.submit(newStartChild(child))); } for (Future result : results) { result.get(); }
if (pipeline instanceof Lifecycle) { ((Lifecycle) pipeline).start(); }
threadStart();
Host (implementation class for StandardHost) in the start no special, will call the parent class ContainerBase startInternal method, will continue to look for child containers to call the start method
In the Context container, the execution logic of the start method will be more complex:
Create a Loader, which will contain a class loader internally, and call the start method.
Find the subcontainer (Wrapper) and call the start method.
java
1 2 3 4 5
for (Container child : findChildren()) { if (!child.getState().isAvailable()) { child.start(); } }
Calling the onStartup method of the ServletContainerInitializer interface
java
1 2 3
for (Map.Entry>> entry :initializers.entrySet()) { entry.getKey().onStartup(entry.getValue(),getServletContext()); }
Looking for subcontainers that need to be loaded at startup time, the subcontainer Wrapper loads the Servlet internally and calls the Servlet#init method. This kind is loaded at startup, by default, it is delayed loading.
java
1
loadOnStartup(findChildren());
There is nothing special about the Wrapper container.
Connector internally calls the start method of ProtocolHandler
java
1 2
protocolHandler.start();
ProtocolHandler is an interface with an abstract class AbstractProtocol, which internally implements the main logic:
Endpoint is an interface , the abstract class is AbstractEndpoint, the internal will call startInternal, implemented by different implementation of the class . NioEndpoint as an example. The main logic is as follows::
Internally, the Server’s await method will actually be called. By default, the port has a value, a ServerSocket is created, and the main thread blocks in the accept() method.
In the stopServer method in Catalina (which can be called with the command stop, which will call that method), in addition to calling Stop on the Server, if the port is greater than 0, it will also create a socket and send the SHUTDOWN string.
java
1 2 3 4 5 6 7 8
Socketsocket=newSocket(s.getAddress(), s.getPort(); OutputStreamstream= socket.getOutputStream(); Stringshutdown= s.getShutdown(); for (inti=0; i < shutdown.length(); i++) { stream.write(shutdown.charAt(i)); } stream.flush();