码迷,mamicode.com
首页 > 其他好文 > 详细

tomcat(14)服务器组件和服务组件

时间:2016-05-23 15:15:52      阅读:311      评论:0      收藏:0      [点我收藏+]

标签:

【0】README
0.1)本文部分文字描述转自 “how tomcat works”,旨在学习 “tomcat(14)服务器组件和服务组件” 的基础知识;
0.2)for complete source code ,please visit  https://github.com/pacosonTang/HowTomcatWorks/tree/master/chapter14

【1】服务器组件(org.apache.catalina.Server)
1)org.apache.catalina.Server接口的实例表示 Catalina的整个servlet引擎,囊括了所有的组件。服务器组件使用了一种优雅的方法来启动/关闭 整个系统,不需要再对连接器和容器分别启动/ 关闭;
2)启动/关闭机制的工作原理:当启动服务器组件时,它会启动其中所有的组件,然后它就无限期地等待关闭命令。如果想要关闭系统,可以向指定端口发送一条关闭命令。服务器组件接收到关闭命令后,就会关闭其中所有的组件;
3)服务组件:服务器组件引入了服务组件来包含其他组件,如一个容器组件和一个或多个连接器组件;(干货——注意区分服务器组件和服务组件,以下代码摘自某测试用例,StandardService表服务组件,而StandardServer表服务器组件)
Service service = new StandardService();
    service.setName("Stand-alone Service");
    Server server = new StandardServer();
    server.addService(service);

4)服务器组件Server接口定义
package org.apache.catalina;
import org.apache.catalina.deploy.NamingResources; 
public interface Server { 
    public String getInfo();
    public NamingResources getGlobalNamingResources(); 
    public void setGlobalNamingResources (NamingResources globalNamingResources);  
    public int getPort(); 
    public void setPort(int port);  
    public String getShutdown(); 
    public void setShutdown(String shutdown); 
    public void addService(Service service); 
    public void await();   
    public Service findService(String name);   
    public Service[] findServices();    
    public void removeService(Service service);
    public void initialize() throws LifecycleException;
}
对以上代码的分析(Analysis):
A1)shutdown属性:保存了必须发送给Server 实例用来关闭整个系统的关闭命令;
A2)port属性:定义了服务器组件会从哪个端口获取关闭命令;
A3)addService() 和 removeService()方法:为服务器组件添加或移除服务组件;
A4)findService()方法:返回添加到该服务器组件中的所有服务组件;
A5)initialize()方法:包含在系统启动前要执行的一些代码;

【2】StandardServer类
1)intro:一个服务器组件可以有0个或多个服务组件;(干货——一个服务器组件可以有0个或多个服务组件)
2)StandardServer类有4个与生命周期相关的方法,分别是initialize()方法,start()方法,stop()方法 和 await()方法;

【2.1】initialize()方法
1)intro:用于初始化添加到其中的服务器组件;
 public void initialize()  throws LifecycleException {  //org.apache.catalina.StandardServer.initialize().
        if (initialized)
            throw new LifecycleException (
                sm.getString("standardServer.initialize.initialized"));
        initialized = true;

        // Initialize our defined Services
        for (int i = 0; i < services.length; i++) {
            services[i].initialize();
        }
    }
【2.2】start() 方法
1)intro:该方法用于启动服务器组件,即启动所有的服务组件,逐个启动所有组件,如连接器组件和servlet容器;
 public void start() throws LifecycleException {  //org.apache.catalina.StandardServer.start().
        // Validate and update our current component state
        if (started)
            throw new LifecycleException
                (sm.getString("standardServer.start.started"));

        // Notify our interested LifecycleListeners
        lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null);

        lifecycle.fireLifecycleEvent(START_EVENT, null);
        started = true;

        // Start our defined Services
        synchronized (services) {
            for (int i = 0; i < services.length; i++) {
                if (services[i] instanceof Lifecycle)
                    ((Lifecycle) services[i]).start();
            }
        }

        // Notify our interested LifecycleListeners
        lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);
    }
【2.3】stop()方法
1)intro:用于关闭服务器组件;(调用stop方法会关闭所有的服务组件,并reset started,这样,才能再次启动服务器组件;参见start()方法)
public void stop() throws LifecycleException {   //org.apache.catalina.StandardServer.stop().

        // Validate and update our current component state
        if (!started)
            throw new LifecycleException
                (sm.getString("standardServer.stop.notStarted"));

        // Notify our interested LifecycleListeners
        lifecycle.fireLifecycleEvent(BEFORE_STOP_EVENT, null);

        lifecycle.fireLifecycleEvent(STOP_EVENT, null);
        started = false;

        // Stop our defined Services
        for (int i = 0; i < services.length; i++) {
            if (services[i] instanceof Lifecycle)
                ((Lifecycle) services[i]).stop();
        }
        // Notify our interested LifecycleListeners
        lifecycle.fireLifecycleEvent(AFTER_STOP_EVENT, null);
    }
【2.4】await()方法
1)intro:该方法负责等待关闭整个tomcat 部署的命令;
2)await()方法:调用该方法后,会一直阻塞,直到它从 8085 端口(也可以是其他端口)上接收到关闭命令(accept()方法);当await()方法返回时,会运行stop方法来关闭其下的所有子组件;
public void await() {  //org.apache.catalina.StandardServer.await().
        // Set up a server socket to wait on
        ServerSocket serverSocket = null;
        try {
            serverSocket =
                new ServerSocket(port, 1,
                                 InetAddress.getByName("127.0.0.1"));
        } catch (IOException e) {
            System.err.println("StandardServer.await: create[" + port
                               + "]: " + e);
            e.printStackTrace();
            System.exit(1);
        }

        // Loop waiting for a connection and a valid command
        while (true) {

            // Wait for the next connection
            Socket socket = null;
            InputStream stream = null;
            try {
                socket = serverSocket.accept(); //highlight line.
                socket.setSoTimeout(10 * 1000);  // Ten seconds
                stream = socket.getInputStream();
            } catch (AccessControlException ace) {
                System.err.println("StandardServer.accept security exception: "
                                   + ace.getMessage());
                continue;
            } catch (IOException e) {
                System.err.println("StandardServer.await: accept: " + e);
                e.printStackTrace();
                System.exit(1);
            }

            // Read a set of characters from the socket
            StringBuffer command = new StringBuffer();
            int expected = 1024; // Cut off to avoid DoS attack
            while (expected < shutdown.length()) {
                if (random == null)
                    random = new Random(System.currentTimeMillis());
                expected += (random.nextInt() % 1024);
            }
            while (expected > 0) {
                int ch = -1;
                try {
                    ch = stream.read();
                } catch (IOException e) {
                    System.err.println("StandardServer.await: read: " + e);
                    e.printStackTrace();
                    ch = -1;
                }
                if (ch < 32)  // Control character or EOF terminates loop
                    break;
                command.append((char) ch);
                expected--;
            }

            // Close the socket now that we are done with it
            try {
                socket.close();
            } catch (IOException e) {
                ;
            }

            // Match against our command string
            boolean match = command.toString().equals(shutdown); //highlight line.
            if (match) {
                break;
            } else
                System.err.println("StandardServer.await: Invalid command '" +
                                   command.toString() + "' received");
        }
        // Close the server socket and return
        try {
            serverSocket.close();
        } catch (IOException e) {
            ;
        }
    }
对以上代码的调用过程分析(steps):
step1)创建一个ServerSocket对象,监听8085端口,并在while循环中调用它的accept()方法;
step2)当在指定端口上接收到消息时,accept()方法才会返回;
step3)将接收到的消息与关闭命令的字符串相比较,相同的话就跳出while循环,关闭 ServerSocket,否则会再次循环,继续等待消息;

【3】Service接口(服务组件接口——org.apache.catalina.core.Service)
1)intro:一个服务组件可以有一个servlet容器 和 多个连接器实例;(干货——一个服务器组件可以有0个或多个服务组件,而一个服务组件可以有一个servlet容器 和 多个连接器实例)
2)可以自由地把连接器添加到服务组件中,所有的连接器都会与这个servlet容器相关联; 
package org.apache.catalina; 
public interface Service { 
    public Container getContainer();   
    public void setContainer(Container container);   
    public String getInfo(); 
    public String getName(); 
    public void setName(String name); 
    public Server getServer();   
    public void setServer(Server server);     
    public void addConnector(Connector connector); 
    public Connector[] findConnectors();   
    public void removeConnector(Connector connector);    
    public void initialize() throws LifecycleException;
}
【4】StandardService类(org.apache.catalina.core.StandardService)
1)StandardService.initialize()方法:用于初始化添加到其中的所有连接器;
2)StandardService.start()方法:启动连接器和所有servlet容器;

