Servlet容器、Tomcat和Servlet自我理解(2)

tomcat容器模型如下:参考https://www.cnblogs.com/gy19920604/p/5377766.html

说这个模型前,先说说server.xml,这个XML是tomcat的配置文件,这个配置文件的结构如下:参考https://www.cnblogs.com/kismetv/p/7228274.html#title3-1
<Server>
    <Service>
        <Connector />
        <Connector />
        <Engine>
            <Host>
                <Context /><!-- 现在常常使用自动部署,不推荐配置Context元素,Context小节有详细说明 -->
            </Host>
        </Engine>
    </Service>
</Server>
Server是指Tomcat整个容器。Server的主要任务,就是提供一个接口让客户端能够访问到这个Service集合,同时维护它所包含的所有的Service的声明周期,包括如何初始化、如何结束服务、如何找到客户端要访问的Service
Service顾名思义是服务为客户提供服务,由于一个Server下可以包含多个service,即可以为客户提供多个不同的服务。那多个service即可监听不同的端口,一个service也能监听多个不同的端口。不同的service可以部署不同的web应用进而监听不同的端口。Service下包含了多个connector和一个Engine,并且Engine下包含了多个host。service所说的监听也是靠connector进行监听。
Connector:连接器组件接收客户端连接,connector配置了具体监听的端口和这个端口上对应的协议等等一些参数。connector监听也是监听tcp连接,当客户端发送一个tcp连接过来时,connector会解析tcp请求,并调用wrapper包装功能,将tcp请求包装成http请求,传给engine处理。
Engine:是引擎组件,也称为处理引擎组件,因为Connector会将request请求交给Egine(经过wrapper处理),Engine处理完成后,并且把response回应数据返回给Connector。但是具体处理也并不是engine来处理,而是由host下的组件来处理,但由于一个engine下可以配置多个host,为了防止出现意外,Engine配置了一个默认的host。
Host:是虚拟主机组件, Host是Engine的子容器。Engine下可以包含多个host组件,每个host虚拟主机对应了一个域名(DNS域名,例如:www.test.com)。由于Engine配置了一个默认的host,所以,多个host当中必须有一个与Engine配置的名称一致。因为当Tomcat根据域名去匹配各个host时,若发现都匹配不上时,则直接交给engine下默认的host处理。host配置中配置了web应用的根目录,以及是否自动部署(会将war包自动解压)等等信息。
Context:是上下文,这个上下文代表了具体一个web应用。每个Web应用基于WAR文件,或WAR文件解压后对应的目录(这里称为应用目录)

需要注意的是,在自动部署场景下(配置文件位于xmlBase中),不能指定path属性,path属性由配置文件的文件名、WAR文件的文件名或应用目录的名称自动推导出来。如扫描Web应用时,发现了xmlBase目录下的app1.xml,或appBase目录下的app1.WAR或app1应用目录,则该Web应用的path属性是”app1”。如果名称不是app1而是ROOT,则该Web应用是虚拟主机默认的Web应用,此时path属性推导为””。

reloadable属性指示tomcat是否在运行时监控在WEB-INF/classes和WEB-INF/lib目录下class文件的改动。如果值为true,那么当class文件改动时,会触发Web应用的重新加载。在开发环境下,reloadable设置为true便于调试;但是在生产环境中设置为true会给服务器带来性能压力,因此reloadable参数的默认值为false。

讲完每个组件的功能了,现在举例说明一下:当一个客户输入了http://www.test.com/app1/index.html(http代表协议, www.test.com代表域名以及对应的ip和端口,app1代表web应用),浏览器先去DNS查询到域名 www.test.com对应的ip和端口,然后浏览器根据tcp协议,连接ip和端口,同时把整个路径以及协议等等信息发送给web服务器,web服务器的connector收到这个连接后(当然server根据ip和端口也就知道是哪个service在服务了),因为是http协议,所以,调用wrapper组件,将tcp请求的信息包装成http的请求,发给engine来处理,engin收到后,通过域名 www.test.com来匹配哪个虚拟主机来处理,找到host后紧接着,根据名称app1找到web context(web应用),web应用就开始处理客户的请求了。当然这时还有个疑问那就是web应用是怎么处理的,那接着往下看。
web应用的处理就会涉及到一个配置文件即web.xml:参考:https://www.cnblogs.com/gy19920604/p/5377766.html
注:在Servlet2.5规范之前,Java Web引用绝大部分组件通过web.xml文件来配置管理,从Servlet3.0开始,也可以通过注解来配置管理Web组件,也就是从3.0以后,web.xml这个配置文件不是必须有的了。
WEB应用的初始化工作是在ContextConfig的configureStart方法中实现的,应用的初始化工作主要是解析web.xml文件,这个文件是一个WEB应用的入口。Tomcat首先会找globalWebXml,这个文件的搜索路径是engine的工作目录下的org/apache/catalina/startup/NO-DEFAULT_XML或conf/web.xml。接着会找hostWebXml,这个文件可能会在System.getProperty("catalina.base")/conf/${EngineName}/${HostName}/web.xml.default中。接着寻找应用的配置文件examples/WEB-INF/web.xml,web.xml文件中的各个配置项将会被解析成相应的属性保存在WebXml对象中。接下来会讲WebXml对象中的属性设置到context容器中,这里包括创建servlet对象,filter,listerner等,这些在WebXml的configureContext方法中。

创建Servlet实例 

前面完成了servlet的解析工作,并且被包装成了StandardWrapper添加到Context容器中,但是它仍然不能为我们工作,它还没有被实例化。

1.创建

如果Servlet的load-on-startup配置项大于0,那么在Context容器启动时就会被实例化。

前面提到的在解析配置文件时会读取默认的globalWebXml,在conf下的web.xml文件中定义了一些默认的配置项,其中定义了两个Servlet,分别是org.apache.catalina.servlets.DefaultServlet和org.apache.jsper.servlet.JspServelt,它们的load-on-startup分别是1和3,也就是当tomcat启动时这两个servlet就会被启动。

创建Servlet实例的方式是从Wrapper.loadServlet开始的,loadServlet方法要完成的就是获取servletClass,然后把它交给InstanceManager去创建一个基于servletClass.class的对象。如果这个Servlet配置了jsp-file,那么这个servletClass就是在conf/web.xml中定义的org.apache.jasper.servlet.JspServlet。

2.初始化

初始化Servlet在StandardWrapper的initServlet方法中,这个方法很简单,就是调用Servlet的init()方法,同时把包装了StandardWrapper对象的StandardWrapperFacade作为ServletConfig传给Servlet。

如果该Servlet关联的是一个JSP文件,那么前面初始化的就是JspServlet,接下来会模拟一次简单请求,请求调用这个JSP文件,以便编译这个JSP文件为类,并初始化这个类。

这样Servlet对象的初始化就完成了。
下面具体介绍一下,web.xml内容和格式。

Schema文件:每个 xml 文件都有 定义它书写规则的Schema文件 ,也就是说 javaEE 的定义 web.xml 所对应的 xml Schema 文件中定义了多少种标签元素, web.xml 中就可以出现它所定义的标签元素,也就具备哪些特定的功能。 web.xml 的模式文件是由 Sun  公司定义的,每个 web.xml 文件的 根元素为<web-app> 中,必须标明这个 web.xml 使用的是哪个模式文件。
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <web-app version="2.5"   
  3. xmlns="http://java.sun.com/xml/ns/javaee"  --命名空间,类似包名,因为xml的标签可自定义,需要命名空间来区分  
  4. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" --xml遵循的标签规范  
  5. xsi:schemaLocation="http://java.sun.com/xml/ns/javaee   
  6. <a href="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd\" "="">http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" --用来定义xmlschema的地址,也就是xml书写时需要遵循的语法,两部分组成,前面部分就是命名空间的名字,后面是xsd(xmlschema)的地址  
  7. >  
  8. </web-app> 
web.xml的模式文件中定义的标签并不是定死的,模式文件也是可以改变的,一般来说,随着web.mxl模式文件的版本升级,里面定义的功能会越来越复杂,标签元素的种类肯定也会越来越多,但有些不是很常用的,我们只需记住一些常用的并知道怎么配置就可以了。

