首页 > 学院 > 开发设计 > 正文

Tomcat(二) Tomcat实现:Servlet与web.xml介绍 以及 源码分析Tomcat实现细节

2019-11-07 23:46:46
字体:
来源:转载
供稿:网友

原创链接:点击打开链接

Tomcat(二) Tomcat实现:

Servlet与web.xml介绍 以及 源码分析Tomcat实现细节

       在《Tomcat(一) Tomcat是什么:Tomcat与java技术 Tomcat与Web应用 以及Tomcat基本框架及相关配置》对Tomcat有了一个大体的认识,下面将深入了解Tomcat技术的实现:

      1、先来了解JavaEE Servlet技术的一些对象组件

      2、再来了Web应用程序部署文件web.xml中对Servlet组件的定义;

      3、最后再从Tomcat源码分析一些实现细节,重点关注:Tomcat的启动/初始化、并发线程模式、接收请求与处理、以及Servlet容器的实现。

1、JavaEE Servlet技术

       Tomcat是一个Servlet容器,实现了Servlet规范,可以运行我们自己编写的Servlet应用程序处理动态请求,并返回响应,下面介绍Listener、Filter、Servlet、Request、Respones这几个比较常见的对象元素。

1、Listener

      Listener(监听器)用来监听一些对象的事件,当事件发生时可以进入到定义监听器中进行处理,主要有ServletContextListener、HttpsessionListener 和 ServletRequestListener。

       我们程序中可以实现这些JavaEE Servlet API中提供的监听器接口,然后通过web.xml定义部署发生作用,如ServletContextListenerServlet(Servlet 上下文事件监听器)接口可以监听到部署web应用Servlet的状态改变通知(如创建、关闭),如sPRing框架中常见的一些ServletContextListenerServlet实现在web.xml定义如下:

       它们都实现javax.servlet.ServletContextListener接口,如org.springframework.web.context.ContextLoaderListener用来在部署相关Web应用时初始化其上下文环境,在停止退出Web应用时清理其资源,如下:

       Servlet容器需要在开始执行进入应用的第一个请求之前完成Web应用中的监听器类的实例化,而且保持每一个监听器的引用直到为Web应用最后一个请求提供服务。

       更多Listener信息请参考:《Servlet3.1规范(最终版)》第10章

2、Filter

      Filter(过滤器)可以改变HTTP请求的内容、响应、及header信息,过滤器通常不产生响应或像 servlet 那样对请求作出响应,而是修改或调整到资源的请求,修改或调整来自资源的响应。

       Filter在部署描述符中通过<filter>元素声明,一个过滤器或一组过滤器可以通过在部署描述符中定义<filter-mapping>来为调用配置。

       容器部署Web应用时,必须确保它为过滤器列表中的每一个都实例化了一个适当类的过滤器, 并调用其Filter.init()方法;当容器接收到传入的请求时,它将获取列表中所有符合该请求的过虑器组成过虑器链(FilterChain),然后通过FilterChain嵌套调用各过虑器的Filter.doFilter()方法(一个过滤器可以使得滤器链调用下一个过滤器),传入ServletRequest 和ServletResponse进行处理。

      当滤器链调用完各Filter.doFilter()方法后,会调用相关Servlet.service()方法,从而进行Servlet的处理。注意,Filter.doFilter()可以阻止过滤器链接下来的调用,返回时过滤器负责填充Reponse对象。

      过滤器实例移除之前,容器必须先调用过滤器的Filter.destroy()方法。

      如Struts2框架通过在web.xml中定义其实现了Filter接口的StrutsPrepareAndExecuteFilter来作为处理请求的入口,如下:

       StrutsPrepareAndExecuteFilter.init()在部署Web应用时被容器调用,其实现了Struts2配置文件的读取及初始化,而在doFilter()方法中找到符合的Action处理程序后,就不再调用chain.doFilter(),而经Action处理后开始返回,如下:

       更多Filter信息请参考:《Servlet3.1规范(最终版)》第6章

3、Servlet

      Servlet 这里指的是实现了javax.servlet.Servlet接口的处理程序,一般开发中都是继承HttpServlet,其继承自实现了Servlet接口的GenericServlet类。

       容器在部署Web应用程序时,或Servlet第一次请求处理时实例化调用Servlet.init()方法;而Servlet.service()方法从上面Filter介绍中可以知道是在各Filter.doFilter()嵌套调用中被调用的,而HttpServlet..service()中会根据请求类型分为doGet(),doPost()等方法,继承HttpServlet只需重写这样些需要的方法即可,如Tomcat的/conf/web.xml定义了默认的DefaultServlet用来处理静态内容请求(如html/js/各种图片),如下:

       而当Servlet容器确定servlet应该从服务中移除时(内存不足等),将调用Servlet.destroy()方法以允许Servlet释放它使用的任何资源和保存任何持久化的状态。

       容器中的Servlet实例通常都是单例的(可通过实现SingleThreadModel 接口实现每个请求对应一个Servlet),所以需要注意在多线程下的线程安全问题。

       更多Servlet信息请参考:《Servlet3.1规范(最终版)》第2章

4、Request与Response

       Request和Response都可以在上面这些处理接口程序中通过参数接收到,Request对象封装了客户端请求的所有信息,Response对象封装了从服务器返回到客户端的所有信息。

      每个Request/Response对象只在Servlet.service()方法、或Filter.doFilter()方法的作用域内有效;发生异步处理的情况下,对象一直有效,直到调用AsyncContext.complete()方法。

      除了异步请求时的AsyncContext.startAsync()和AsyncContext.complete()方法,Request/Response对象的实现都不保证线程安全,多线程访问时需要同步处理。

更多信息请参考:《Servlet3.1规范(最终版)》

2、web.xml文件说明

       上篇文件章介绍过web.xml是Web应用程序部署描述符文件web.xml,描述组成应用程序的servlet和其他组件、以及相关初始化参数等信息。

       web.xml中组件加载顺序为:

       context-param -> listener -> filter -> servlet(同类则按编写顺序执行)。

      web.xml常用组件解析:

[plain] view plain copyprint?在CODE上查看代码片派生到我的代码片<span style="color:#000000;"><web-app>           <display-name></display-name> <!--WEB应用的名字 -->           <description></description> <!--WEB应用的描述-->           <context-param></context-param> <!--context-param元素声明应用范围内的初始化参数-->           <!--例如指定spring加载多个spring配置文件-->           <context-param>                  <param-name>contextConfigLocation</param-name>                  <param-value>                         /WEB-INF/applicationContext.xml, /WEB-INF/action-servlet.xml                  </param-value>           </context-param>                <<strong>filter></filter></strong> <!--过滤器将一个名字与一个实现javax.servlet.Filter接口的类相关联-->           <strong><filter-mapping></filter-mapping> <</strong>!--一旦命名了一个过滤器,就要利用filter-mapping元素把它与一个或多个servlet或jsp页面相关联-->         <strong><listener></listener></strong> <!--事件监听程序在建立、修改和删除会话或servlet环境时得到通知。Listener元素指出事件监听程序类,如Log4j这个广泛使用的监听器-->           <strong><servlet></servlet></strong> <!--在向servlet或JSP页面制定初始化参数或定制URL时,必须首先命名servlet或JSP页面。Servlet元素就是用来完成此项任务的。-->           <strong><servlet-mapping></servlet-mapping> </strong><!--服务器一般为servlet提供一个缺省的URL:http://host/webAppPrefix/servlet/ServletName,但是,常常会更改这个URL,以便servlet可以访问初始化参数或更容易地处理相对URL。在更改缺省URL时,使用servlet-mapping元素-->           <session-config></session-config> <!--如果某个会话在一定时间内未被访问,服务器可以抛弃它以节省内存,可通过使用HttpSession的setMaxInactiveInterval方法明确设置单个会话对象的超时值,或者可利用session-config元素制定缺省超时值-->           <mime-mapping></mime-mapping> <!--如果Web应用具有想到特殊的文件,希望能保证给他们分配特定的MIME类型,则mime-mapping元素提供这种保证-->           <welcome-file-list></welcome-file-list> <!--指示服务器在收到引用一个目录名而不是文件名的URL时,使用哪个文件(其实就是欢迎界面或者说入口界面一般为index.*) -->           <error-page></error-page> <!--在返回特定HTTP状态代码时,或者特定类型的异常被抛出时,能够制定将要显示的页面-->           <taglib></taglib> <!--对标记库描述符文件(Tag Libraryu Descriptor file)指定别名。此功能使你能够更改TLD文件的位置, 而不用编辑使用这些文件的JSP页面-->           <resource-env-ref></resource-env-ref> <!--声明与资源相关的一个管理对象-->           <resource-ref></resource-ref> <!--声明一个资源工厂使用的外部资源-->              <security-constraint></security-constraint> <!--制定应该保护的URL。它与login-config元素联合使用-->           <login-config></login-config> <!--指定服务器应该怎样给试图访问受保护页面的用户授权,它与sercurity-constraint元素联合使用-->           security-role></security-role> <!--给出安全角色的一个列表,这些角色将出现在servlet元素内的security-role-ref元素的role-name子元素中。分别地声明角色可使高级IDE处理安全信息更为容易-->           <env-entry></env-entry>  <!--声明Web应用的环境项-->  </web-app></span>  
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表