How tomcat works——19 管理Servlet
来源:互联网 发布:淘宝大学怎么进入 编辑:程序博客网 时间:2024/05/29 11:43
概述
Tomcat4/5有一个 Manager 应用程序用于管理部署的应用程序。跟其它应用程序不同,Manager 并不在%CATALINA_HOME%/webapps 目录下而是在%CATALINA_HOME%/server/webapps 下。Manager 有一描述文件 manager.xml在%CATALINA_HOME$/webapps(Tomcat4)或%CATALINA_HOME%/server/webapps(Tomcat5),所以当 Tomcat 启动时就会安装 Manager。
注意:上下文描述符文件已在第 18 章中讨论了。
本章主要介绍 Manager 应用,首先概括的解释了 Manager 是如何工作的,然后介绍了 ContainerServlet 接口。
19.1 使用Manager
Manager 应用可以在%CATALINA_HOME%/server/webapps/manager 目录下找到。该应用中的主 servlet 是 ManagerServlet。在 Tomcat4 中,该类属于org.apache.catalina.servlets 包。在 Tomcat5 中,该类是org.apache.catalina.manager包的一部分,并以JAR包形式部署在WEB-INF/lib目录下。
注意:由于 Tomcat4 中的Manager应用程序相比 Tomcat5 中的要简单,所以它更容易学习,本章主要讨论它。在读完了本章后,你也就可以理解 Tomcat5 中的 Manager是如何工作的了。
这里是 Tomcat4 中对应servlet 元素的部署描述文件:
<servlet> <servlet-name>Manager</servlet-name> <servlet-class>org.apache.catalina.servlets.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.servlets.HTMLManagerServlet</servlet-class> <init-param> <param-name>debug</param-name> <param-value>2</param-value> </init-param></servlet>
第一个 servlet 是 org.apache.catalina.servlets.ManagerServlet,第二个是org.apache.catalina.servlets.HTMLManagerServlet。本章主要介绍ManagerServerlet。
本应用程序的描述文件 manager.xml,说明了本应用程序的上下文路径为/manager:
<Context path="/manager" docBase="../server/webapps/manager" debug="0" privileged="true"><!-- Link to the user database we will get roles from --><ResourceLink name="users" global="UserDatabase" type="org.apache.catalina.UserDatabase"/></Context>
第一个 servlet 映射元素说明如何调用 ManagerServlet:
<servlet-mapping> <servlet-name>Manager</servlet-name> <url-pattern>/*</url-pattern></servlet-mapping>
换句话说,如下形式的 URL 模式将会调用 MangerServlet:
http://localhost:8080/manager/
但是,注意在部署描述符中还有安全限制元素:
<security-constraint> <web-resource-collection> <web-resource-name>Entire Application</web-resource-name> <url-pattern>/*</url-pattern> </web-resource-collection> <auth-constraint> <!-- NOTE: This role is not present in the default users file --> <role-name>manager</role-name> </auth-constraint></security-constraint>
它的意思是说,整个应用程序只能被 manager 角色的用户使用。auth-login 元素规定用户需要提供正确的用户名密码来通过 BASIC 验证:
<login-config> <auth-method>BASIC</auth-method> <realm-name>Tomcat Manager Application</realm-name></login-config>
在 Tomcat 中,用户角色在%CATALINA_HOME%/conf 目录下的 tomcat-users.xml文件中有列表。因此,要进入 Manager 应用程序,必须给用户添加 manager 角色。如下事例:
<?xml version='1.0' encoding='utf-8'?><tomcat-users> <role rolename="manager"/> <user username="tomcat" password="tomcat" roles="manager "/></tomcat-users>
通过该 tomcat-users.xml,我们可以使用用户名tomcat密码tomcat来访问Manager应用程序。
下面的是 ManagerServlet 的可用函数:
•list
•start
•stop
•reload
•remove
•resources
•roles
•sessions
•undeploy
查看servlet 的doGet()方法看下该如何调用一个 function。
19.2 ContainerServlet接口
一个实现了org.apache.catalina.ContainerServlet 接口的servlet 将可以访问代表着它的StandardWrapper 对象。可以访问包装器,它也能访问表示该 web 应用的上下文对象,以及该上下文的部署器(StandardHost 实例)和其它对象。
ContainerServlet 接口如 Listing19.1 所示:
Listing 19.1: The ContainerServlet Interface
package org.apache.catalina;public interface ContainerServlet { public Wrapper getWrapper(); public void setWrapper(Wrapper wrapper);}
Catalina调用实现了ContainerServlet接口的servlet的setWrapper()方法将引用传递给表示该servlet的StandardWrapper。
19.3 初始化ManagerServlet
通常,一个 servlet 用一个org.apache.catalina.core.StandardWrapper实例表示。在第一次调用该 servlet 时,StandardedWrapper 对象的loadServlet()方法会被调用,它又调用 servlet 的 init()方法。接下来我们会看到ManagerServlet 的 loadServlet()方法是如何工作的:
...// Special handling for ContainerServlet instancesif ((servlet instanceof ContainerServlet) &&isContainerProvidedServlet(actualClass)) { ((ContainerServlet) servlet).setWrapper(this);}// Call the initialization method of this servlettry { instanceSupport.fireInstanceEvent(InstanceEvent.BEFORE_INIT_EVENT,servlet); servlet.init(facade);...
该servlet 表示要加载的 servlet(在这里是 ManagerServlet)。
在 if 语句块中,如果 servlet 是 org.apache.catalina.ContainerServlet 的实例并且 isContainerProvidedServlet()方法返回 true。就调用 ContainerServlet接口的 setWrapper() 方法。
ManagerServlet 类实现了 ContainerServlet,因此 servlet 是ContainerSerlvet 的一个实例。在 StanadardWrapper 中的isContainerProvidedServlet()方法如 Listing19.2 所示。
Listing 19.2: The isContainerProvidedServlet method in the StandardWrapper classprivate boolean isContainerProvidedServlet(String classname) { if (classname.startsWith("org.apache.catalina.")) { return (true); } try { Class clazz = this.getClass().getClassLoader().loadClass(classname); return (ContainerServlet.class.isAssignableFrom(clazz)); }catch (Throwable t) { return (false); }}
传递给 isContainerProvidedServlet()方法的参数 classname 是 ManagerSerlvet类的完全限定名,即org.apache.catalina.servlets.ManagerServlet。因此,isContainerProvidedServlet()方法返回 true。
如果该 servlet 类是 ContainerServlet 的子类,该方法也返回 true,例如,classname 是继承了 ContainerServlet的接口 或是实现了 ContainerServlet接口的类。
注意:如果表示当前对象的类或接口跟 clazz 表示的类或接口或相同,或是超类、超接口时, java.lang.Class 类的 isAssignableFrom(Class clazz)则返回true。
因此,表示 ManagerServlet 实例的 StandardWrapper 在它的 loadServlet()方法中会调用 ManagerServlet 的 setWrapper()方法。这里是 ManagerServlet 类对setWrapper()方法的实现:
public void setWrapper(Wrapper wrapper) { this.wrapper = wrapper; if (wrapper == null) { context = null; deployer = null; }else { context = (Context) wrapper.getParent(); deployer = (Deployer) context.getParent(); }}
如果参数 wrapper 不是 null,将会执行 else 语句块。这意味着将表示 Manager 应用的上
下文赋值给 context 变量并将该上下文部署在 StandardHost 实例上。Deployer非常重要,它会在 ManagerServlet 的好几个方法中使用到。
在 StandardWrapper 的 loadServlet()方法调用了ManagerServlet的 setWrapper()方法之后。loadServlet()方法调用 MangerServlet 的 init()方法。
19.4 部署清单
可以使用如下 URL 来查看所部署的所有应用程序:
http://localhost:8080/manager/list
下面是一输出的例子:
OK - Listed applications for virtual host localhost/admin:stopped:0:../server/webapps/admin/app1:running:0:C:\123data\JavaProjects\Pyrmont\webapps\app1/manager:running:0:../server/webapps/manager
上面的 URL 将会调用 ManagerServlet 的list()方法,如 Listing19.3 所示。
Listing 19.3: The list method of ManagerServletprotected void list(PrintWriter writer) { 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())); } } } }
方法 list()调用部署器的 findDeployedApps()来获得所有部署在 Catalina 中的上下文的路径。然后遍历路径数组获得每个独立的上下文并检查该上下文是否可用。对于每个可用的上下文,打印出上下文路径,’running’字符串,用户的Session个数和文档基(document base)。对于不可用的上下文,打印出上下文路径,’stopperd’字符串,0 ,以及文档基。
19.5 启动Web应用
可以使用如下 URL 来启动一个 web 应用:
http://localhost:8080/manager/start?path=/contextPath
contextPath是想要启动的应用的上下文路径。例如,要启动 admin 应用,可以使用如下路径:
http://localhost:8080/manager/start?path=/admin
如果该应用程序已经启动,你会收到错误提示信息。
根据该 URL,ManagerServlet 调用 start()方法,如 Listing19.4 所示。
Listing 19.4: The start method of the ManagerServlet classprotected void start(PrintWriter writer, String path) { 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); if (context == null) { writer.println(sm.getString("managerServlet.noContext", displayPath)); return; } deployer.start(path); if (context.getAvailable()) writer.println (sm.getString("managerServlet.started", displayPath)); else writer.println (sm.getString("managerServlet.startFailed", displayPath)); } catch (Throwable t) { getServletContext().log (sm.getString("managerServlet.startFailed", displayPath), t); writer.println (sm.getString("managerServlet.startFailed", displayPath)); writer.println(sm.getString("managerServlet.exception", t.toString())); } }
在一些检查之后,start()方法调用部署器的 findDeployedApp()方法,该方法根据path路径获得上下文,如果上下文不为空,start()方法则调用部署器的 start()方法来启动该应用程序。
19.6 停止Web应用
可以使用如下命令来停止一个应用程序:
http://localhost:8080/manager/stop?path=/contextPath
contextPath是我们想要停止的 web应用的路径,如果该应用并没有正在运行,则会返回错误信息。
ManagerSerlvet 收到请求时,它调用 stop()方法,如 Listing19.5 所示。
Listing 19.5: The stop method of the ManagerServlet classprotected void stop(PrintWriter writer, String path) { 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); 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); writer.println(sm.getString("managerServlet.stopped", displayPath)); } catch (Throwable t) { log("ManagerServlet.stop[" + displayPath + "]", t); writer.println(sm.getString("managerServlet.exception", t.toString())); } }
通过上面的代码我们可以明白stop()方法是如何工作的。ManagerServlet 类中的其它方法也很消化理解。
19.7小结
本章介绍了如何使用特殊接口 ContainerServelet 来创建一个可以访问Catalina 内部类的 Servlet。Manager 应用可以用于管理部署应用,并说明了如何从包装器对象获得其它对象。另外还可以设计一个更精致的 Servlet 来管理Tomcat。
- How tomcat works——19 管理Servlet
- How tomcat works——9 session管理
- How tomcat works——20 基于JMX的管理
- How tomcat works——引言
- How tomcat works——3 连接器
- How tomcat works——5 容器
- How tomcat works——6 生命周期
- How tomcat works——10 安全性
- How tomcat works——11 StandardWrapper
- How tomcat works——12 StandardContext
- How tomcat works——15 Digester
- How tomcat works——18 部署
- How tomcat works——序言
- How tomcat works——2 一简单的Servlet容器
- how tomcat works 五 servlet容器 上
- how tomcat works 5 servlet容器 下
- how tomcat works 读书笔记九 Session管理
- 【How Tomcat Works】深入剖析Tomcat——引言
- POJ 2892-Tunnel Warfare(线段树单点更新-炸毁修复城市隧道)
- 关于Android单元测试
- java的枚举
- opencv学习(四十三)之图像的矩moments()
- mysql安装包方式安装及配置(Windows)
- How tomcat works——19 管理Servlet
- 初次接触堆排序
- propertyAnimator(属性动画)之objectanimator(动画执行类)
- HDU 1520 Anniversary party (树型dp)
- 自定义屏幕保护
- ApplicationContext国际化实例
- 学习淘淘商城第二十六课(内容分类管理)
- 5-3 树的同构(非递归——懒法)
- FFmpeg常见命令