web.xml包含的对应的 web-app_2_5.xsd包含的属性:
web-app是根目录,下面是加载的顺序servletcontext->context-param->listener->filter->servlet。

  1. <?xml version="1.0" encoding="UTF-8"?>   
  2. <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"   
  3. "http://java.sun.com/dtd/web-app_2_3.dtd">   
  4. <web-app>   
  5. <display-name>Sample Application</display-name>   
  6. <description>This is a sample application</description>  
  7. <!-- 在此设定的参数,可以在servlet中用 getServletContext().getInitParameter("my_param") 来取得 -->  
  8. <context-param>   <!-- 用来设定web站台的环境参数 -->  
  9.     <param-name>my_param</param-name>  
  10.     <param-value>hello</param-value>  
  11. </context-param>  
  12. <filter>   
  13. <!–过滤器名,可以随便取,当web应用中有多个过滤器时不允许重名.–>   
  14. <filter-name>SampleFilter</filter-name>   
  15. <!–具体的过滤器的类的完整的包名+类名。注意:不能写错了。否则容器不能正确的实例化过滤器–>   
  16. <filter-class>mypack.SampleFilter</filter-class>   
  17. <init-param>   
  18. <!– 参数名 –>   
  19. <param-name>initParam1</param-name>   
  20. <!– 参数值 –>   
  21. <param-value>2</param-value>   
  22. </init-param>   
  23. </filter>   
  24. <!– Define the SampleFilter Mapping –>   
  25. <filter-mapping>   
  26. <!–过滤器名,注意要和上面的<filter-name>里的名字一样。–>   
  27. <filter-name>SampleFilter</filter-name>   
  28. <!– 指定过滤器负责过滤的URL。这里指定了*.jsp表示在访问任何一个jsp页面时都会先使用mypack.SampleFilter过滤器进行过滤。如果写成login.jsp.则只有在访问login.jsp时才会调用该过滤器进行过滤。–>   
  29. <url-pattern>*.jsp</url-pattern>   
  30. </filter-mapping>   
  31. <servlet>   
  32. <!– Servlet名字,可以随便取,有多个Servlet时不允许重名–>   
  33. <servlet-name>SampleServlet</servlet-name>   
  34. <!–指定实现这个Servlet的类。完整的包名+类名–>   
  35. <servlet-class>mypack.SampleServlet</servlet-class>   
  36. <!–定义Servlet的初始化参数(包括参数名和参数值)一个<servlet>元素里可以有多个<init-param>元素。在Servlet类中通过ServletConfig类的来访问这些参数。   
  37. >   
  38. <init-param>   
  39. <!– 参数名 –>   
  40. <param-name>initParam1</param-name>   
  41. <!– 参数值 –>   
  42. <param-value>2</param-value>   
  43. </init-param>   
  44. <!–指定当前Web应用启动时装载Servlet的次序。当这个数>=0时,容器会按数值从小到大依次加载。如果数值<0或没有指定,容器将载Web客户首次访问这个Servlet时加载。–>   
  45. <load-on-startup>1</load-on-startup>   
  46. </servlet>   
  47. <!– Define the SampleServlet Mapping –>   
  48. <servlet-mapping>   
  49. <!–必须和<servlet>里的<servlet-name>内容一样–>   
  50. <servlet-name>SampleServlet</servlet-name>   
  51. <!–指定访问这个Servlet的URL。这里给出的是对于整个Web应用的相对URL路径。–>   
  52. <url-pattern>/sample</url-pattern>   
  53. </servlet-mapping>   
  54. <session-config>   
  55. <!–设 定HttpSession的生命周期。这里以分钟计算。下面的设定指明Session在最长不活动时间为10分钟。过了这个时间,Servlet容器将它 作为无效处理。注意这里和程序里指定的计数单位不同,程序里是以秒为单位。<session-config>只有<session- timeout>这个元素–>   
  56. <session-timeout>10</session-timeout>   
  57. </session-config>   
  58. <!— 配置会话侦听器,class表示一个HttpSessionListener或 HttpSessionActivationListener 或 HttpSessionAttributeListener或 HttpSessionBindingListener的实现类。该节点允许多个 –>   
  59. <listener>   
  60. <listener-class>com.cn.SessionListenerImpl</listener-class>   
  61. </listener>   
  62. <!– 在 用户访问Web应用时,如果仅给出Web应用的根访问URL,没有指定具体的文件名,容器会调用<weblcome-file- list> 元素里指定的文件清单。<welcome-file-list>里允许有多个<welcome-file>元 素,每个元素代表一个文件。容器会先找第一文文件件是否存在,如果存在这把这个文件返回个客户,不再进行其他文件的查找。如果不存在则找第二个文件,依次 类推。如果所有文件都不存在,则跑出404错误–>   
  63. <welcome-file-list>   
  64. <welcome-file>login.jsp</welcome-file>   
  65. <welcome-file>index.htm</welcome-file>   
  66. </welcome-file-list>   
  67. <!– 设置Web应用引用的自定义标签库。下面的代码定义了一个/mytaglib标签库,它对应的TLD文件为/WEB-INF/mytaglib.tld –>   
  68. <taglib>   
  69. <taglib-uri>/mytaglib</taglib-uri>   
  70. <taglib-location>/WEB-INF/mytaglib.tld</taglib-location>   
  71. </taglib>   
  72. <!– 如果Web应用访问了由Servlet容器管理的某个JNDI Resource必须在这里声明对JNDI Resource的引用 –>   
  73. <resource-ref>   
  74. <!– 对应用资源的说明 –>   
  75. <description>DB Connection</description>   
  76. <!– 指定所引用资源的JNDI名字 –>   
  77. <res-ref-name>jdbc/sampleDb</res-ref-name>   
  78. <!– 指定所引用资源的类名字 –>   
  79. <res-type>javax.sql.DataSource</res-type>   
  80. <!– 指定管理所引用资源的Manager, 它有两个可选值:Container和Application.Container表示由容器来创建和管理Resource,Application表示由Web应用来管理和创建Resource –>   
  81. <res-auth>Container</res-auth>   
  82. </resource-ref>   
  83. <security-constraint>   
  84. <web-resource-collection>   
  85. <!– 这个名字是必须的,由工具使用,别的地方不使用 –>   
  86. <web-resource-name>my application</web-resource-name>   
  87. <!– 指定要受约束的资源,至少有一个。可以有多个. –>   
  88. <uri-pattern>/*</uri-pattern>   
  89. <!– 描 述了度可与URL模式指定的资源哪些方法是受约束的,如果没有<http-method>元素,表示任何角色的人都无法访问任何http的方 法  。这里放置了GET方法,表示只有GET方法是受约束的。其他任何角色的人可以访问POST和其他的方法。但不能访问GET方法。–>   
  90. <http-method>GET</http-method>   
  91. </web-resource-collection>   
  92. <!– 如果没有<auth-constraint>表示所有角色都能访问GET方法,如果是<auth-constraint/>表示任何角色都不能访问GET方法 –>   
  93. <auth-constraint>   
  94. <!– 可选的。表示哪些角色能够在指定的资源上调用受约束的方法。这里表示只有拥有Admin和Member角色的人能够访问GET方法   
  95. <security-role>>里的<role-name>值一样 –>   
  96. <role-name>Admin</role-name>   
  97. <role-name>Member</role-name>   
  98. </auth-constraint>   
  99. </security-constraint>   
  100. <!– 将指定的角色映射到web.xml里 –>   
  101. <security-role>   
  102. <description>The role that is required to log into the my Application   
  103. </description>   
  104. <!– 以下的角色和tomcat-users.xml里的<tomcat-users>里的<role rolename=""/>里的rolename属性值对应 –>   
  105. <role-name>Guest</role-name>   
  106. <role-name>Admin</role-name>   
  107. <role-name>Member</role-name>   
  108. </security-role>   
  109. <!– 如果要想进行认证,必须有<login-config>>   
  110. <login-config>   
  111. <!– 认证方式。有4种:BASIC:基本。 DIGEST:摘要。CLIENT-CERT:客户证书(能提供最高强度的认证)。FORM:表单 –>   
  112. <auth-method>FORM</auth-method>   
  113. <realm-name>   
  114. Tomcat Servet Configuraton Form-Based Authentication Area   
  115. </realm-name>   
  116. <form-login-config>   
  117. <form-login-page>/login.jsp</form-login-page>   
  118. <form-error-page>/error.jsp</form-error-page>   
  119. </form-login-config>   
  120. </login-config>  
  121. <error-page> <!-- 用来处理错误代码或异常的页面,有三个子元素: -->  
  122.     <error-code>404</error-code> <!-- 指定错误代码 -->  
  123.     <exception-type>java.lang.Exception</exception-type> <!-- 指定一个JAVA异常类型 -->  
  124.     <location>/error404.jsp</location> <!-- 指定在web站台内的相关资源路径 -->  
  125. </error-page>  
  126. <mime-mapping>        <!-- 定义某一个扩展名和某一个MIME Type做对映,包含两个节点 -->  
  127.     <extension>doc</extension>  <!-- 扩展名的名称 -->  
  128.     <mime-type>application/vnd.ms-word</mime-type>  <!-- MIME格式 -->  
  129. </mime-mapping>   
  130. <mime-mapping>  
  131.     <extension>xls</extension>  
  132.     <mime-type>application/vnd.ms-excel</mime-type>  
  133. </mime-mapping>  
  134. </web-app>  
好了,介绍完web.xml配置。
接上面的例子: http://www.test.com/app1/index.html,已经找到了web应用了,web应用怎么处理。web应用启动时已经生成了servlet对象和filter以及listener,servlet拿springmvc dispatchservlet来说,由于每个servlet都是按照servlet规范来开发,所以,context容器负责调用service接口,来执行 dispatchservlet主要服务。
那filter又是怎么回事,因为刚设计servlet时,本身servlet就是处理具体请求的,但是有些数据需要预处理一下交给servlet会更好,所以出现了filter过滤器,经过过滤器也就是相当于预处理了一次,所以,为啥filter会比servlet加载顺序高,同时加上filter也可以称为加强版的servlet。


  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值