【4.1】connectors 和 container
1)StandardService实例中有两种组件:连接器和servlet容器;其中servlet容器只有一个,而连接器则可以有多个;(干货——StandardService实例中有两种组件:连接器和servlet容器)
2)多个连接器使tomcat 可以为多种不同的请求协议提供服务;如,一个连接器处理HTTP请求,而另一个连接器处理HTTPS请求;(干货——多个连接器使tomcat 可以为多种不同的请求协议提供服务)
3)变量connectors 和 container:StandardService类使用 container 变量来指向一个Container接口的实例,而数组connectors 来保存所有连接器的引用;(干货——变量connectors 和 container的用途)
 private Connector connectors[] = new Connector[0]; // defined in StandardService.
4)setContainer()方法:需要调用setContainer()方法 将servlet容器与服务组件相关联;
public void setContainer(Container container) { // org.apache.catalina.core.StandardService.setContainer().
        Container oldContainer = this.container;
        if ((oldContainer != null) && (oldContainer instanceof Engine))
            ((Engine) oldContainer).setService(null);
        this.container = container;
        if ((this.container != null) && (this.container instanceof Engine))
            ((Engine) this.container).setService(this);
        if (started && (this.container != null) &&
            (this.container instanceof Lifecycle)) {
            try {
                ((Lifecycle) this.container).start();
            } catch (LifecycleException e) {
                ;
            }
        }
        synchronized (connectors) {
            for (int i = 0; i < connectors.length; i++)
                connectors[i].setContainer(this.container);
        }
        if (started && (oldContainer != null) &&
            (oldContainer instanceof Lifecycle)) {
            try {
                ((Lifecycle) oldContainer).stop();
            } catch (LifecycleException e) {
                ;
            }
        }
        // Report this property change to interested listeners
        support.firePropertyChange("container", oldContainer, this.container);
    }
对以上代码的补充描述(description):与服务组件相关联的servlet容器的实例将被传给每个连接器对象的 setContainer()方法,这样在服务组件中就可以形成每个连接器和 servlet容器间的关联关系;
5)addConnector()方法和removeConnector()方法:前者将连接器添加到服务组件中, 后者将某个连接器移除;
(补充:addConnector()方法会初始化并启动添加到其中的连接器,参见下面的start()方法——highlight line.)
public void addConnector(Connector connector) { //org.apache.catalina.core.StandardService.addConnector().
        synchronized (connectors) {
            connector.setContainer(this.container);
            connector.setService(this);
            Connector results[] = new Connector[connectors.length + 1];
            System.arraycopy(connectors, 0, results, 0, connectors.length);
            results[connectors.length] = connector;
            connectors = results;

            if (initialized) {
                try {
                    connector.initialize(); //highlight line.
                } catch (LifecycleException e) {
                    e.printStackTrace(System.err);
                }
            }

            if (started && (connector instanceof Lifecycle)) {
                try {
                    ((Lifecycle) connector).start();//highlight line.
                } catch (LifecycleException e) {
                    ;
                }
            }
            // Report this property change to interested listeners
            support.firePropertyChange("connector", null, connector);
        }
    }
public void removeConnector(Connector connector) {  //org.apache.catalina.core.StandardService.removeConnector().
        synchronized (connectors) {
            int j = -1;
            for (int i = 0; i < connectors.length; i++) {
                if (connector == connectors[i]) {
                    j = i;
                    break;
                }
            }
            if (j < 0)
                return;
            if (started && (connectors[j] instanceof Lifecycle)) {
                try {
                    ((Lifecycle) connectors[j]).stop();
                } catch (LifecycleException e) {
                    ;
                }
            }
            connectors[j].setContainer(null);
            connector.setService(null);
            int k = 0;
            Connector results[] = new Connector[connectors.length - 1];
            for (int i = 0; i < connectors.length; i++) {
                if (i != j)
                    results[k++] = connectors[i];
            }
            connectors = results;

            // Report this property change to interested listeners
            support.firePropertyChange("connector", connector, null);
        }
    }
【4.2】与生命周期有关的方法(start() + stop() + initialize())
1)intro: 与生命周期有关的方法包括Lifecycle.start() + Lifecycle.stop()+ initialize()方法;其中initialize()方法会调用该服务组件中所有连接器的 initialize()方法;
2)org.apache.catalina.core.StandardService.initialize()源码如下:
public void initialize()  throws LifecycleException {  //org.apache.catalina.core.StandardService.initialize().
        if (initialized) 
            throw new LifecycleException (
                sm.getString("standardService.initialize.initialized"));
        initialized = true;
        // Initialize our defined Connectors
        synchronized (connectors) {
                for (int i = 0; i < connectors.length; i++) {
                    connectors[i].initialize(); //highlight line.
                }
        }
    }
