JavaWeb—Tomcat
简介
Tomcat 是由 Apache 开发的一个 Servlet 容器,实现了对 Servlet 和 JSP 的支持,并提供了作为Web服务器的一些特有功能,如Tomcat管理和控制平台、安全域管理和Tomcat阀等。
Tomcat目录:
- bin:存放启动和关闭tomcat脚本
- conf:存放不同的配置文件(server.xml和web.xml);
- doc:存放Tomcat文档;
- lib/japser/common:存放Tomcat运行需要的库文件(JARS);
- logs:存放Tomcat执行时的LOG文件;
- src:存放Tomcat的源代码;
- webapps:Tomcat的主要Web发布目录(包括应用程序示例);
- work:存放jsp编译后产生的class文件;
Tomcat配置文件:
我们打开conf文件夹可以看到Tomcat的配置文件:
- server.xml: Tomcat的主配置文件,包含Service, Connector, Engine, Realm, Valve, Hosts主组件的相关配置信息;
- web.xml:遵循Servlet规范标准的配置文件,用于配置servlet,并为所有的Web应用程序提供包括MIME映射等默认配置信息;
- tomcat-user.xml:Realm认证时用到的相关角色、用户和密码等信息;Tomcat自带的manager默认情况下会用到此文件;在Tomcat中添加/删除用户,为用户 指定角色等将通过编辑此文件实现;
- catalina.policy:Java相关的安全策略配置文件,在系统资源级别上提供访问控制的能力;
- catalina.properties:Tomcat内部package的定义及访问相关控制,也包括对通过类装载器装载的内容的控制;Tomcat在启动时会事先读取此文件的相关设置;
- logging.properties: Tomcat6通过自己内部实现的JAVA日志记录器来记录操作相关的日志,此文件即为日志记录器相关的配置信息,可以用来定义日志记录的组 件级别以及日志文件的存在位置等;
- context.xml:所有host的默认配置信息;
Tomcat架构及常用的组件:
1、服务器(Server)组件
Tomcat的一个实例,通常一个JVM只能包含一个Tomcat实例;因此,一台物理服务器上可以在启动多个JVM的情况下在每一个JVM中启动一个Tomcat实例,每个实例分属于一个独立的管理端口。这是一个顶级组件。
例如server.xml文件中定义的:
<Server port=”8005” shutdown=”SHUTDOWN”>
它监听在8005端口以接收shutdown命令,使用 telnet 连接8005 端口可以直接执行 SHUTDOWN 命令来关闭 Tomcat。因此,管理员可以直接telnet至此端口使用SHUTDOWN命令关闭此实例。不过,基于安全角度的考虑,这通常不允许远程进行。
Server的相关属性:
- className: 用于实现此Server容器的完全限定类的名称,默认为org.apache.catalina.core.StandardServer;
- port: 接收shutdown指令的端口,默认仅允许通过本机访问,默认为8005;
- shutdown:发往此Server用于实现关闭tomcat实例的命令字符串,默认为SHUTDOWN;
2、服务(Service)组件
Service主要用于关联一个引擎和与此引擎相关的连接器,每个连接器通过一个特定的端口和协议接收入站请求交将其转发至关联的引擎进行处理。因此,Service要包含一个引擎、一个或多个连接器。
例如server.xml文件中定义的:
<Service name=”Catalina”>
这定义了一个名为Catalina的Service,此名字也会在产生相关的日志信息时记录在日志文件当中。给服务命名可以方便管理员在日志文件中识别不同服务产生的日志。
Service相关的属性:
- className: 用于实现service的类名,一般都是org.apache.catalina.core.StandardService。
- name:此服务的名称,默认为Catalina;
3、连接器(Connector)组件
负责连接客户端(可以是浏览器或Web服务器)请求至Servlet容器内的Web应用程序,通常指的是接收客户发来请求的位置及服务器端分配的端口。默认端口通常是HTTP协议的8080,管理员也可以根据自己的需要改变此端口。
进入Tomcat的请求可以根据Tomcat的工作模式分为如下两类:
- Tomcat作为应用程序服务器:请求来自于前端的web服务器,这可能是Apache, IIS, Nginx等;
- Tomcat作为独立服务器:请求来自于web浏览器;
Tomcat应该考虑工作情形并为相应情形下的请求分别定义好需要的连接器才能正确接收来自于客户端的请求。一个引擎可以有一个或多个连接器,以适应多种请求方式,但这些连接器必须使用不同的端口。
定义连接器可以使用多种属性,有些属性也只适用于某特定的连接器类型。一般说来,常见于server.xml中的连接器类型通常有4种:
- HTTP连接器
- SSL连接器
- AJP 1.3连接器
- proxy连接器
如上面示例server.xml中定义的HTTP连接器:
<Connector port=”8080″ protocol=”HTTP/1.1″ maxThreads=”150″ connectionTimeout=”20000″ redirectPort=”8443″/>
定义连接器时可以配置的属性非常多,但通常定义HTTP连接器时必须定义的属性只有“port“,定义AJP连接器时必须定义的属性只有”protocol”,因为默认的协议为HTTP。以下为常用属性的说明:
- address:指定连接器监听的地址,默认为所有地址,即0.0.0.0; 可以自己指定地,如
- maxThreads:支持的最大并发连接数,默认为200;
- port:监听的端口,默认为0;
- protocol:连接器使用的协议,默认为HTTP/1.1,定义AJP协议时通常为AJP/1.3;
- redirectPort:如果某连接器支持的协议是HTTP,当接收客户端发来的HTTPS请求时,则转发至此属性定义的端口;
- connectionTimeout:等待客户端发送请求的超时时间,单位为毫秒,默认为60000,即1分钟;
- enableLookups:是否通过request.getRemoteHost()进行DNS查询以获取客户端的主机名;默认为true; 进行反解的,可以设置为false
- acceptCount:设置等待队列的最大长度;通常在tomcat所有处理线程均处于繁忙状态时,新发来的请求将被放置于等待队列中;
下面是一个定义了多个属性的SSL连接器:
<Connector port=”8443″ maxThreads=”150″ minSpareThreads=”25″ maxSpareThreads=”75″ enableLookups=”false” acceptCount=”100″ debug=”0″ scheme=”https” secure=”true” clientAuth=”false” sslProtocol=”TLS” />
4、引擎(Engine)组件
引擎是指处理请求的Servlet引擎组件,即Catalina Servlet引擎,它检查每一个请求的HTTP首部信息以辨别此请求应该发往哪个host或context,并将请求处理后的结果返回的相应的客户端。严格意义上来说,容器不必非得通过引擎来实现,它也可以是只是一个容器。如果Tomcat被配置成为独立服务器,默认引擎就是已经定义好的引擎。而如果Tomcat被配置为Apache Web服务器的提供Servlet功能的后端,默认引擎将被忽略,因为Web服务器自身就能确定将用户请求发往何处。Engine容器中可以包含Realm、Host、Listener和Valve子容器。
例如server.xml文件中定义的:
<Engine name=”Catalina” defaultHost=”localhost”>
常用的属性定义:
- defaultHost:Tomcat支持基于FQDN的虚拟主机,这些虚拟主机可以通过在Engine容器中定义多个不同的Host组件来实现;但如果此引擎的连接器收到一个发往非明确定义虚拟主机的请求时则需要将此请求发往一个默认的虚拟主机进行处理,因此,在Engine中定义的多个虚拟主机的主机名称中至少要有一个跟defaultHost定义的主机名称同名;
- name:Engine组件的名称,用于日志和错误信息记录时区别不同的引擎;
5、主机(Host)组件
位于Engine容器中用于接收请求并进行相应处理的主机或虚拟主机,如前面示例中的定义:
<Host name=”localhost” appBase=”webapps” unpackWARs=”true” autoDeploy=”true” xmlValidation=”false” xmlNamespaceAware=”false”> </Host>
常用属性说明:
- appBase:此Host的webapps目录,即存放非归档的web应用程序的目录或归档后的WAR文件的目录路径;可以使用基于$CATALINA_HOME的相对路径;
- autoDeploy:在Tomcat处于运行状态时放置于appBase目录中的应用程序文件是否自动进行deploy;默认为true;
- unpackWars:在启用此webapps时是否对WAR格式的归档文件先进行展开;默认为true;
虚拟主机定义示例:
<Engine name=”Catalina” defaultHost=”localhost”> <Host name=”localhost” appBase=”webapps”> <Context path=”” docBase=”ROOT”/> <Context path=”/bbs” docBase=”/web/bss” #path路径是定义在defaultHost背后的 reloadable=”true” crossContext=”true”/> </Host> <Host name=”mail.magedu.com” appBase=”/web/mail”> <Context path=”” docBase=”ROOT”/> </Host> </Engine>
主机别名定义:
如果一个主机有两个或两个以上的主机名,额外的名称均可以以别名的形式进行定义,如下:
<Host name=”www.ttlsa.com” appBase=”webapps” unpackWARs=”true”> <Alias>feiyu.com</Alias> </Host>
6、上下文(Context)组件
Context组件是最内层次的组件,它表示Web应用程序本身。配置一个Context最主要的是指定Web应用程序的根目录,以便Servlet容器能够将用户请求发往正确的位置。Context组件也可包含自定义的错误页,以实现在用户访问发生错误时提供友好的提示信息。
如下面的定义:
<!– Tomcat Root Context –> <Context path=”” docBase=”/web/webapps”/> <!– buzzin webapp –> <Context path=”/bbs” docBase=”/web/threads/bbs” reloadable=”true”> </Context> <!– chat server –> <Context path=”/chat” docBase=”/web/chat”/> <!– darian web –> <Context path=”/darian” docBase=”darian”/>
在Tomcat6中,每一个context定义也可以使用一个单独的XML文件进行,其文件的目录为$CATALINA_HOME/conf/。可以用于Context中的XML元素有Loader,Manager,Realm,Resources和WatchedResource。
常用的属性定义有:
- docBase:相应的Web应用程序的存放位置;也可以使用相对路径,起始路径为此Context所属Host中appBase定义的路径;切记,docBase的路径名不能与相应的Host中appBase中定义的路径名有包含关系,比如,如果appBase为deploy,而docBase绝不能为deploy-bbs类的名字;
- path:相对于Web服务器根路径而言的URI;如果为空“”,则表示为此webapp的根路径;如果context定义在一个单独的xml文件中,此属性不需要定义,有可能是别名;
- reloadable:是否允许重新加载此context相关的Web应用程序的类;默认为false;
7、领域(Realm)组件
领域(Realm):用于用户的认证和授权;在配置一个应用程序时,管理员可以为每个资源或资源组定义角色及权限,而这些访问控制功能的生效需要通过Realm来实现。Realm的认证可以基于文本文件、数据库表、LDAP服务等来实现。Realm的效用会遍及整个引擎或顶级容器,因此,一个容器内的所有应用程序将共享用户资源。同时,Realm可以被其所在组件的子组件继承,也可以被子组件中定义的Realm所覆盖。
- JAASRealm:基于Java Authintication and Authorization Service实现用户认证;
- JDBCRealm:通过JDBC访问某关系型数据库表实现用户认证;
- JNDIRealm:基于JNDI使用目录服务实现认证信息的获取;
- MemoryRealm:查找tomcat-user.xml文件实现用户信息的获取;
- UserDatabaseRealm:基于UserDatabase文件(通常是tomcat-user.xml)实现用户认证,它实现是一个完全可更新和持久有效的MemoryRealm,因此能够跟标准的MemoryRealm兼容;它通过JNDI实现;
下面是一个常见的使用UserDatabase的配置:
<Realm className=”org.apache.catalina.realm.UserDatabaseRealm” resourceName=”UserDatabase”/>
下面是一个使用JDBC方式获取用户认证信息的配置:
<Realm className=”org.apache.catalina.realm.JDBCRealm” debug=”99″ driverName=”org.gjt.mm.mysql.Driver” connectionURL=”jdbc:mysql://localhost/authority” connectionName=”test” connectionPassword=”test” userTable=”users” userNameCol=”user_name” userCredCol=”user_pass” userRoleTable=”user_roles” roleNameCol=”role_name” />
8、阀门(Valve)组件
Valve类似于过滤器,它可以工作于Engine和Host/Context之间、Host和Context之间以及Context和Web应用程序的某资源之间。一个容器内可以建立多个Valve,而且Valve定义的次序也决定了它们生效的次序。Tomcat6中实现了多种不同的Valve:
- AccessLogValve:访问日志Valve
- ExtendedAccessValve:扩展功能的访问日志Valve
- JDBCAccessLogValve:通过JDBC将访问日志信息发送到数据库中;
- RequestDumperValve:请求转储Valve;
- RemoteAddrValve:基于远程地址的访问控制;
- RemoteHostValve:基于远程主机名称的访问控制;
- SemaphoreValve:用于控制Tomcat主机上任何容器上的并发访问数量;
- JvmRouteBinderValve:在配置多个Tomcat为以Apache通过mod_proxy或mod_jk作为前端的集群架构中,当期望停止某节点时,可以通过此Valve将用记请求定向至备用节点;使用此Valve,必须使JvmRouteSessionIDBinderListener;
- ReplicationValve:专用于Tomcat集群架构中,可以在某个请求的session信息发生更改时触发session数据在各节点间进行复制;
- SingleSignOn:将两个或多个需要对用户进行认证webapp在认证用户时连接在一起,即一次认证即可访问所有连接在一起的webapp;
- ClusterSingleSingOn:对SingleSignOn的扩展,专用于Tomcat集群当中,需要结合ClusterSingleSignOnListener进行工作;
RemoteHostValve和RemoteAddrValve可以分别用来实现基于主机名称和基于IP地址的访问控制,控制本身可以通过allow或deny来进行定义,这有点类似于Apache的访问控制功能;如下面的Valve则实现了仅允许本机访问/probe:
<Context path=”/probe” docBase=”probe”> <Valve className=”org.apache.catalina.valves.RemoteAddrValve” allow=”127\.0\.0\.1″/> </Context>
Tomcat请求过程
Tomcat Server处理一个HTTP请求的过程:
描述:
- 用户点击网页内容,请求被发送到本机端口8080,被在那里监听的Coyote HTTP/1.1 Connector获得。
- Connector把该请求交给它所在的Service的Engine来处理,并等待Engine的回应。
- Engine获得请求localhost/test/index.jsp,匹配所有的虚拟主机Host。
- Engine匹配到名为localhost的Host(即使匹配不到也把请求交给该Host处理,因为该Host被定义为该Engine的默认主机),名为localhost的Host获得请求/test/index.jsp,匹配它所拥有的所有的Context。Host匹配到路径为/test的Context(如果匹配不到就把该请求交给路径名为“ ”的Context去处理)。
- path=“/test”的Context获得请求/index.jsp,在它的mapping table中寻找出对应的Servlet。Context匹配到URL PATTERN为*.jsp的Servlet,对应于JspServlet类。
- 构造HttpServletRequest对象和HttpServletResponse对象,作为参数调用JspServlet的doGet()或doPost().执行业务逻辑、数据存储等程序。
- Context把执行完之后的HttpServletResponse对象返回给Host。
- Host把HttpServletResponse对象返回给Engine。
- Engine把HttpServletResponse对象返回Connector。
- Connector把HttpServletResponse对象返回给客户Browser。
参考: