tomcat(19)Manager应用程序的servlet类

原创 2016年06月01日 19:45:09
【0】README
1)本文部分文字描述转自:“深入剖析tomcat”,旨在学习“tomcat(19)Manager应用程序的servlet类” 的相关知识;
2)Manager应用程序用来管理已经部署的web 应用程序;在tomcat7中,manager应用程序位于 %CATALINA_HOME%webapps 目录中;

【1】使用Manager应用程序
1)Manager应用程序中的主servlet类是 ManagerServlet类。在tomcat4中, 该类位于 org.apache.catalina.servlets包下; 而在tomcat5中,该类位于 org.apache.catalina.manager下,是作为 WEB-INF/lib 目录下的一个JAR 文件部署的;

<?xml version="1.0" encoding="ISO-8859-1"?>
<!-- tomcat7 下面的 web.xml -->
 Licensed to the Apache Software Foundation (ASF) under one or more
  contributor license agreements.  See the NOTICE file distributed with
  this work for additional information regarding copyright ownership.
  The ASF licenses this file to You under the Apache License, Version 2.0
  (the "License"); you may not use this file except in compliance with
  the License.  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
-->

<web-app xmlns="http://java.sun.com/xml/ns/javaee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
                      http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
  version="3.0"
  metadata-complete="true">

  <display-name>Tomcat Manager Application</display-name>
  <description>
    A scriptable management web application for the Tomcat Web Server;
    Manager lets you view, load/unload/etc particular web applications.
  </description>

  <servlet>
    <servlet-name>Manager</servlet-name>
    <servlet-class>org.apache.catalina.manager.ManagerServlet</servlet-class>
    <init-param>
      <param-name>debug</param-name>
      <param-value>2</param-value>
    </init-param>
  </servlet>
  <servlet>
    <servlet-name>HTMLManager</servlet-name>
    <servlet-class>org.apache.catalina.manager.HTMLManagerServlet</servlet-class>
    <init-param>
      <param-name>debug</param-name>
      <param-value>2</param-value>
    </init-param>
    <!-- Uncomment this to show proxy sessions from the Backup manager or a
         StoreManager in the sessions list for an application
    <init-param>
      <param-name>showProxySessions</param-name>
      <param-value>true</param-value>
    </init-param>
    -->
    <multipart-config>
      <!-- 50MB max -->
      <max-file-size>52428800</max-file-size>
      <max-request-size>52428800</max-request-size>
      <file-size-threshold>0</file-size-threshold>
    </multipart-config>
  </servlet>
  <servlet>
    <servlet-name>Status</servlet-name>
    <servlet-class>org.apache.catalina.manager.StatusManagerServlet</servlet-class>
    <init-param>
      <param-name>debug</param-name>
      <param-value>0</param-value>
    </init-param>
  </servlet>

  <servlet>
    <servlet-name>JMXProxy</servlet-name>
    <servlet-class>org.apache.catalina.manager.JMXProxyServlet</servlet-class>
  </servlet>

  <!-- Define the Manager Servlet Mapping -->
  <servlet-mapping>
    <servlet-name>Manager</servlet-name>
      <url-pattern>/text/*</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <servlet-name>Status</servlet-name>
    <url-pattern>/status/*</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <servlet-name>JMXProxy</servlet-name>
      <url-pattern>/jmxproxy/*</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <servlet-name>HTMLManager</servlet-name>
    <url-pattern>/html/*</url-pattern>
  </servlet-mapping>

  <filter>
    <filter-name>SetCharacterEncoding</filter-name>
    <filter-class>org.apache.catalina.filters.SetCharacterEncodingFilter</filter-class>
    <init-param>
      <param-name>encoding</param-name>
      <param-value>UTF-8</param-value>
    </init-param>
  </filter>

  <filter-mapping>
    <filter-name>SetCharacterEncoding</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

  <filter>
    <filter-name>CSRF</filter-name>
    <filter-class>org.apache.catalina.filters.CsrfPreventionFilter</filter-class>
    <init-param>
      <param-name>entryPoints</param-name>
      <param-value>/html,/html/,/html/list,/index.jsp</param-value>
    </init-param>
  </filter>

  <filter-mapping>
    <filter-name>CSRF</filter-name>
    <servlet-name>HTMLManager</servlet-name>
    <servlet-name>jsp</servlet-name>
  </filter-mapping>

  <!-- Define a Security Constraint on this Application -->
  <!-- NOTE:  None of these roles are present in the default users file -->
  <security-constraint>
    <web-resource-collection>
      <web-resource-name>HTML Manager interface (for humans)</web-resource-name>
      <url-pattern>/html/*</url-pattern>
    </web-resource-collection>
    <auth-constraint>
       <role-name>manager-gui</role-name>
    </auth-constraint>
  </security-constraint>
  <security-constraint>
    <web-resource-collection>
      <web-resource-name>Text Manager interface (for scripts)</web-resource-name>
      <url-pattern>/text/*</url-pattern>
    </web-resource-collection>
    <auth-constraint>
       <role-name>manager-script</role-name>
    </auth-constraint>
  </security-constraint>
  <security-constraint>
    <web-resource-collection>
      <web-resource-name>JMX Proxy interface</web-resource-name>
      <url-pattern>/jmxproxy/*</url-pattern>
    </web-resource-collection>
    <auth-constraint>
       <role-name>manager-jmx</role-name>
    </auth-constraint>
  </security-constraint>
  <security-constraint>
    <web-resource-collection>
      <web-resource-name>Status interface</web-resource-name>
      <url-pattern>/status/*</url-pattern>
    </web-resource-collection>
    <auth-constraint>
       <role-name>manager-gui</role-name>
       <role-name>manager-script</role-name>
       <role-name>manager-jmx</role-name>
       <role-name>manager-status</role-name>
    </auth-constraint>
  </security-constraint>

  <!-- Define the Login Configuration for this Application -->
  <login-config>
    <auth-method>BASIC</auth-method>
    <realm-name>Tomcat Manager Application</realm-name>
  </login-config>

  <!-- Security roles referenced by this web application -->
  <security-role>
    <description>
      The role that is required to access the HTML Manager pages
    </description>
    <role-name>manager-gui</role-name>
  </security-role>
  <security-role>
    <description>
      The role that is required to access the text Manager pages
    </description>
    <role-name>manager-script</role-name>
  </security-role>
  <security-role>
    <description>
      The role that is required to access the HTML JMX Proxy
    </description>
    <role-name>manager-jmx</role-name>
  </security-role>
  <security-role>
    <description>
      The role that is required to access to the Manager Status pages
    </description>
    <role-name>manager-status</role-name>
  </security-role>

  <error-page>
    <error-code>401</error-code>
    <location>/WEB-INF/jsp/401.jsp</location>
  </error-page>
  <error-page>
    <error-code>403</error-code>
    <location>/WEB-INF/jsp/403.jsp</location>
  </error-page>
  <error-page>
    <error-code>404</error-code>
    <location>/WEB-INF/jsp/404.jsp</location>
  </error-page>

</web-app>
对以上代码的分析(Analysis):
A1)第1个servlet是 org.apache.catalina.manager.ManagerServlet;第2个是 org.apache.catalina.manager.HTMLManagerServlet;
A2)org.apache.catalina.manager.ManagerServlet 的函数列表如下:
protected void list(PrintWriter writer) {
        if (debug >= 1)
            log("list: Listing contexts for virtual host '" +
                host.getName() + "'");

        writer.println(sm.getString("managerServlet.listed",
                                    host.getName()));
        Container[] contexts = host.findChildren();
        for (int i = 0; i < contexts.length; i++) {
            Context context = (Context) contexts[i];
            String displayPath = context.getPath();
            if( displayPath.equals("") )
                displayPath = "/";
            if (context != null ) {
                if (context.getAvailable()) {
                    writer.println(sm.getString("managerServlet.listitem",
                                                displayPath,
                                                "running",
                                      "" + context.getManager().findSessions().length,
                                                context.getDocBase()));
                } else {
                    writer.println(sm.getString("managerServlet.listitem",
                                                displayPath,
                                                "stopped",
                                                "0",
                                                context.getDocBase()));
                }
            }
        }
    }
    protected void reload(PrintWriter writer, String path) {

        if (debug >= 1)
            log("restart: Reloading web application at '" + path + "'");

        if ((path == null) || (!path.startsWith("/") && path.equals(""))) {
            writer.println(sm.getString("managerServlet.invalidPath",
                                        RequestUtil.filter(path)));
            return;
        }
        String displayPath = path;
        if( path.equals("/") )
            path = "";

        try {
            Context context = (Context) host.findChild(path);
            if (context == null) {
                writer.println(sm.getString
                               ("managerServlet.noContext",
                                   RequestUtil.filter(displayPath)));
                return;
            }
            // It isn't possible for the manager to reload itself
            if (context.getPath().equals(this.context.getPath())) {
                writer.println(sm.getString("managerServlet.noSelf"));
                return;
            }
            context.reload();
            writer.println
                (sm.getString("managerServlet.reloaded", displayPath));
        } catch (Throwable t) {
            log("ManagerServlet.reload[" + displayPath + "]", t);
            writer.println(sm.getString("managerServlet.exception",
                                        t.toString()));
        }
    }
    protected void resources(PrintWriter writer, String type) {

        if (debug >= 1) {
            if (type != null) {
                log("resources:  Listing resources of type " + type);
            } else {
                log("resources:  Listing resources of all types");
            }
        }

        // Is the global JNDI resources context available?
        if (global == null) {
            writer.println(sm.getString("managerServlet.noGlobal"));
            return;
        }

        // Enumerate the global JNDI resources of the requested type
        if (type != null) {
            writer.println(sm.getString("managerServlet.resourcesType",
                                        type));
        } else {
            writer.println(sm.getString("managerServlet.resourcesAll"));
        }

        Class clazz = null;
        try {
            if (type != null) {
                clazz = Class.forName(type);
            }
        } catch (Throwable t) {
            log("ManagerServlet.resources[" + type + "]", t);
            writer.println(sm.getString("managerServlet.exception",
                                        t.toString()));
            return;
        }
        printResources(writer, "", global, type, clazz);
    }
    protected void printResources(PrintWriter writer, String prefix,
                                  javax.naming.Context namingContext,
                                  String type, Class clazz) {
        try {
            NamingEnumeration items = namingContext.listBindings("");
            while (items.hasMore()) {
                Binding item = (Binding) items.next();
                if (item.getObject() instanceof javax.naming.Context) {
                    printResources
                        (writer, prefix + item.getName() + "/",
                         (javax.naming.Context) item.getObject(), type, clazz);
                } else {
                    if ((clazz != null) &&
                        (!(clazz.isInstance(item.getObject())))) {
                        continue;
                    }
                    writer.print(prefix + item.getName());
                    writer.print(':');
                    writer.print(item.getClassName());
                    // Do we want a description if available?
                    writer.println();
                }
            }
        } catch (Throwable t) {
            log("ManagerServlet.resources[" + type + "]", t);
            writer.println(sm.getString("managerServlet.exception",
                                        t.toString()));
        }
    }
    protected void roles(PrintWriter writer) {
        if (debug >= 1) {
            log("roles:  List security roles from user database");
        }
        // Look up the UserDatabase instance we should use
        UserDatabase database = null;
        try {
            InitialContext ic = new InitialContext();
            database = (UserDatabase) ic.lookup("java:comp/env/users");
        } catch (NamingException e) {
            writer.println(sm.getString("managerServlet.userDatabaseError"));
            log("java:comp/env/users", e);
            return;
        }
        if (database == null) {
            writer.println(sm.getString("managerServlet.userDatabaseMissing"));
            return;
        }

        // Enumerate the available roles
        writer.println(sm.getString("managerServlet.rolesList"));
        Iterator roles = database.getRoles();
        if (roles != null) {
            while (roles.hasNext()) {
                Role role = (Role) roles.next();
                writer.print(role.getRolename());
                writer.print(':');
                if (role.getDescription() != null) {
                    writer.print(role.getDescription());
                }
                writer.println();
            }
        }
    }
    protected void serverinfo(PrintWriter writer) {
        if (debug >= 1)
            log("serverinfo");
        try {
            StringBuffer props = new StringBuffer();
            props.append("OK - Server info");
            props.append("\nTomcat Version: ");
            props.append(ServerInfo.getServerInfo());
            props.append("\nOS Name: ");
            props.append(System.getProperty("os.name"));
            props.append("\nOS Version: ");
            props.append(System.getProperty("os.version"));
            props.append("\nOS Architecture: ");
            props.append(System.getProperty("os.arch"));
            props.append("\nJVM Version: ");
            props.append(System.getProperty("java.runtime.version"));
            props.append("\nJVM Vendor: ");
            props.append(System.getProperty("java.vm.vendor"));
            writer.println(props.toString());
        } catch (Throwable t) {
            getServletContext().log("ManagerServlet.serverinfo",t);
            writer.println(sm.getString("managerServlet.exception",
                                        t.toString()));
        }
    }
    protected void sessions(PrintWriter writer, String path, int idle) {
        if (debug >= 1) {
            log("sessions: Session information for web application at '" + path + "'");
            if (idle >= 0)
                log("sessions: Session expiration for " + idle + " minutes '" + path + "'");
        }
        if ((path == null) || (!path.startsWith("/") && path.equals(""))) {
            writer.println(sm.getString("managerServlet.invalidPath",
                                        RequestUtil.filter(path)));
            return;
        }
        String displayPath = path;
        if( path.equals("/") )
            path = "";
        try {
            Context context = (Context) host.findChild(path);
            if (context == null) {
                writer.println(sm.getString("managerServlet.noContext",
                                            RequestUtil.filter(displayPath)));
                return;
            }
            Manager manager = context.getManager() ;
            if(manager == null) {
               writer.println(sm.getString("managerServlet.noManager",
               RequestUtil.filter(displayPath)));
               return;               
            }
            int maxCount = 60;
            int maxInactiveInterval = manager.getMaxInactiveInterval()/60;
            int histoInterval = maxInactiveInterval / maxCount;
            if ( histoInterval * maxCount < maxInactiveInterval ) 
                histoInterval++;
            maxCount = maxInactiveInterval / histoInterval;
            if ( histoInterval * maxCount < maxInactiveInterval ) 
                maxCount++;

            writer.println(sm.getString("managerServlet.sessions", displayPath));
            writer.println(sm.getString("managerServlet.sessiondefaultmax",
                                "" + maxInactiveInterval));
            Session [] sessions = manager.findSessions();
            int [] timeout = new int[maxCount];
            int notimeout = 0;
            int expired = 0;
            long now = System.currentTimeMillis();
            for (int i = 0; i < sessions.length; i++) {
                int time = (int)((now-sessions[i].getLastAccessedTimeInternal())/1000);
                if (idle >= 0 && time >= idle*60) {
                    sessions[i].expire();
                    idle++;
                }
                time=time/60/histoInterval;
                if (time < 0)
                    notimeout++;
                else if (time >= maxCount)
                    timeout[maxCount-1]++;
                else
                    timeout[time]++;
            }
            if (timeout[0] > 0)
                writer.println(sm.getString("managerServlet.sessiontimeout",
                                            "<" + histoInterval, "" + timeout[0]));
            for (int i = 1; i < maxCount-1; i++) {
                if (timeout[i] > 0)
                    writer.println(sm.getString("managerServlet.sessiontimeout",
                                     "" + (i)*histoInterval + " - <" + (i+1)*histoInterval,
                                                "" + timeout[i]));
            }
            if (timeout[maxCount-1] > 0)
                writer.println(sm.getString("managerServlet.sessiontimeout",
                                            ">=" + maxCount*histoInterval,
                                            "" + timeout[maxCount-1]));
            if (notimeout > 0)
                writer.println(sm.getString("managerServlet.sessiontimeout",
                                            "unlimited","" + notimeout));
            if (idle >= 0)
                writer.println(sm.getString("managerServlet.sessiontimeout",
                                            "" + idle,"expired " + expired));
        } catch (Throwable t) {
            log("ManagerServlet.sessions[" + displayPath + "]", t);
            writer.println(sm.getString("managerServlet.exception",
                                        t.toString()));
        }
    }
protected void undeploy(PrintWriter writer, String path) {
        if (debug >= 1)
            log("undeploy: Undeploying web application at '" + path + "'");
        if ((path == null) || (!path.startsWith("/") && path.equals(""))) {
            writer.println(sm.getString("managerServlet.invalidPath",
                                        RequestUtil.filter(path)));
            return;
        }
        String displayPath = path;
        if( path.equals("/") )
            path = "";

        try {

            // Validate the Context of the specified application
            Context context = (Context) host.findChild(path);
            if (context == null) {
                writer.println(sm.getString("managerServlet.noContext",
                                            RequestUtil.filter(displayPath)));
                return;
            }
            // Identify the appBase of the owning Host of this Context (if any)
            String appBase = null;
            File appBaseDir = null;
            if (context.getParent() instanceof Host) {
                appBase = ((Host) context.getParent()).getAppBase();
                appBaseDir = new File(appBase);
                if (!appBaseDir.isAbsolute()) {
                    appBaseDir = new File(System.getProperty("catalina.base"),
                                          appBase);
                }
            }
            if (!isDeployed(path)) {
                writer.println(sm.getString("managerServlet.notDeployed",
                        RequestUtil.filter(displayPath)));
                return;
            }

            if (!isServiced(path)) {
                addServiced(path);
                try {
                    // Try to stop the context first to be nicer
                    ((Lifecycle) context).stop();
                } catch (Throwable t) {
                    // Ignore
                }
                try {
                    File war = new File(getAppBase(), getDocBase(path) + ".war");
                    File dir = new File(getAppBase(), getDocBase(path));
                    File xml = new File(configBase, getConfigFile(path) + ".xml");
                    if (war.exists()) {
                        war.delete();
                    } else if (dir.exists()) {
                        undeployDir(dir);
                    } else {
                        xml.delete();
                    }
                    // Perform new deployment
                    check(path);
                } finally {
                    removeServiced(path);
                }
            }
            writer.println(sm.getString("managerServlet.undeployed",
                                        displayPath));
        } catch (Throwable t) {
            log("ManagerServlet.undeploy[" + displayPath + "]", t);
            writer.println(sm.getString("managerServlet.exception",
                                        t.toString()));
        }
    }
2)在部署描述符中,还有 security-constraint 元素:(also tomcat7)
 <!-- Define a Security Constraint on this Application -->
  <!-- NOTE:  None of these roles are present in the default users file -->
  <security-constraint>
    <web-resource-collection>
      <web-resource-name>HTML Manager interface (for humans)</web-resource-name>
      <url-pattern>/html/*</url-pattern>
    </web-resource-collection>
    <auth-constraint>
       <role-name>manager-gui</role-name>
    </auth-constraint>
  </security-constraint>
  <security-constraint>
    <web-resource-collection>
      <web-resource-name>Text Manager interface (for scripts)</web-resource-name>
      <url-pattern>/text/*</url-pattern>
    </web-resource-collection>
    <auth-constraint>
       <role-name>manager-script</role-name>
    </auth-constraint>
  </security-constraint>
  <security-constraint>
    <web-resource-collection>
      <web-resource-name>JMX Proxy interface</web-resource-name>
      <url-pattern>/jmxproxy/*</url-pattern>
    </web-resource-collection>
    <auth-constraint>
       <role-name>manager-jmx</role-name>
    </auth-constraint>
  </security-constraint>
  <security-constraint>
    <web-resource-collection>
      <web-resource-name>Status interface</web-resource-name>
      <url-pattern>/status/*</url-pattern>
    </web-resource-collection>
    <auth-constraint>
       <role-name>manager-gui</role-name>
       <role-name>manager-script</role-name>
       <role-name>manager-jmx</role-name>
       <role-name>manager-status</role-name>
    </auth-constraint>
  </security-constraint>
对上述代码的分析(Analysis):
A1)上面的配置意思是: 整个应用程序被限制为只有带manager前缀的用户角色的用户才能访问;
A2)auth-login 元素指明了权限认证使用 BASIC 身份验证方式,只有当用户输入正确的用户名和密码时才能访问受限资源;
 <login-config>
    <auth-method>BASIC</auth-method>
    <realm-name>Tomcat Manager Application</realm-name>
  </login-config>
3)在tomcat中,用户和角色列表都存储在 tomcat-users.xml 中,该文件位于 %CATALINA_HOME%/conf 目录下。因此,要访问 Manager应用程序,必须添加一个 manager角色(如manager-gui)和一个拥有该角色的用户, 例如:
<tomcat-users>
    <role rolename="<span style="font-family: Arial, Helvetica, sans-serif;">manager-gui</span><span style="font-family: Arial, Helvetica, sans-serif;">"/></span>
    <user username="tomcat" password="tomcat" roles="manager-gui"/>
</tomcat-users>
对以上代码的分析(Analysis):通过这个 tomcat-users.xml 文件,就可以以tomcat为用户名,以tomcat为密码来访问 Manager 应用程序了;

【2】ContainerServlet接口(org.apache.catalina.ContainerServlet接口)
1)intro:实现该接口的 servlet类可以访问表示该 servlet实例的StandardWrapper对象,通过访问该Wrapper实例,它也就可以访问表示当前 web 应用程序的Context实例,以及该Context实例内的部署器(StandardHost类的实例)等对象;
public interface ContainerServlet {   
    public Wrapper getWrapper();
    public void setWrapper(Wrapper wrapper); 
} 
2)Catalina实例会调用实现了 ContainerServlet接口的servlet类的 setWrapper方法:将该引用传递给表示该servlet类 的 StandardWrapper实例;

【3】初始化 ManagerServlet
1)intro:servlet 对象由一个 org.apache.catalina.core.StandardWrapper 实例表示,第一次调用servlet实例时,会调用 StandardWrapper.loadServlet()方法,然后调用 servlet实例的init()方法;
(下面的图片借用自tomcat(5)servlet容器 章节5.7)


【4】列出已经部署的web 应用程序 
1)通过 http://localhost:8888/manager/list 列出已经部署的web 应用程序;
2)上面的URL 会调用 ManagerServlet.list()方法, 源码如下:
 protected void list(PrintWriter writer) { // org.apache.catalina.manager.ManagerServlet.list().
        if (debug >= 1)
            log("list: Listing contexts for virtual host '" +
                deployer.getName() + "'");
        writer.println(sm.getString("managerServlet.listed",
                                    deployer.getName()));
        String contextPaths[] = deployer.findDeployedApps();
        for (int i = 0; i < contextPaths.length; i++) {
            Context context = deployer.findDeployedApp(contextPaths[i]);
            String displayPath = contextPaths[i];
            if( displayPath.equals("") )
                displayPath = "/";
            if (context != null ) {
                if (context.getAvailable()) {
                    writer.println(sm.getString("managerServlet.listitem",
                                                displayPath,
                                                "running",
                                      "" + context.getManager().findSessions().length,
                                                context.getDocBase()));
                } else {
                    writer.println(sm.getString("managerServlet.listitem",
                                                displayPath,
                                                "stopped",
                                                "0",
                                                context.getDocBase()));
                }
            }
        }
    }
对以上代码的分析(Analysis):
A1)list()方法会调用部署器的 findDeployedApps()方法来获取catalina中所有已经部署了的 Context的路径;
A2)然后,对path 数组进行迭代,获取每一个Context,然后检查该 Context是否可用;
A3)对每个可用的 Context:list()方法输出上下文路径,字符串 "running",用户session 的数量以及文档的根路径;
A4)对那些不可用的 Context:list()方法输出上下文路径,字符串 "stopped",0 以及文档的根路径;

【5】启动web 应用程序
1)使用如下URL 来启动某个web 应用程序: http://localhost:8888/manager/start?path=ContextPath , 而ContextPath是想要启动web 应用程序的路径;
2)在接收到该URL后,会调用 ManagerServlet.start() 方法;
protected void start(PrintWriter writer, String path) { //org.apache.catalina.manager.ManagerServlet.start().
        if (debug >= 1)
            log("start: Starting web application at '" + path + "'");
        if ((path == null) || (!path.startsWith("/") && path.equals(""))) {
            writer.println(sm.getString("managerServlet.invalidPath", path));
            return;
        }
        String displayPath = path;
        if( path.equals("/") )
            path = "";
        try {
            Context context = deployer.findDeployedApp(path); // highlight line.
            if (context == null) {
                writer.println(sm.getString("managerServlet.noContext", displayPath));
                return;
            }
            deployer.start(path);// highlight line.
            if (context.getAvailable())
                writer.println
                    (sm.getString("managerServlet.started", displayPath));
            else
                writer.println
                    (sm.getString("managerServlet.startFailed", displayPath));
        } //......
    }
public void start(String contextPath) throws IOException { //org.apahce.catalina.core.StandardHostDeployer.start().
        // Validate the format and state of our arguments
        if (contextPath == null)
            throw new IllegalArgumentException
                (sm.getString("standardHost.pathRequired"));
        if (!contextPath.equals("") && !contextPath.startsWith("/"))
            throw new IllegalArgumentException
                (sm.getString("standardHost.pathFormat", contextPath));
        Context context = findDeployedApp(contextPath);
        if (context == null)
            throw new IllegalArgumentException
                (sm.getString("standardHost.pathMissing", contextPath));
        host.log("standardHost.start " + contextPath);
        try {
            ((Lifecycle) context).start(); // highlight line.启动Context容器.
        } //......
    }
对以上代码的分析(Analysis):在执行一些检查工作后,start()方法会在 try代码块中调用部署器的 findDeployedApp()方法,该方法返回参数path 指向的Context对象。如果context不是null,start()方法调用部署器的start()方法来启动该 web 应用程序;

【6】关闭web 应用程序 
1)intro:使用如下URL 关闭某个web 应用程序:  http://localhost:8888/manager/stop?path=ContextPath;
2)在接收到该URL后,会调用 ManagerServlet.stop() 方法;
protected void stop(PrintWriter writer, String path) { //org.apache.catalina.manager.ManagerServlet.stop().
        if (debug >= 1)
            log("stop: Stopping web application at '" + path + "'");
        if ((path == null) || (!path.startsWith("/") && path.equals(""))) {
            writer.println(sm.getString("managerServlet.invalidPath", path));
            return;
        }
        String displayPath = path;
        if( path.equals("/") )
            path = "";
        try {
            Context context = deployer.findDeployedApp(path); //highlight line.
            if (context == null) {
                writer.println(sm.getString("managerServlet.noContext", displayPath));
                return;
            }
            // It isn't possible for the manager to stop itself
            if (context.getPath().equals(this.context.getPath())) {
                writer.println(sm.getString("managerServlet.noSelf"));
                return;
            }
            deployer.stop(path); // highlight line.
            writer.println(sm.getString("managerServlet.stopped", displayPath));
        } //.....
    }
public void stop(String contextPath) throws IOException { //org.apahce.catalina.core.StandardHostDeployer.start().

        // Validate the format and state of our arguments
        if (contextPath == null)
            throw new IllegalArgumentException
                (sm.getString("standardHost.pathRequired"));
        if (!contextPath.equals("") && !contextPath.startsWith("/"))
            throw new IllegalArgumentException
                (sm.getString("standardHost.pathFormat", contextPath));
        Context context = findDeployedApp(contextPath);
        if (context == null)
            throw new IllegalArgumentException
                (sm.getString("standardHost.pathMissing", contextPath));
        host.log("standardHost.stop " + contextPath);
        try {
            ((Lifecycle) context).stop(); //highlight line. 停止该容器.
        } catch (LifecycleException e) {
            host.log("standardHost.stop " + contextPath + ": ", e);
            throw new IllegalStateException
                ("standardHost.stop " + contextPath + ": " + e);
        }
    }
public synchronized void stop() throws LifecycleException { // org.apache.catalina.core.StandardContext.stop().
        // Validate and update our current component state
        if (!started)
            throw new LifecycleException
                (sm.getString("containerBase.notStarted", logName()));

        if (debug >= 1)
            log("Stopping");

        // Notify our interested LifecycleListeners
        lifecycle.fireLifecycleEvent(BEFORE_STOP_EVENT, null);
        // Mark this application as unavailable while we shut down
        setAvailable(false);
        // Binding thread
        ClassLoader oldCCL = bindThread();
        // Stop our filters
        filterStop();
        // Stop our application listeners
        listenerStop();
        // Finalize our character set mapper
        setCharsetMapper(null);
        if ((manager != null) && (manager instanceof Lifecycle)) {
            ((Lifecycle) manager).stop();
        }
        // Normal container shutdown processing
        if (debug >= 1)
            log("Processing standard container shutdown");
        // Notify our interested LifecycleListeners
        lifecycle.fireLifecycleEvent(STOP_EVENT, null);
        started = false;

        try {
            // Stop the Valves in our pipeline (including the basic), if any
            if (pipeline instanceof Lifecycle) {
                ((Lifecycle) pipeline).stop();
            }
            // Stop our child containers, if any
            Container children[] = findChildren();
            for (int i = 0; i < children.length; i++) {
                if (children[i] instanceof Lifecycle)
                    ((Lifecycle) children[i]).stop();
            }
            // Stop our Mappers, if any
            Mapper mappers[] = findMappers();
            for (int i = 0; i < mappers.length; i++) {
                if (mappers[(mappers.length-1)-i] instanceof Lifecycle)
                    ((Lifecycle) mappers[(mappers.length-1)-i]).stop();
            }
            // Stop resources
            resourcesStop();
            if ((realm != null) && (realm instanceof Lifecycle)) {
                ((Lifecycle) realm).stop();
            }
            if ((cluster != null) && (cluster instanceof Lifecycle)) {
                ((Lifecycle) cluster).stop();
            }
            if ((logger != null) && (logger instanceof Lifecycle)) {
                ((Lifecycle) logger).stop();
            }
            if ((loader != null) && (loader instanceof Lifecycle)) {
                ((Lifecycle) loader).stop();
            }
        } finally {
            // Unbinding thread
            unbindThread(oldCCL);
        }
        // Reset application context
        context = null;
        // Notify our interested LifecycleListeners
        lifecycle.fireLifecycleEvent(AFTER_STOP_EVENT, null); 
        if (debug >= 1)
            log("Stopping complete");
    }
Conclusion)
C1)本文讲解了如何使用一个专用的接口(ContainerServlet)来创建一个可以访问 Catalina内部类的 servlet类;
C2)可以用来管理已部署web 应用程序的 Manager应用程序展示了如何从 Wrapper对象中获取其他 Catalina对象;


版权声明:本文为博主原创文章,未经博主允许不得转载。

常量池知多少——class文件替换无效引发的思考

终于,经过一次次需求和设计的更改,项目终于快要上线了。可是最近几天,我发现了一个特别古怪的问题: 一般来说,我们更新网站,就是把最近的class文件,替换掉原先的class文件即可。服务器如Tomca...
  • liu765023051
  • liu765023051
  • 2015年01月27日 21:23
  • 3490

常量池知多少——class文件替换无效引发的思考

终于,经过一次次需求和设计的更改,项目终于快要上线了,兴奋啊,哈哈。咳咳。。。大家记得关注哈。 可是最近几天,我发现了一个特别古怪的问题: 替换掉原先的类文件无效,重启服务器也无效! ps实...
  • w2222288
  • w2222288
  • 2016年01月26日 10:00
  • 831

How tomcat works——19 管理Servlet

概述Tomcat4/5有一个 Manager 应用程序用于管理部署的应用程序。跟其它应用程序不同,Manager 并不在%CATALINA_HOME%/webapps 目录下而是在%CATALINA_...
  • LoveJavaYDJ
  • LoveJavaYDJ
  • 2017年04月16日 18:57
  • 658

Servlet 使用介绍(1)

说明本篇介绍java web中比较重要的一个技术:servlet。servlet是一种对用户请求动态响应的一个技术,是java web的核心一环。对于一般服务性质的纯后台服务应用而言,或许整个应用是由...
  • chf1142152101
  • chf1142152101
  • 2017年08月06日 01:11
  • 226

移动终端接入无线网络控制管理 - 接入控制等级介绍(Access Control Class)

Access Control allows restriction of call access attempts. All mobile stations are assigned to a "lo...
  • ghxbob
  • ghxbob
  • 2013年11月04日 22:24
  • 2482

jsp和Servlet的区别以及什么时候创建Servlet或者class文件

什么时候创建Servlet或者class文件: 处理用户请求的,接收用来页面发来的请求,要返回到jsp页面就servlet,如登录(获取用户名密码),注册等(获取用户信息),分页。 具体业务逻辑的实现...
  • u013223565
  • u013223565
  • 2015年08月12日 10:29
  • 1734

关于servlet和jsp的学习总结一(详细)

一、常用的web服务器 主要有Tomact、Resin、Apache、IIS。 1、在这里主要讲一下关于Tomact和Apache的区别 说法一 A:Apache支持静...
  • guo_love_peng
  • guo_love_peng
  • 2011年08月08日 20:15
  • 739

servlet实现用户登录

最近在做课程设计,之前有人问我用户登录的实现,刚又有同学问到,于是我决定还把这个问题的实现写一下吧,免得要一遍一遍的去讲……原谅我的懒惰=_==============================...
  • lmb55
  • lmb55
  • 2015年06月01日 01:23
  • 5361

关于不重启Tomcat自动加载改变的class文件

关于不重启Tomcat自动加载改变的class文件
  • wf632856695
  • wf632856695
  • 2016年12月03日 15:44
  • 4661

eclipse发布程序到Tomcat class文件丢失

做项目的时候遇到个问题,新写的类,启动的时候总是报错,报的错误非常离谱,感觉是发布到tomcat 中的项目丢东西了,于是找到tomcat中一看,配置文件都在,就是class文件丢失了.排除法 开始以为...
  • liuyifeng1920
  • liuyifeng1920
  • 2015年11月12日 16:01
  • 11502
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:tomcat(19)Manager应用程序的servlet类
举报原因:
原因补充:

(最多只允许输入30个字)