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

【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 morecontributor license agreements.  See the NOTICE file distributed withthis 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 withthe License.  You may obtain a copy of the License athttp://www.apache.org/licenses/LICENSE-2.0Unless required by applicable law or agreed to in writing, softwaredistributed 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 andlimitations 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/javaeehttp://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 aStoreManager 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 itselfif (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 typeif (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 useUserDatabase 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 roleswriter.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]++;elsetimeout[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 applicationContext 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 deploymentcheck(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));elsewriter.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 argumentsif (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 itselfif (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 argumentsif (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 stateif (!started)throw new LifecycleException(sm.getString("containerBase.notStarted", logName()));if (debug >= 1)log("Stopping");// Notify our interested LifecycleListenerslifecycle.fireLifecycleEvent(BEFORE_STOP_EVENT, null);// Mark this application as unavailable while we shut downsetAvailable(false);// Binding threadClassLoader oldCCL = bindThread();// Stop our filtersfilterStop();// Stop our application listenerslistenerStop();// Finalize our character set mappersetCharsetMapper(null);if ((manager != null) && (manager instanceof Lifecycle)) {((Lifecycle) manager).stop();}// Normal container shutdown processingif (debug >= 1)log("Processing standard container shutdown");// Notify our interested LifecycleListenerslifecycle.fireLifecycleEvent(STOP_EVENT, null);started = false;try {// Stop the Valves in our pipeline (including the basic), if anyif (pipeline instanceof Lifecycle) {((Lifecycle) pipeline).stop();}// Stop our child containers, if anyContainer children[] = findChildren();for (int i = 0; i < children.length; i++) {if (children[i] instanceof Lifecycle)((Lifecycle) children[i]).stop();}// Stop our Mappers, if anyMapper 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 resourcesresourcesStop();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 threadunbindThread(oldCCL);}// Reset application contextcontext = null;// Notify our interested LifecycleListenerslifecycle.fireLifecycleEvent(AFTER_STOP_EVENT, null); if (debug >= 1)log("Stopping complete");}
Conclusion)
C1)本文讲解了如何使用一个专用的接口(ContainerServlet)来创建一个可以访问 Catalina内部类的 servlet类;
C2)可以用来管理已部署web 应用程序的 Manager应用程序展示了如何从 Wrapper对象中获取其他 Catalina对象;


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/331141.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用Java 8 Stream像操作SQL一样处理数据(下)

转载自 使用Java 8 Stream像操作SQL一样处理数据&#xff08;下&#xff09; 在上一篇文章中&#xff0c;我们介绍了Stream可以像操作数据库一样来操作集合&#xff0c;但是我们没有介绍 flatMap 和 collect 操作。这两种操作对实现复杂的查询是非常有用的。比如你可以结果 fl…

spring(4)面向切面的Spring(AOP)

【0】README1&#xff09;本文部分文字描述转自&#xff1a;“Spring In Action&#xff08;中/英文版&#xff09;”&#xff0c;旨在review “spring(4)面向切面的Spring&#xff08;AOP&#xff09;”的相关知识&#xff1b;2&#xff09;在软件开发中&#xff0c;散布于应…

Mybatis-plus 思维导图,让 Mybatis-plus 不再难懂

转载自 Mybatis-plus 思维导图&#xff0c;让 Mybatis-plus 不再难懂 摘要: Mybatis-Plus&#xff08;简称MP&#xff09;是一个Mybatis的增强工具&#xff0c;在 Mybatis 的基础上只做增强不做改变&#xff0c;为简化开发、提高效率而生。mybatis-plus与mybatis mybatis Mybat…

报错:The type javax.servlet.http.HttpServletRequest cannot be resolved

【0】README 0.1&#xff09;以下内容转自&#xff1a; http://blog.csdn.net/vincent080928/article/details/5392891 problem&#xff09;The type javax.servlet.http.HttpServletRequest cannot be resolved. It is indirectly referenced from required .class files. 这…

MyBatis 思维导图,让 MyBatis 不再难懂(一)

转载自 MyBatis 思维导图&#xff0c;让 MyBatis 不再难懂&#xff08;一&#xff09;写在前面与hibernate相比&#xff0c;我无疑更喜欢mybatis&#xff0c;就因为我觉得它真的好用&#xff0c;哈哈。它简单上手和掌握&#xff1b;sql语句和代码分开&#xff0c;方便统一管理和…

tomcat(20)基于JMX的管理

【0】README1&#xff09;本文部分文字描述转自&#xff1a;“深入剖析tomcat”&#xff0c;旨在学习“tomcat(20)基于JMX的管理” 的相关知识&#xff1b;2&#xff09;晚辈我在tomcat上部署web 项目以测试JMX管理 tomcat 容器bean的效果&#xff0c;结果运行不成功&#xff0…

mybatis思维导图,让mybatis不再难懂(二)

转载自 mybatis思维导图&#xff0c;让mybatis不再难懂&#xff08;二&#xff09; 写在前面 上一篇文章写了mybatis的基本原理和配置文件的基本使用&#xff0c;这一篇写mybatis的使用&#xff0c;主要包括与sping集成、动态sql、还有mapper的xml文件一下复杂配置等。值得注意…

