NingG +

Tomcat 梳理

几点:

简介

Apache Tomcat,开源软件(这句是废话),支持Java Servlet和JavaServer Pages(JSP)的实现,具体Java Servlet和JavaServer Pages specification是由JCP(Java Community Process)主导制定。Tomcat不是完整意义上的Java EE服务器,没有提供完整的Java EE API支持(实际上,TomEE服务器支持完成的Java EE API),Tomcat对Java开源框架Structs、Spring、Hibernate等,实现完美支持。

安装、启动Tomcat

几个步骤:

实际上,执行$APACHE_HOMT/bin/startup.bat后,会出现如下信息:

2015-3-23 16:51:55 org.apache.coyote.AbstractProtocol start
信息: Starting ProtocolHandler ["http-apr-8080"]
2015-3-23 16:51:55 org.apache.coyote.AbstractProtocol start
信息: Starting ProtocolHandler ["ajp-apr-8009"]
2015-3-23 16:51:55 org.apache.catalina.startup.Catalina start
信息: Server startup in 691 ms

上述信息中,出现的两个数字80808009为Tomcat默认监听的端口。

Tomcat常用配置

Tomcat依赖server.xml文件来启动Sserver,一个Tomcat实例,核心就是启动容器Catalina。

Tomcat部署Webapp时,依赖context.xmlweb.xml来部署Web应用。实际上,在部署任何一个webapp时,Tomcat自带的context.xml以及web.xml都会生效,同时webapp自带的META-INF/context.xml和WEB-INF/web.xml也会定义每个webapp的特定行为。

web.xml

此处的web.xml文件,也是由Servlet官方规范来限定的,更多信息可参考:

补充:

web.xml文件中,示例代码片段:

<web-app>

	<servlet>
		<servlet-name>default</servlet-name>
		<servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
		<init-param>
			<param-name>debug</param-name>
			<param-value>0</param-value>
		</init-param>
		<init-param>
			<param-name>listings</param-name>
			<param-value>false</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
	
	<servlet>
		<servlet-name>jsp</servlet-name>
		<servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
		<init-param>
			<param-name>fork</param-name>
			<param-value>false</param-value>
		</init-param>
		<init-param>
			<param-name>xpoweredBy</param-name>
			<param-value>false</param-value>
		</init-param>
		<load-on-startup>3</load-on-startup>
	</servlet>
	
	<!-- The mapping for the default servlet -->
	<servlet-mapping>
		<servlet-name>default</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>

	<!-- The mappings for the JSP servlet -->
	<servlet-mapping>
		<servlet-name>jsp</servlet-name>
		<url-pattern>*.jsp</url-pattern>
		<url-pattern>*.jspx</url-pattern>
	</servlet-mapping>
	
	<filter>
		<filter-name>...</filter-name>
		<filter-class>...</filter-class>
	</filter>
	
	<filter-mapping>
		<filter-name>...</filter-name>
		<url-pattern>...</url-pattern>
	</filter-mapping>
	
	<!-- session失效时间(mins) -->
	<session-config>
		<session-timeout>30</session-timeout>
	</session-config>
	
	<!-- 请求静态资源时,根据资源后缀,添加`Content-Type`属性 -->
	<mime-mapping>
		<extension>123</extension>
		<mime-type>application/vnd.lotus-1-2-3</mime-type>
	</mime-mapping>

	<!-- 欢迎页面 -->
	<welcome-file-list>
		<welcome-file>index.html</welcome-file>
		<welcome-file>index.htm</welcome-file>
		<welcome-file>index.jsp</welcome-file>
	</welcome-file-list>

</web-app>

思考:上述代码中,当请求url为index.jsp时,上述两个Servelt如何进行处理?RE:单独整理了一篇文章。

server.xml

server.xml配置文件详解,官网地址:Apache Tomcat 8 Configuration Reference

Tomcat Server的结构图:

Tomcat的server.xml文件基本结构:

<Server>
	<Listener />
	<GlobaNamingResources></GlobaNamingResources
	<Service>
		<Executor />
		<Connector />
		<Engine>
			<Cluster />
			<Realm />
			<Realm />
			   <Host>
				   <Valve />
				   <Context />
			   </Host>
		</Engine>
	</Service>
</Server>

Server

Server是Catalina Servlet容器。属性如下:

Listener

Listener即监听器,负责监听特定的事件,当特定事件触发时,Listener会捕捉到该事件,并做出相应处理。Listener通常用在Tomcat的启动和关闭过程。Listener可嵌在Server、Engine、Host、Context内。常用属性:

