Servlet容器、Tomcat和Servlet自我理解(2)
tomcat容器模型如下:参考https://www.cnblogs.com/gy19920604/p/5377766.html
<Service>
<Connector />
<Connector />
<Engine>
<Host>
<Context /><!-- 现在常常使用自动部署,不推荐配置Context元素,Context小节有详细说明 -->
</Host>
</Engine>
</Service>
</Server>
需要注意的是,在自动部署场景下(配置文件位于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。
创建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文件为类,并初始化这个类。
- <?xml version="1.0" encoding="UTF-8"?>
- <web-app version="2.5"
- xmlns="http://java.sun.com/xml/ns/javaee" --命名空间,类似包名,因为xml的标签可自定义,需要命名空间来区分
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" --xml遵循的标签规范
- xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
- <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)的地址
- >
- </web-app>
- <?xml version="1.0" encoding="UTF-8"?>
- <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
- "http://java.sun.com/dtd/web-app_2_3.dtd">
- <web-app>
- <display-name>Sample Application</display-name>
- <description>This is a sample application</description>
- <!-- 在此设定的参数,可以在servlet中用 getServletContext().getInitParameter("my_param") 来取得 -->
- <context-param> <!-- 用来设定web站台的环境参数 -->
- <param-name>my_param</param-name>
- <param-value>hello</param-value>
- </context-param>
- <filter>
- <!–过滤器名,可以随便取,当web应用中有多个过滤器时不允许重名.–>
- <filter-name>SampleFilter</filter-name>
- <!–具体的过滤器的类的完整的包名+类名。注意:不能写错了。否则容器不能正确的实例化过滤器–>
- <filter-class>mypack.SampleFilter</filter-class>
- <init-param>
- <!– 参数名 –>
- <param-name>initParam1</param-name>
- <!– 参数值 –>
- <param-value>2</param-value>
- </init-param>
- </filter>
- <!– Define the SampleFilter Mapping –>
- <filter-mapping>
- <!–过滤器名,注意要和上面的<filter-name>里的名字一样。–>
- <filter-name>SampleFilter</filter-name>
- <!– 指定过滤器负责过滤的URL。这里指定了*.jsp表示在访问任何一个jsp页面时都会先使用mypack.SampleFilter过滤器进行过滤。如果写成login.jsp.则只有在访问login.jsp时才会调用该过滤器进行过滤。–>
- <url-pattern>*.jsp</url-pattern>
- </filter-mapping>
- <servlet>
- <!– Servlet名字,可以随便取,有多个Servlet时不允许重名–>
- <servlet-name>SampleServlet</servlet-name>
- <!–指定实现这个Servlet的类。完整的包名+类名–>
- <servlet-class>mypack.SampleServlet</servlet-class>
- <!–定义Servlet的初始化参数(包括参数名和参数值)一个<servlet>元素里可以有多个<init-param>元素。在Servlet类中通过ServletConfig类的来访问这些参数。
- –>
- <init-param>
- <!– 参数名 –>
- <param-name>initParam1</param-name>
- <!– 参数值 –>
- <param-value>2</param-value>
- </init-param>
- <!–指定当前Web应用启动时装载Servlet的次序。当这个数>=0时,容器会按数值从小到大依次加载。如果数值<0或没有指定,容器将载Web客户首次访问这个Servlet时加载。–>
- <load-on-startup>1</load-on-startup>
- </servlet>
- <!– Define the SampleServlet Mapping –>
- <servlet-mapping>
- <!–必须和<servlet>里的<servlet-name>内容一样–>
- <servlet-name>SampleServlet</servlet-name>
- <!–指定访问这个Servlet的URL。这里给出的是对于整个Web应用的相对URL路径。–>
- <url-pattern>/sample</url-pattern>
- </servlet-mapping>
- <session-config>
- <!–设 定HttpSession的生命周期。这里以分钟计算。下面的设定指明Session在最长不活动时间为10分钟。过了这个时间,Servlet容器将它 作为无效处理。注意这里和程序里指定的计数单位不同,程序里是以秒为单位。<session-config>只有<session- timeout>这个元素–>
- <session-timeout>10</session-timeout>
- </session-config>
- <!— 配置会话侦听器,class表示一个HttpSessionListener或 HttpSessionActivationListener 或 HttpSessionAttributeListener或 HttpSessionBindingListener的实现类。该节点允许多个 –>
- <listener>
- <listener-class>com.cn.SessionListenerImpl</listener-class>
- </listener>
- <!– 在 用户访问Web应用时,如果仅给出Web应用的根访问URL,没有指定具体的文件名,容器会调用<weblcome-file- list> 元素里指定的文件清单。<welcome-file-list>里允许有多个<welcome-file>元 素,每个元素代表一个文件。容器会先找第一文文件件是否存在,如果存在这把这个文件返回个客户,不再进行其他文件的查找。如果不存在则找第二个文件,依次 类推。如果所有文件都不存在,则跑出404错误–>
- <welcome-file-list>
- <welcome-file>login.jsp</welcome-file>
- <welcome-file>index.htm</welcome-file>
- </welcome-file-list>
- <!– 设置Web应用引用的自定义标签库。下面的代码定义了一个/mytaglib标签库,它对应的TLD文件为/WEB-INF/mytaglib.tld –>
- <taglib>
- <taglib-uri>/mytaglib</taglib-uri>
- <taglib-location>/WEB-INF/mytaglib.tld</taglib-location>
- </taglib>
- <!– 如果Web应用访问了由Servlet容器管理的某个JNDI Resource必须在这里声明对JNDI Resource的引用 –>
- <resource-ref>
- <!– 对应用资源的说明 –>
- <description>DB Connection</description>
- <!– 指定所引用资源的JNDI名字 –>
- <res-ref-name>jdbc/sampleDb</res-ref-name>
- <!– 指定所引用资源的类名字 –>
- <res-type>javax.sql.DataSource</res-type>
- <!– 指定管理所引用资源的Manager, 它有两个可选值:Container和Application.Container表示由容器来创建和管理Resource,Application表示由Web应用来管理和创建Resource –>
- <res-auth>Container</res-auth>
- </resource-ref>
- <security-constraint>
- <web-resource-collection>
- <!– 这个名字是必须的,由工具使用,别的地方不使用 –>
- <web-resource-name>my application</web-resource-name>
- <!– 指定要受约束的资源,至少有一个。可以有多个. –>
- <uri-pattern>/*</uri-pattern>
- <!– 描 述了度可与URL模式指定的资源哪些方法是受约束的,如果没有<http-method>元素,表示任何角色的人都无法访问任何http的方 法 。这里放置了GET方法,表示只有GET方法是受约束的。其他任何角色的人可以访问POST和其他的方法。但不能访问GET方法。–>
- <http-method>GET</http-method>
- </web-resource-collection>
- <!– 如果没有<auth-constraint>表示所有角色都能访问GET方法,如果是<auth-constraint/>表示任何角色都不能访问GET方法 –>
- <auth-constraint>
- <!– 可选的。表示哪些角色能够在指定的资源上调用受约束的方法。这里表示只有拥有Admin和Member角色的人能够访问GET方法
- <security-role>>里的<role-name>值一样 –>
- <role-name>Admin</role-name>
- <role-name>Member</role-name>
- </auth-constraint>
- </security-constraint>
- <!– 将指定的角色映射到web.xml里 –>
- <security-role>
- <description>The role that is required to log into the my Application
- </description>
- <!– 以下的角色和tomcat-users.xml里的<tomcat-users>里的<role rolename=""/>里的rolename属性值对应 –>
- <role-name>Guest</role-name>
- <role-name>Admin</role-name>
- <role-name>Member</role-name>
- </security-role>
- <!– 如果要想进行认证,必须有<login-config>–>
- <login-config>
- <!– 认证方式。有4种:BASIC:基本。 DIGEST:摘要。CLIENT-CERT:客户证书(能提供最高强度的认证)。FORM:表单 –>
- <auth-method>FORM</auth-method>
- <realm-name>
- Tomcat Servet Configuraton Form-Based Authentication Area
- </realm-name>
- <form-login-config>
- <form-login-page>/login.jsp</form-login-page>
- <form-error-page>/error.jsp</form-error-page>
- </form-login-config>
- </login-config>
- <error-page> <!-- 用来处理错误代码或异常的页面,有三个子元素: -->
- <error-code>404</error-code> <!-- 指定错误代码 -->
- <exception-type>java.lang.Exception</exception-type> <!-- 指定一个JAVA异常类型 -->
- <location>/error404.jsp</location> <!-- 指定在web站台内的相关资源路径 -->
- </error-page>
- <mime-mapping> <!-- 定义某一个扩展名和某一个MIME Type做对映,包含两个节点 -->
- <extension>doc</extension> <!-- 扩展名的名称 -->
- <mime-type>application/vnd.ms-word</mime-type> <!-- MIME格式 -->
- </mime-mapping>
- <mime-mapping>
- <extension>xls</extension>
- <mime-type>application/vnd.ms-excel</mime-type>
- </mime-mapping>
- </web-app>