spring(5)构建 spring web 应用程序

【0】README1&#xff09;本文部分文字描述转自&#xff1a;“Spring In Action&#xff08;中/英文版&#xff09;”&#xff0c;旨在review “spring(5)构建 spring web 应用程序” 的相关知识&#xff1b;【1】spring mvc 起步【1.1】跟踪spring mvc的请求1&#xff09;请求…

Spring思维导图,让Spring不再难懂(ioc篇)

转载自 Spring思维导图&#xff0c;让Spring不再难懂&#xff08;ioc篇&#xff09; 写过java的都知道&#xff1a;所有的对象都必须创建&#xff1b;或者说&#xff1a;使用对象之前必须先创建。而使用ioc之后&#xff0c;你就可以不再手动创建对象&#xff0c;而是从ioc容器中…

spring(6) 渲染web视图

【0】README1&#xff09;本文部分文字描述转自&#xff1a;“Spring In Action&#xff08;中/英文版&#xff09;”&#xff0c;旨在review “spring(6) 渲染web视图” 的相关知识&#xff1b;【1】 理解视图解析【1.1】视图解析的基础知识以及spring 提供的其他视图解析器1…

Spring思维导图,让Spring不再难懂(aop篇)

转载自 Spring思维导图&#xff0c;让Spring不再难懂&#xff08;aop篇&#xff09; 什么是aop AOP&#xff08;Aspect-OrientedProgramming&#xff0c;面向方面编程&#xff09;&#xff0c;可以说是OOP&#xff08;Object-Oriented Programing&#xff0c;面向对象编程&…

tomcatSupplement(1)tomcat启动脚本分析(以Windows平台为例)

【0】README1&#xff09;本文部分文字描述转自&#xff1a;“深入剖析tomcat”&#xff0c;旨在学习“tomcat启动脚本分析” 的相关知识&#xff1b;2&#xff09;for tomcat4 startup files&#xff0c; please visit https://github.com/pacosonTang/HowTomcatWorks/tree/ma…

Spring思维导图,让spring不再难懂(一)

转载自 Spring思维导图&#xff0c;让spring不再难懂&#xff08;一&#xff09; 摘要: Spring是一个开源框架&#xff0c;是为了解决企业应用程序开发复杂性而创建的。框架的主要优势之一就是其分层架构&#xff0c;分层架构允许您选择使用哪一个组件&#xff0c;同时为 J2EE …

spring(7)spring mvc 的高级技术

【0】README1&#xff09;本文部分文字描述转自&#xff1a;“Spring In Action&#xff08;中/英文版&#xff09;”&#xff0c;旨在review “spring(7)spring mvc 的高级技术” 的相关知识&#xff1b;2&#xff09;本文将会看到如何编写控制器来处理文件上传&#xff0c;如…

Ubuntu下MySQL、Redis以及MongoDB三个数据库的启动、重启以及停止命令

一、MySQL #启动 /etc/init.d/mysql start #停止 /etc/init.d/mysql stop #重启 /etc/init.d/mysql restart 二、Redis #启动 redis-server #停止 pkill redis-server三、MongoDB #启动服务 sudo service mongod start #重启 sudo service mongod restart #终止 sudo serv…

Spring思维导图,让Spring不再难懂(mvc篇)

转载自 Spring思维导图&#xff0c;让Spring不再难懂&#xff08;mvc篇&#xff09;spring mvc简介与运行原理Spring的模型-视图-控制器&#xff08;MVC&#xff09;框架是围绕一个DispatcherServlet来设计的&#xff0c;这个Servlet会把请求分发给各个处理器&#xff0c;并支持…

spring(10)通过spring 和 JDBC征服数据库

【0】README1&#xff09;本文部分文字描述转自&#xff1a;“Spring In Action&#xff08;中/英文版&#xff09;”&#xff0c;旨在review “spring(10)通过spring 和 JDBC征服数据库” 的相关知识&#xff1b;【1】 spring 的数据访问哲学1&#xff09;intro&#xff1a;s…

Ubuntu下apt-get方式Git的安装、配置和更新

一、首先命令行下载Git sudo apt-get update sudo apt-get install git 通过此种方式安装的git可能不是官方的最新版本&#xff0c;通过 git --version 查看版本信息&#xff0c;然后与git官网比对官网下载地址 二、然后配置git的帐号信息 git config --global user.name &q…

Spring思维导图,让Spring不再难懂(cache篇)

转载自 Spring思维导图&#xff0c;让Spring不再难懂&#xff08;cache篇&#xff09; 关于缓存 缓存是实际工作中非常常用的一种提高性能的方法。而在java中&#xff0c;所谓缓存&#xff0c;就是将程序或系统经常要调用的对象存在内存中&#xff0c;再次调用时可以快速从内存…

intro to JNDI

【0】README 1&#xff09;本文转自 http://sishuok.com/forum/blogPost/list/1186.html 【1】原文如下 1&#xff09;JNDI 是什么&#xff1f; JNDI是 Java 命名与目录接口&#xff08;Java Naming and Directory Interface&#xff09;&#xff0c;在J2EE规范中是重要的规范之…