上一篇我们已经分析了Digester类,有基础分析Catalina类的代码,所以这篇主要是看下Catalina类,之前我们分析Bootstrap类的时候,知道Bootstrap的类主要是通过CatalinaClassLoader加载Catalina类调用Catalina的load(arguments), start(),stop(),stopServer(),现在我们逐个方法来看。
1、 load(arguments)方法:看源码load(arguments)最后调用的是load方法;
1.1. load方法:
看load方法之前先对比看server.xml和createStartDigester方法
createStartDigester方法server片段,
1 long t1=System.currentTimeMillis();
2 // Initialize the digester
3 Digester digester = new Digester();
4 digester.setValidating(false);
5 digester.setRulesValidation(true);
6 HashMap<Class<?>, List<String>> fakeAttributes = new HashMap<>();
7 ArrayList<String> attrs = new ArrayList<>();
8 attrs.add("className");
9 fakeAttributes.put(Object.class, attrs);
10 digester.setFakeAttributes(fakeAttributes);
11 digester.setUseContextClassLoader(true);
12
13 // Configure the actions we will be using
14 digester.addObjectCreate("Server",
15 "org.apache.catalina.core.StandardServer",
16 "className");
17 digester.addSetProperties("Server");
18 digester.addSetNext("Server",
19 "setServer",
20 "org.apache.catalina.Server");
可以看到我们之前分析的Rule,ObjectCreateRule,SetPropertiesRule,SetNextRule,当解析到
下面看load方法代码片段,最后还是调用server.init。
1 。。。。
2 //根据System参数java.io.tmpdir判断临时文件夹
3 initDirs();
4 //
5 initNaming();
6
7 //创建startDigester,这个我们后面重点分析
8 Digester digester = createStartDigester();
9
10 InputSource inputSource = null;
11 InputStream inputStream = null;
12 File file = null;
13 try {
14 try {
15 //默认是config/server.xml
16 file = configFile();
17 inputStream = new FileInputStream(file);
18 inputSource = new InputSource(file.toURI().toURL().toString());
19 } catch (Exception e) {
20 if (log.isDebugEnabled()) {
21 log.debug(sm.getString("catalina.configFail", file), e);
22 }
23 }
24 ……………
25
26 try {
27 inputSource.setByteStream(inputStream);
28 //将catalina,push进Digester
29 digester.push(this);
30 //parse server.xml,解析过程中回调之前我们分析的rule
31 digester.parse(inputSource);
32 } catch (SAXParseException spe) {
33 log.warn("Catalina.start using " + getConfigFile() + ": " +
34 spe.getMessage());
35 return;
36 } catch (Exception e) {
37 log.warn("Catalina.start using " + getConfigFile() + ": " , e);
38 return;
39 }
40 } finally {
41 if (inputStream != null) {
42 try {
43 inputStream.close();
44 } catch (IOException e) {
45 // Ignore
46 }
47 }
48 }
49 //parse之后catalina已经调用setServer方法创建得到server
50 getServer().setCatalina(this);
51 getServer().setCatalinaHome(Bootstrap.getCatalinaHomeFile());
52 getServer().setCatalinaBase(Bootstrap.getCatalinaBaseFile());
53
54 // Stream redirection
55 initStreams();
56
57 // Start the new server
58 try {
59 //调用server.init方法
60 getServer().init();
61 } catch (LifecycleException e) {
62 ……..
63 }
2、 start方法;
1 ………
2
3 try {
4 //调用Server的start方法
5 getServer().start();
6 } catch (LifecycleException e) {
7 ………
8 return;
9 }
10
11 long t2 = System.nanoTime();
12 if(log.isInfoEnabled()) {
13 log.info("Server startup in " + ((t2 - t1) / 1000000) + " ms");
14 }
15
16 //注册shutdownhook,jvm退出的时候会回调这个runnable
17 if (useShutdownHook) {
18 if (shutdownHook == null) {
19 shutdownHook = new CatalinaShutdownHook();
20 }
21 Runtime.getRuntime().addShutdownHook(shutdownHook);
22
23 ……….
24 }
25
26 if (await) {
27 await();
28 stop();
29 }
3、 stopServer()方法;
1 …….
2
3 Server s = getServer();
4 if (s == null) {
5 //cmd 调用shutdown.bat的时候,走这里,当为空将创建StandServer
6 Digester digester = createStopDigester();
7 File file = configFile();
8 try (FileInputStream fis = new FileInputStream(file)) {
9 InputSource is =
10 new InputSource(file.toURI().toURL().toString());
11 is.setByteStream(fis);
12 digester.push(this);
13 digester.parse(is);
14 } catch (Exception e) {
15 log.error("Catalina.stop: ", e);
16 System.exit(1);
17 }
18 } else {
19 //不为空直接调用server stop,作为一个service运行的时候
20 try {
21 s.stop();
22 } catch (LifecycleException e) {
23 log.error("Catalina.stop: ", e);
24 }
25 return;
26 }
27
28 s = getServer();
29 if (s.getPort()>0) {
30 //给监听ServerSocket,发送SHUTDOWN信息,关闭Server
31 try (Socket socket = new Socket(s.getAddress(), s.getPort());
32 OutputStream stream = socket.getOutputStream()) {
33 String shutdown = s.getShutdown();
34 for (int i = 0; i < shutdown.length(); i++) {
35 stream.write(shutdown.charAt(i));
36 }
37 stream.flush();
38 } catch (ConnectException ce) {
39 log.error(sm.getString("catalina.stopServer.connectException",
40 s.getAddress(),
41 String.valueOf(s.getPort())));
42 log.error("Catalina.stop: ", ce);
43 System.exit(1);
44 } catch (IOException e) {
45 log.error("Catalina.stop: ", e);
46 System.exit(1);
47 }
48 } else {
49 log.error(sm.getString("catalina.stopServer"));
50 System.exit(1);
51 }
4、 Stop()方法;
1 …………
2 try {
3 Server s = getServer();
4 LifecycleState state = s.getState();
5 if (LifecycleState.STOPPING_PREP.compareTo(state) <= 0
6 && LifecycleState.DESTROYED.compareTo(state) >= 0) {
7 //stop已经被调用
8 } else {
9 //调用server stop方法
10 s.stop();
11 s.destroy();
12 }
13 } catch (LifecycleException e) {
14 log.error("Catalina.stop", e);
15 }
总结:catalina类中,load方法调用的时候会将server.xml里面的配置信息通过Digester解析成对象,分析到目前为止可以知道的对象是Catalina->Server,start方法调用server.start同时注册shutdownHook,stopServer方法当双击ShutDown.bat来关闭tomcat的时候,将发送SHUTDOWN给正在运行的Server的ServerSocket,当tomcat作为一个service运行的时候,会直接调用Server的stop方法停止tomcat
版权声明:本文不是「本站」原创文章,版权归原作者所有 | 原文地址: