Tomcat简介和应用


Tomcat简介和应用
1.Tomcat 是Web应用服务器,也是一个Servlet/JSP容器。


Tomcat处理一个请求的过程
假设来自客户的请求为:http://localhost:8080/wsota/wsota_index.jsp
1) 请求被发送到本机端口8080,被在那里侦听的CoyoteHTTP/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匹配到URLPATTERN为*.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


Servlet工作过程
1.Servlet容器是运行在JVM中的一个进程(一个一直监听某个网络端口的应用程序)。(就是一个java进程)
2.Servlet是一个处理请求的java程序实例(就是一个类的实例)。实例里面定义了一些接口(init、service、doGet、doPost、destroy),在适当的时候进行调用。
3.Servlet容器接收到一个请求后,会新建一个新的线程去处理这个请求。
4.新的线程运行后,按照URL查找对应的Servlet实例,如果这时Servlet容器中没有这个Servlet实例就会加载这个实例的类并生成一个实例。
5.Servlet实例生成后调用Servlet实例中的init进行初始化(一个实例类只会初始化一次)。
6.Servlet实例初始化后就调用Servlet实例中的service,service检测请求类型后决定调用Servlet实例中doGet或doPost。
7.Servlet实例中doGet或doPost是的处理事务的代码(逻辑处理、数据库访问等)。
8.新的线程运行完Servlet实例的doGet或doPost后得到返回结果后将数据返回给客户端。
9.新的线程的处理完这个请求,新的线程成为空闲线程放到Servlet容器的请求处理线程池中,方便下一个请求到来时,从请求处理线程池中取出来处理请求。
10.请求处理线程池目的是加快请求处理速度,提高性能,线程创建要时间。


Tomcat一共有四种类型的容器:
1.Engine:代表完整的Servlet引擎,是最顶层的容器,在这个容器上调用setParent会抛出异常。一个Engine由多个Host容器组成。
2.Host:代表一个虚拟主机,可以运行多个应用,它负责安装和展开这些应用,其子容器为Context。
3.Context:代表ServletContext,管理多个Servlet,理论上只要有Context就可以运行Servlet了,其子容器为Wrapper。
4.Wrapper:代表一个Servlet,是最底部的容器,它没有子容器。它负责管理一个Servlet,包含Servlet的装载、初始化、执行和卸载等。只有Wrapper也是可以运行Servlet的!


Tomcat如何与web应用产生联系
1.Tomcat启动时会跟据server.xml文件在conf目录下生成一个Engine的文件夹(Engine的名字)。并在Engine文件夹下生成每一个Host的文件夹(Host的名字)
2.读取conf目录下每个Host文件夹下的每个xml文件,xml文件就是为Context的内容(指定URL路径和工作目录是什么)。
3.读取后在Tomcat内部建立相关的联系.
4.Tomcat启动到后面会读取webapps目录中的war包,并为每个war包创建一个Context
5.解压war包,读取web应用中的web.xml中的<servlet>和<servlet-mapping>中的内容,并建立URL与servlet之间的关系表。
6.有了关联表,Context就知道请求应该由那个servlet来完成请求处理了。


Spring MVC在Tomcat中的应用
1.因为Tomcat有默认的Context配置,所以在server.xml中可以不写
2.容器(Tomcat)会创建一个ServletContext(上下文),应用范围内即整个WEB项目都能使用这个上下文。
3.接着容器会将读取web.xml的<context-param>转化为键值对,并交给ServletContext。
4.容器创建web.xml中的<listener></listener>中的类实例,即创建监听(必须需要继承ServletContextListener,设为"org.springframework.web.context.ContextLoaderListener")
5.在监听的类中会有一个contextInitialized(ServletContextEvent event)初始化方法,在这个方法中可以通过event.getServletContext().getInitParameter("contextConfigLocation")来得到context-param 设定的值。
6.在这个类中还必须有一个contextDestroyed(ServletContextEvent event) 销毁方法.用于关闭应用前释放资源,比如说数据库连接的关闭。
7.context-param的contextConfigLocation定义了spring ioc建立的xml文件,扫描包并建立spring中的bean管理,就是建立好相关bean的生成和映射、注入。
8.ContextLoaderListener建立起了spring的运行环境。
9.继续初始化web.xml中的 listener、fileter、servlet(有请求时才初始化),到些运行环境建立好。
10.Spring MVC中web.xml的<servlet>为DispatcherServlet,<servlet-mapping>的<url-pattern>为"/",就是所有符合域名的都会交由DispatcherServlet处理
11.DispatcherServlet里面有自己的匹配关系表与controler进行映射,由原来不同URL交由不同的servlet处理变成了不同的URL交由不同的controler接口(方法来处理)
12.当有请求到来时DispatcherServlet初始化,DispatcherServlet指定了contextConfigLocation参数(如果没指定就是/WEB-INF/[server-name]-servlet.xml(这样的命名规则)),指定就是具体的文件。
13.DispatcherServlet中的contextConfigLocation参数是一个xml文件,负责MVC相关bean的配置管理(如ViewResolver、Controller、MultipartResolver等),就是为MVC建立运行环境
14.DispatcherServlet建立好环境后就会将请求交由对应URL的controler进行处理了


Tomcat自动部署方式(3种)
1.安装tomcat后,把WAR包复制到webapps目录下就就可以了(如果tomcat已经启动),tomcat会自动扫描webapps目录的变化。
(1)自动解压WAR包到当前目录(目录名为WAR包名),生成了一个默认的Context,目录为这个包解压出来的文件夹的目录。对应URL的路径为文件夹的目录名。
(2)符合大多数的应用,但如果URL路径名与war包不一样要改war包名.
(3)项目会解压到webapps目录下
2.在server.xml文件中的Host指定Context,但每增加一个应用(WAR包)都要修改server.xml文件,并且要从启tomcat才会生效。
3.在conf目录中,新建 Catalina(注意大小写)\localhost目录,在该目录中新建一个xml文件,名字可以随意取,只要和当前文件中的文件名不重复就行了。
(1)xml文件名要与path(URL路径名)一样
(2)docBase就是项目包的路径,war包会解压到webapps目录中(<Host中appBase="webapps"指定),非war包不用放到(复制)webapps目录中
(3)不用重启tomcat,可以将包放到非(webapps)目录
(4)删除目录时要将xml文件也要删除,否则会继续到这个目录找相关的项目。
如:
<?xml version='1.0' encoding='utf-8'?>
<Context path="/hellotest" docBase="D:\tomcatTest\test.war" debug="0" privileged="true">
</Context>


server.xml详解
server.xml层次结构
Server//Tomcat的顶层元素
	Service//定义一个服务目录的元素(一般只有一个)
		Connector//定义与客户程序实际交互的组件元素(一般两个),用于监听端口,创建新线程与用户交互(匹配的是IP和端口号)
		Engine//(只有一个),所有的Connector都会将请求发送给它,按URL的域名进行匹配到不同的Host,并将请求交给Host
			Realm//
			Host//虚拟主机(有多个),每个对应一个域名(就好像一个单独的主机一样(因每个IP可对应多个域名,所以有虚拟主机一说)),
				//接收来自Engine的请求,按URL最长匹配(工程匹配)到Context
				Context//Context对应于一个Web Application,一个WebApplication由一个或者多个Servlet组成。(可以多个)
				Valve//定义该虚拟主机的输出log的格式


server.xml分析
<?xml version='1.0' encoding='utf-8'?>

<!-- //1.Server,Tomcat的顶层元素,它代表整个容器,它包含一个或多个Service元素,(一般只有一个Service) -->
<!-- //2.port,指定一个端口,这个端口负责监听关闭tomcat 的请求 -->
<!-- //3.shutdown,指定关闭tomcat要向端口发送的命令字符串 -->
<Server port="8005" shutdown="SHUTDOWN">
	<!-- //1.Tomcat的监听器定义 -->
	<Listener className="org.apache.catalina.startup.VersionLoggerListener" />

	<Listener className="org.apache.catalina.core.AprLifecycleListener"
		SSLEngine="on" />
	<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
	<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
	<Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />

	<GlobalNamingResources>
		<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>

	<!-- //1.Service,它包含一个Engine元素,以及一个或多个Connector,这些Connector元素共享用同一个Engine元素 -->
	<!-- //2.name,指定service 的名字 -->
	<Service name="Catalina">
		<!-- //1.允许您为一个Service的所有Connector配置一个共享线程池 -->
		<!-- //2.name,共享线程池的名字。 -->
		<!-- //3.namePrefix,在JVM上,每个运行线程都可以有一个name 字符串。这一属性为线程池中每个线程的name字符串设置了一个前缀, -->
		<!-- //Tomcat将把线程号追加到这一前缀的后面、默认值:tomcat-exec-。 -->
		<!-- //4.maxIdleTime,在Tomcat关闭一个空闲线程之前,允许空闲线程持续的时间(以毫秒为单位)。只有当前活跃的线程数大于minSpareThread -->
		<!-- //的值,才会关闭空闲线程、默认值:60000(一分钟)。 -->
		<!-- //5.maxThreads,该线程池可以容纳的最大线程数、默认值:200。 -->
		<!-- //6.minSpareThreads,Tomcat应该始终打开的最小不活跃线程数、默认值:25。 -->
		<!-- //7.threadPriority、含义:整数值,表示线程池中所有线程的线程优先权。默认值:Thread.NORM_PRIORITY -->
		<!-- //8.一旦使用了线程池,则其它的线程属性,比如 maxThreads等将被忽略 -->
		<Executor name="tomcatThreadPool" namePrefix="catalina-exec-"
			maxThreads="1000" minSpareThreads="4" />

		<!--//1.Connector元素代表与客户程序实际交互的组件,它负责接收客户请求,以及向客户返回响应结果. -->
		<!--//2.Connector,表示客户端和service 之间的连接 -->
		<!--//3.URIEncoding, -->
		<!--//4.connectionTimeout,定义建立客户连接超时的时间.如果为-1,表示不限制建立客户连接的时间( 以毫秒为单位) -->
		<!--//5.port,指定服务器端要创建的端口号,并在这个断口监听来自客户端的请求 -->
		<!--//6.protocol,设定Http协议,默认值为HTTP/1.1,"org.apache.coyote.http11.Http11NioProtocol"性能会好点 -->
		<!--//(1).HTTP/1.1协议负责建立HTTP连接,web应用通过浏览器访问tomcat服务器用的就是这个连接器,默认监听的是8080端口; -->
		<!--//(2).AJP/1.3协议负责和其他HTTP服务器建立连接,监听的是8009端口,比如tomcat和apache或者iis集成时需要用到这个连接器。 -->
		<!--//(3).NIO则是使用单线程(单个CPU)或者只使用少量的多线程(多CPU)来接受Socket,而由线程池来处理堵塞在pipe或者队列里的请 -->
		<!--//求.这样的话,只要OS可以接受TCP的连接,web服务器就可以处理该请求。大大提高了web服务器的可伸缩性。 -->
		<!--//(4).BIO(默认)<NIO<APR -->
		<!--//7.redirectPort,指定转发端口.如果当前端口只支持non-SSL请求,在需要安全通信的场命,将把客户请求转发至SSL的redirectPort端口 -->
		<!--//8.acceptCount,指定当所有可以使用的处理请求的线程数都被使用时,可以放到处理队列中的请求数,超过这个数的请求将不予处理 -->
		<!--//9.minProcessors,服务器启动时创建的处理请求的线程数 -->
		<!--//10.maxProcessors,最大可以创建的处理请求的线程数 -->
		<!--//11.enableLookups,如果为true ,则可以通过调用request.getRemoteHost() 进行DNS 查询来得到远程客户端的实际主机名, -->
		<!--//若为false 则不进行DNS 查询,而是返回其ip 地址 -->
		<!--//12.address,如果服务器有二个以上ip地址,此属性可以设定端口监听的ip地址.默认情况下,端口会监听服务器上所有的ip地址 -->
		<!--//13.bufferSize,设定由端口创建的输入流的缓存大小.默认值为2048byte -->
		<!--//14.executor,共享线程池的名字 -->
		<Connector executor="tomcatThreadPool" port="8080" protocol="HTTP/1.1"
			acceptCount="1000" connectionTimeout="20000" redirectPort="8443" />

		<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />

		<!--//1.Engine,表示指定service 中的请求处理机,接收和处理来自Connector 的请求,处理在同一个Service中所有Connector元素接收到的客户请求 -->
		<!--//2.defaultHost,指定缺省的处理请求的主机名,它至少与其中的一个host 元素的name 属性值是一样的 -->
		<!--//3.name,是引擎的逻辑名称,在日志和错误消息中会用到,在同一台服务器上有多个Service时,name必须唯一。 -->
		<!--//4.Engine下可以配置多个虚拟主机Virtual Host,每个虚拟主机都有一个域名当Engine获得一个请求时,它把该请求匹配到某个Host上,然后把该请求交给该Host来处理 -->
		<!--//5.engine是一个完整的Servlet容器,其下面拥有多个虚拟主机,它的责任就是将用户请求分配给一个虚拟上机处理。 -->
		<Engine name="Catalina" defaultHost="localhost">

			<!--//1.Realm,表示存放用户名,密码及role 的数据库 -->
			<!--//2.className,指定Realm 使用的类名,此类必须实现org.apache.catalina.Realm 接口 -->
			<!--//3.tomcat项目管理页面相关,在tomcat-users.xml中设置角色和用户帐号和密码-->
			<Realm className="org.apache.catalina.realm.LockOutRealm">
				<Realm className="org.apache.catalina.realm.UserDatabaseRealm"
					resourceName="UserDatabase" />
			</Realm>

			<!--//1.一个Engine元素可以包含多个Host元素.每个Host的元素定义了一个虚拟主机.它包含了一个或多个Web应用. -->
			<!--//1.Host,表示一个虚拟主机 ,每个虚拟主机和某个网络域名Domain Name相匹配 -->
			<!--//2.name,指定主机名 -->
			<!--//3.appBase,应用程序基本目录,即存放应用程序的目录 -->
			<!--//4.autoDeploy, -->
			<!--//5.unpackWARs,如果为true ,则tomcat 会自动将WAR 文件解压,否则不解压,直接从WAR 文件中运行应用程序 -->
			<!--//6.alias,指定主机别名,可以指定多个别名 -->
			<Host name="localhost" appBase="webapps" unpackWARs="true"
				autoDeploy="true">

				<!--//1.Valve,功能与Logger 差不多,其prefix 和suffix 属性解释和Logger 中的一样 -->
				<!--//2.className,定Valve 使用的类名,如用org.apache.catalina.valves.AccessLogValve
					类可以记录应用程序的访问信息 -->
				<!--//3.directory,指定log 文件存放的位置 -->
				<!--//4.pattern,有两个值,common 方式记录远程主机名或ip 地址,用户名,日期,第一行请求的字符串,HTTP 响应代码,发送的字节数。 -->
				<!--//combined 方式比common 方式记录的值更多 -->
				<!--//5.prefix,指定log 文件的前缀 -->
				<!--//6.suffix,指定log 文件的后缀 -->
				<Valve className="org.apache.catalina.valves.AccessLogValve"
					directory="logs" prefix="localhost_access_log" suffix=".txt"
					pattern="%h %l %u %t &quot;%r&quot; %s %b" />

				<!--//1.每个Context元素代表了运行在虚拟主机上的单个Web应用 -->
				<!--//1.Context,表示一个web 应用程序,通常为WAR 文件 -->
				<!--//2.docBase,应用程序的路径或者是WAR 文件存放的路径 -->
				<!--//3.path,表示此web 应用程序的url 的前缀,这样请求的url 为http://localhost:8080/path/**** -->
				<!--//4.reloadable,这个属性非常重要,如果为true ,则tomcat 会自动检测应用程序的/WEB-INF/lib 和/WEB-INF/classes
					目录的变化,自动装载新的应用程序,我们可以在不重起tomcat 的情况下改变应用程序 -->
				<!--//5.workDir,是这个应用的工作目录,存放运行时生成的与这个应用相关的文件;
				<!--//6.debug 则是设定debug level,  0表示提供最少的信息,9表示提供最多的信息 -->
				<!--//7.privileged设置为true的时候,才允许Tomcat的Web应用使用容器内的Servlet -->
				<!--//7.有一个Context path当Host获得一个请求时,将把该请求匹配到某个Context上,然后把该请求交给该Context来处理 -->
				<!--//8.一个Context对应于一个Web Application,一个WebApplication由一个或者多个Servlet组成 -->
				<!--//9.Context在创建的时候将根据配置文件$CATALINA_HOME/conf/web.xml和$WEBAPP_HOME/WEB-INF/web.xml载入Servlet类 -->
				<!--//10.当Context获得请求时,将在自己的映射表(mappingtable)中寻找相匹配的Servlet类如果找到,则执行该类,获得请求的回应,并返回 -->
				<!--//11.并不推荐将context直接写在server.xml文件中,因为修改server.xml文件不会导致重新部署,必须重新启动tomcat才会生效, -->
				<!--//但是在server.xml文件中可以定义多个context元素,其他两种情况不允许。 -->
				<!--//12.可以不设置,有默认的 -->
				<!-- <Context path="/v1" docBase="CESmart" debug="0" privileged="true"/> -->
			</Host>
		</Engine>
	</Service>
</Server>


<?xml version='1.0' encoding='utf-8'?>
<tomcat-users xmlns="http://tomcat.apache.org/xml"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://tomcat.apache.org/xml tomcat-users.xsd"
              version="1.0">

<role rolename="tomcat"/>
  <role rolename="role1"/>
  <role rolename="manager"/>
  <role rolename="manager-gui"/>
  <role rolename="admin"/>
  <role rolename="admin-gui"/>
  <role rolename="manager-script"/>
  <role rolename="manager-jmx"/>
  <role rolename="manager-status"/>
  <user username="tomcat" password="tomcat" roles="tomcat"/>
  <user username="both" password="tomcat" roles="tomcat,role1"/>
  <user username="role1" password="tomcat" roles="role1"/>
  <user username="admin" password="admin" roles="tomcat,role1"/>
  <user username="tomcat" password="" roles="manager-gui"/>
  <user username="Tomcat" password="Tomcat" roles="admin-gui,admin,manager-gui,manager,manager-script,manager-jmx,manager-status"/>
</tomcat-users>



参考原文(Tomcat工作原理详解): http://blog.csdn.net/res_cue/article/details/21756357
参考原文(Tomcat学习之Connector(各个模块的介绍)): http://blog.csdn.net/aesop_wubo/article/details/7617416
参考原文(一个Tomcat配置多个Service多个项目): http://blog.csdn.net/zhanjianshinian/article/details/44591183
参考原文(tomcat英文文档): http://www.cnblogs.com/xing901022/p/4552843.html
参考原文(Tomcat下使用war包发布项目): http://blog.csdn.net/wy818/article/details/7240294
参考原文(从零认识tomcat): http://grass51.blog.51cto.com/4356355/1123400
参考原文(TOMCAT的安全域(Realm)): http://blog.163.com/liangge_sky/blog/static/210500188201102031733245/
参考原文((Executor Thread pool)的配置): http://blog.csdn.net/java2000_net/article/details/3280020
参考原文(Tomcat工作原理详解): http://blog.sina.com.cn/s/blog_7cc931cb01014r6n.html
参考原文(spring和springMVC父子容器的原理): http://blog.csdn.net/caomiao2006/article/details/51290494

猜你喜欢

转载自huangyongxing310.iteye.com/blog/2334997