public void initialize()  throws LifecycleException { //org.apache.catalina.connector.HttpConnector.initialize().
        if (initialized)
            throw new LifecycleException (
                sm.getString("httpConnector.alreadyInitialized"));
        this.initialized=true;
        Exception eRethrow = null;
        // Establish a server socket on the specified port
        try {
            serverSocket = open();
        } catch (IOException ioe) {
            log("httpConnector, io problem: ", ioe);
            eRethrow = ioe;
        } catch (KeyStoreException kse) {
            log("httpConnector, keystore problem: ", kse);
            eRethrow = kse;
        } catch (NoSuchAlgorithmException nsae) {
            log("httpConnector, keystore algorithm problem: ", nsae);
            eRethrow = nsae;
        } catch (CertificateException ce) {
            log("httpConnector, certificate problem: ", ce);
            eRethrow = ce;
        } catch (UnrecoverableKeyException uke) {
            log("httpConnector, unrecoverable key: ", uke);
            eRethrow = uke;
        } catch (KeyManagementException kme) {
            log("httpConnector, key management problem: ", kme);
            eRethrow = kme;
        }
        if ( eRethrow != null )
            throw new LifecycleException(threadName + ".open", eRethrow);
    }
3)org.apache.catalina.core.StandardService.start()源码如下:该方法负责启动被添加到 该服务组件中的连接器和servlet容器;
 public void start() throws LifecycleException {  // org.apache.catalina.core.StandardService.start()
        // Validate and update our current component state
        if (started) {
            throw new LifecycleException
                (sm.getString("standardService.start.started"));
        }
        // Notify our interested LifecycleListeners
        lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null);
        System.out.println
            (sm.getString("standardService.start.name", this.name));
        lifecycle.fireLifecycleEvent(START_EVENT, null);
        started = true;
        // Start our defined Container first
        if (container != null) {
            synchronized (container) {
                if (container instanceof Lifecycle) {
                    ((Lifecycle) container).start(); //highlight line.
                }
            }
        }
        // Start our defined Connectors second
        synchronized (connectors) {
            for (int i = 0; i < connectors.length; i++) {
                if (connectors[i] instanceof Lifecycle)
                    ((Lifecycle) connectors[i]).start(); //highlight line.
            }
        }
        // Notify our interested LifecycleListeners
        lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);
    }
4)org.apache.catalina.core.StandardService.stop()源码如下:用于关闭与该服务组件相关联的servlet容器和所有连接器;
public void stop() throws LifecycleException { // org.apache.catalina.core.StandardService.stop()
        // Validate and update our current component state
        if (!started) {
            throw new LifecycleException
                (sm.getString("standardService.stop.notStarted"));
        }
        // Notify our interested LifecycleListeners
        lifecycle.fireLifecycleEvent(BEFORE_STOP_EVENT, null);
        lifecycle.fireLifecycleEvent(STOP_EVENT, null);
        System.out.println
            (sm.getString("standardService.stop.name", this.name));
        started = false;
        // Stop our defined Connectors first
        synchronized (connectors) {
            for (int i = 0; i < connectors.length; i++) {
                if (connectors[i] instanceof Lifecycle)
                    ((Lifecycle) connectors[i]).stop();//highlight line.
            }
        }
        // Stop our defined Container second
        if (container != null) {
            synchronized (container) {
                if (container instanceof Lifecycle) {
                    ((Lifecycle) container).stop(); //highlight line.
                }
            }
        }
        // Notify our interested LifecycleListeners
        lifecycle.fireLifecycleEvent(AFTER_STOP_EVENT, null);
    }