GlobalNamingResources

GlobalNamingResources用于配置JNDI。

Service

Service包装Executor、n个Connector、1个Engine,Connector获取request,Engine处理request。Server可以包含多个Service组件。 常用属性:

Executor

Executor即Service提供的线程池,供Service内各组件使用,特别是Connector组件。

Connector

Connector是Tomcat接收请求的入口,每个Connector有自己专属的监听端口;Connector有两种:HTTP Connector和AJP Connector。 常用属性:

HTTP与AJP:

Engine

Engine负责处理Service内的所有请求。它接收来自Connector的请求,并决定传给哪个Host来处理,Host处理完请求后,将结果返回给Engine,Engine再将结果返回给Connector。 常用属性:

几点:

Host

关于Host,几点:

Engine与Host之间,几点:

Host负责管理一个或多个Web项目。常用属性:

Context

几点:

将一个Web项目(D:\MyApp)添加到Tomcat,在Host标签内,添加Context标签

<Context path="" docBase="D:\MyApp"  reloadable="true" crossContext="true"></Context>

常用属性:

Cluster

Tomcat集群配置。

Realm

Realm可以理解为包含用户、密码、角色的”数据库”。Tomcat定义了多种Realm实现:

Valve

Valve可以理解为Tomcat的拦截器,而我们常用filter为项目内的拦截器。Valve可以用于Tomcat的日志、权限等。Valve可嵌在Engine、Host、Context内。

小结:Request处理过程

request为http://localhost:8080/examples/index.html,回顾一下Tomcat处理请求的流程图:

Server和Service充当的就是包装的角色:

更多细节:

context.xml

所有host下Context的默认配置信息;默认配置如下:

<Context>
	<WatchedResource>WEB-INF/web.xml</WatchedResource>
</Context>

说明:每个Context代表了运行在Host上的一个Web app。

tomcat-users.xml

Realm认证时用到的相关角色、用户和密码等信息;Tomcat自带的manager默认情况下会用到此文件;在Tomcat中添加/删除用户,为用户指定角色等将通过编辑此文件实现;

其他配置文件

其他配置文件:

Tomcat基本原理

推荐资料:

疑问:Tomcat运行时,是一个Process,那在Tomcat容器中部署的web应用,是作为process启动的?还是直接thread?

Tomcat Server处理一个HTTP请求的过程

假设来自客户的请求为:

http://localhost:8080/wsota/wsota_index.jsp

基本过程:

  1. 请求被发送到本机(localhost)端口8080,被在那里侦听的Coyote HTTP/1.1 Connector获得
  2. Connector把该请求交给它所在的Service的Engine来处理,并等待来自Engine的回应
  3. Engine获得请求localhost/wsota/wsota_index.jsp,匹配它所拥有的所有虚拟主机Host
  4. Engine匹配到名为localhost的Host(即使匹配不到也把请求交给该Host处理,因为该Host被定义为该Engine的默认主机)
  5. localhost Host获得请求/wsota/wsota_index.jsp,匹配它所拥有的所有Context
  6. Host匹配到路径为/wsota的Context(如果匹配不到就把该请求交给路径名为”“的Context去处理)
  7. path=”/wsota”的Context获得请求/wsota_index.jsp,在它的mapping table中寻找对应的servlet
  8. Context匹配到URL PATTERN为*.jsp的servlet,对应于JspServlet类
  9. 构造HttpServletRequest对象和HttpServletResponse对象,作为参数调用JspServlet的doGet或doPost方法
  10. Context把执行完了之后的HttpServletResponse对象返回给Host
  11. Host把HttpServletResponse对象返回给Engine
  12. Engine把HttpServletResponse对象返回给Connector
  13. Connector把HttpServletResponse对象返回给客户browser

单实例应用程序配置一例

规划:

分析:

注:下面两个配置文件,没有验证。

conf/server.xml 配置文件:

<Server port="8005" shutdown="SHUTDOWN"> 
  <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" /> 
  <Listener className="org.apache.catalina.core.JasperListener" /> 
  <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" /> 
  <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" /> 
  <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" /> 
  


  <!-- 全局命名资源,来定义一些外部访问资源,其作用是为所有引擎应用程序所引用的外部资源的定义 -->
  <GlobalNamingResources>  

	<!-- 定义的一个名叫“UserDatabase”的认证资源,将conf/tomcat-users.xml加载至内存中,
		在需要认证的时候到内存中进行认证 --> 
	<Resource name="UserDatabase" auth="Container" 
			  type="org.apache.catalina.UserDatabase" 
			  description="User database that can be updated and saved" 
			  factory="org.apache.catalina.users.MemoryUserDatabaseFactory" 
			  pathname="conf/tomcat-users.xml" /> 

  </GlobalNamingResources> 
  
  <!-- # 定义Service组件,同来关联Connector和Engine,一个Engine可以对应多个Connector,每个Service中只能一个Engine --> 
  <Service name="Catalina"> 


	<!-- 修改HTTP/1.1的Connector监听端口为80.客户端通过浏览器访问的请求,只能通过HTTP传递给tomcat。  --> 
	<Connector port="80" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" /> 
	<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" /> 


	<Engine name="Catalina" defaultHost="test.com"> 
	<!-- 修改当前Engine,默认主机是,www.test.com  --> 


	<Realm className="org.apache.catalina.realm.LockOutRealm"> 
		<Realm className="org.apache.catalina.realm.UserDatabaseRealm" 
			   resourceName="UserDatabase"/> 
	</Realm> 
	<!-- # Realm组件,定义对当前容器内的应用程序访问的认证,通过外部资源UserDatabase进行认证   -->


	  <Host name="test.com"  appBase="/web" unpackWARs="true" autoDeploy="true"> 
	  <!--  定义一个主机,域名为:test.com,应用程序的目录是/web,设置自动部署,自动解压    --> 


		<Alias>www.test.com</Alias> 
		<!--    定义一个别名www.test.com,类似apache的ServerAlias --> 


		<Context path="" docBase="www/" reloadable="true" /> 
		<!--    定义该应用程序,访问路径"",即访问www.test.com即可访问,网页目录为:相对于appBase下的www/,
			即/web/www,并且当该应用程序下web.xml或者类等有相关变化时,
			自动重载当前配置,即不用重启tomcat使部署的新应用程序生效  --> 


		<Context path="/bbs" docBase="/web/bbs" reloadable="true" /> 
		<!--  定义另外一个独立的应用程序,访问路径为:www.test.com/bbs,该应用程序网页目录为/web/bbs   --> 


		<Valve className="org.apache.catalina.valves.AccessLogValve" directory="/web/www/logs" 
			   prefix="www_access." suffix=".log" 
			   pattern="%h %l %u %t &quot;%r&quot; %s %b" /> 
		<!--   定义一个Valve组件,用来记录tomcat的访问日志,日志存放目录为:/web/www/logs,
			如果定义为相对路径则是相当于$CATALINA_HOME,并非相对于appBase,这个要注意。
			定义日志文件前缀为www_access.并以.log结尾,pattern定义日志内容格式,
			具体字段表示可以查看tomcat官方文档 --> 
	  </Host> 


	  <Host name="manager.test.com" appBase="webapps" unpackWARs="true" autoDeploy="true"> 
	  <!--   定义一个主机名为manager.test.com,应用程序目录是$CATALINA_HOME/webapps,自动解压,自动部署 --> 


		<Valve className="org.apache.catalina.valves.RemoteAddrValve" allow="172.23.136.*" /> 
		<!--   定义远程地址访问策略,仅允许172.23.136.*网段访问该主机,其他的将被拒绝访问  --> 


		<Valve className="org.apache.catalina.valves.AccessLogValve" directory="/web/bbs/logs" 
			   prefix="bbs_access." suffix=".log" 
			   pattern="%h %l %u %t &quot;%r&quot; %s %b" /> 
		<!--   定义该主机的访问日志   --> 


	  </Host> 
	</Engine> 
  </Service> 
</Server> 

conf/tomcat-users.xml配置文件:

<?xml version='1.0' encoding='utf-8'?> 
<tomcat-users> 

  <role rolename="manager-gui" /> 
  <!--  定义一种角色名为:manager-gui  --> 


  <user username="cz" password="manager$!!110" roles="manager-gui" /> 
  <!--  定义一个用户的用户名以及密码,并赋予manager-gui的角色    --> 


</tomcat-users> 

参考来源

杂谈

重走web路,一年多没碰web的东西,该忘的都忘了,用到的时候,需要重新查阅,现在只有解决问题的基本思路,索性借着这次重新使用java web的机会把整体的内容再过一遍。

原文地址:https://ningg.top/tomcat-intro/
微信公众号 ningg, 联系我

同类文章:

微信搜索: 公众号 ningg, 联系我, 交个朋友.

Top