【5】应用程序 
1)intro:本应用程序旨在说明如何使用服务器组件和服务组件,特别是在 StandardServer类中如何利用 启动和关闭机制;
2)共有3个类:Bootstrap类+Stopper类+SimpleContextConfig类(它其实是作为 LifecycleListener的实例)
2.1)Bootstrap类源码
public final class Bootstrap {
  public static void main(String[] args) {

    System.setProperty("catalina.base", System.getProperty("user.dir"));
    Connector connector = new HttpConnector();

    Wrapper wrapper1 = new StandardWrapper();
    wrapper1.setName("Primitive");
    wrapper1.setServletClass("PrimitiveServlet");
    Wrapper wrapper2 = new StandardWrapper();
    wrapper2.setName("Modern");
    wrapper2.setServletClass("ModernServlet");

    Context context = new StandardContext();
    // StandardContext's start method adds a default mapper
    context.setPath("/app1");
    context.setDocBase("app1");

    context.addChild(wrapper1);
    context.addChild(wrapper2);

    LifecycleListener listener = new SimpleContextConfig();
    ((Lifecycle) context).addLifecycleListener(listener);

    Host host = new StandardHost();
    host.addChild(context);
    host.setName("localhost");
    host.setAppBase("webapps");

    Loader loader = new WebappLoader();
    context.setLoader(loader);
    // context.addServletMapping(pattern, name);
    context.addServletMapping("/Primitive", "Primitive");
    context.addServletMapping("/Modern", "Modern");

    Engine engine = new StandardEngine();
    engine.addChild(host);
    engine.setDefaultHost("localhost");

    Service service = new StandardService();
    service.setName("Stand-alone Service");
    Server server = new StandardServer();
    server.addService(service);
    service.addConnector(connector);

    //StandardService class's setContainer will call all its connector's setContainer method
    service.setContainer(engine);

    // Start the new server
    if (server instanceof Lifecycle) {
      try {
        server.initialize();
        ((Lifecycle) server).start();
        server.await();
        // the program waits until the await method returns,
        // i.e. until a shutdown command is received.
      }
      catch (LifecycleException e) {
        e.printStackTrace(System.out);
      }
    }

    // Shut down the server
    if (server instanceof Lifecycle) {
      try {
        ((Lifecycle) server).stop();
      }
      catch (LifecycleException e) {
        e.printStackTrace(System.out);
      }
    }
  }
}
对以上代码的调用过程分析(steps):
step1)该方法会创建一个连接器,两个Wrapper实例,一个Context容器,一个Host容器和一个Engine容器;
step2)将两个Wrapper 实例添加到 Context容器中, 将Context容器添加到 Host容器中,再将Host容器添加到Engine容器中;(干货——到此,tomcat的4种容器创建完毕)
step3)但是,这并没有将连接器和最顶层的容器Engine相关联;
step4)相反,main()方法创建了一个Service对象,设置其名称,再创建一个 Server对象,将Service实例添加到 Server实例中:
 Service service = new StandardService();
    service.setName("Stand-alone Service");
    Server server = new StandardServer();
    server.addService(service);
step5)main()方法将连接器和Engine容器添加到 Service实例中;
    service.addConnector(connector);
    service.setContainer(engine);
step6)main()方法调用 Server.intialize() 和 Server.start()方法,初始化连接器,并启动连接器和servlet容器;
step7)接下来,main()方法调用Server.await()方法,进入循环等待,监听8085端口等待关闭命令;(干货——参见上述【2.4】await()方法)
Attention)此时连接器已经处于运行状态,等待另一个端口8080上的 http 请求;(监听8085和8080端口分别处于不同的线程)
// Start the new server
    if (server instanceof Lifecycle) {
      try {
        server.initialize(); // step6
        ((Lifecycle) server).start(); // step6
        server.await(); // step7
        // the program waits until the await method returns,
        // i.e. until a shutdown command is received.
      }
      catch (LifecycleException e) {
        e.printStackTrace(System.out);
      }
    }
step8)除非收到了正确的关闭命令,否则await()方法是不会返回的。当 await()方法返回时,main()方法调用 Server.stop()方法,实际上关闭其所有组件;
// Shut down the server
    if (server instanceof Lifecycle) {
      try {
        ((Lifecycle) server).stop();
      }
      catch (LifecycleException e) {
        e.printStackTrace(System.out);
      }
    }
2.2)Stopper类 源码
2.2.1)intro:Stopper类提供了更加优雅的方式来关闭Catalina服务器,也保证了所有的生命周期组件中的stop() 方法都能够调用;
public class Stopper {
  public static void main(String[] args) {
    // the following code is taken from the Stop method of
    // the org.apache.catalina.startup.Catalina class
    int port = 8005;
    try {
      Socket socket = new Socket("127.0.0.1", port);
      OutputStream stream = socket.getOutputStream();
      String shutdown = "SHUTDOWN";
      for (int i = 0; i < shutdown.length(); i++)
        stream.write(shutdown.charAt(i));
      stream.flush();
      stream.close();
      socket.close();
      System.out.println("The server was successfully shut down.");
    }
    catch (IOException e) {
      System.out.println("Error. The server has not been started.");
    }
  }
}
对以上代码的分析(Analysis): Stopper类的main()方法会创建一个 Socket对象,然后将正确 的关闭命令 “SHOTDOWN”字符串发送到 端口8085。Catalina 服务器在接收到关闭命令后,就会执行相应的关闭操作;

Attention)本文还是习惯性地总结了上述测试用例的调用流程图
技术分享
技术分享

A1)HttpConnector.start()方法的调用过程如下(下面的图借用自 tomcat(11) 中章节【1】的4.1小节的图):
技术分享

A2)StandardsEngine.start()方法的调用过程如下(下面的第二张图借用自tomcat(13)中的章节【10】 ,两张图可以结合起来看):
技术分享

技术分享
【6】执行结果
1)console info
E:\bench-cluster\cloud-data-preprocess\HowTomcatWorks\src>java -cp .;lib/servlet.jar;lib/catalina_4_1_24.jar;lib/catalina-5.5.4.jar;lib/naming-common.
jar;lib/commons-collections.jar;lib/naming-resources.jar;lib/commons-digester.jar;lib/catalina.jar;E:\bench-cluster\cloud-data-preprocess\HowTomcatWok
s\weroot com.tomcat.chapter14.startup.Bootstrap
HttpConnector Opening server socket on all host IP addresses
Starting service Stand-alone Service
Apache Tomcat/4.1.24
WebappLoader[/app1]: Deploying class repositories to work directory E:\bench-cluster\cloud-data-preprocess\HowTomcatWorks\src\work\_\localhost\app1
WebappLoader[/app1]: Deploy class files /WEB-INF/classes to E:\bench-cluster\cloud-data-preprocess\HowTomcatWorks\src\webapps\app1\WEB-INF\classes
StandardManager[/app1]: Seeding random number generator class java.security.SecureRandom
StandardManager[/app1]: Seeding of random number generator has been completed
StandardManager[/app1]: IOException while loading persisted sessions: java.io.EOFException
java.io.EOFException
        at java.io.ObjectInputStream$PeekInputStream.readFully(Unknown Source)
        at java.io.ObjectInputStream$BlockDataInputStream.readShort(Unknown Source)
        at java.io.ObjectInputStream.readStreamHeader(Unknown Source)
        at java.io.ObjectInputStream.<init>(Unknown Source)
        at org.apache.catalina.util.CustomObjectInputStream.<init>(CustomObjectInputStream.java:103)
        at org.apache.catalina.session.StandardManager.load(StandardManager.java:408)
        at org.apache.catalina.session.StandardManager.start(StandardManager.java:655)
        at org.apache.catalina.core.StandardContext.start(StandardContext.java:3570)
        at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1188)
        at org.apache.catalina.core.StandardHost.start(StandardHost.java:738)
        at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1188)
        at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:347)
        at org.apache.catalina.core.StandardService.start(StandardService.java:497)
        at org.apache.catalina.core.StandardServer.start(StandardServer.java:2190)
        at com.tomcat.chapter14.startup.Bootstrap.main(Bootstrap.java:77)
StandardManager[/app1]: Exception loading sessions from persistent storage
java.io.EOFException
        at java.io.ObjectInputStream$PeekInputStream.readFully(Unknown Source)
        at java.io.ObjectInputStream$BlockDataInputStream.readShort(Unknown Source)
        at java.io.ObjectInputStream.readStreamHeader(Unknown Source)
        at java.io.ObjectInputStream.<init>(Unknown Source)
        at org.apache.catalina.util.CustomObjectInputStream.<init>(CustomObjectInputStream.java:103)
        at org.apache.catalina.session.StandardManager.load(StandardManager.java:408)
        at org.apache.catalina.session.StandardManager.start(StandardManager.java:655)
        at org.apache.catalina.core.StandardContext.start(StandardContext.java:3570)
        at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1188)
        at org.apache.catalina.core.StandardHost.start(StandardHost.java:738)
        at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1188)
        at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:347)
        at org.apache.catalina.core.StandardService.start(StandardService.java:497)
        at org.apache.catalina.core.StandardServer.start(StandardServer.java:2190)
        at com.tomcat.chapter14.startup.Bootstrap.main(Bootstrap.java:77)
HttpConnector[8080] Starting background thread
ModernServlet -- init
StandardHost[localhost]: MAPPING configuration error for request URI /favicon.ico
2)执行效果
技术分享
技术分享


tomcat(14)服务器组件和服务组件

标签:

原文地址:http://blog.csdn.net/pacosonswjtu/article/details/51474873

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!