Tomcat / Jetty(1)

写在最开始: 

  这只是我自己网上找资料和课程学习总结的,并不一定准确,有什么错误可以提出来。。。仅供参考

HTTP

  (tomcat / jetty实际上就是一个http服务器+servlet容器)HTTP是应用层协议,它不涉及数据包传输,而是基于TCP/IP协议来传输数据的,主要是规定客户端和服务器的通信格式。

Cookie

  cookie是http报文的一个请求头,web应用可以将一些信息保存在cookie中,每次请求时传递过去,HTTP是无状态的,每次请求之间没有关系,服务器用cookie来辨别客户端传来的信息。(因为是以明文的方式存储到本地,存储用户信息会不安全,所以使用session)

Session

  session是服务器开辟出来的存储空间,用来存储用户的状态等信息。请求过来时服务器可以将用户的请求和用户的session对应起来。如何对应:浏览器在cookie中放置一个session id之类的字段用来标识请求。

  创建时机:Web应用程序在调用HttpServletRequest的getSession方法时, Web容器(比如Tomcat)创建。

  流程:服务器在创建session的同事会生成一个唯一的session id,浏览器再次发送请求的时候会把session id带上,服务器接收到session id之后会找到对应得session,然后就可以在session中修改内容了。

Servlet规范和Servlet容器

  浏览器发送给服务端的是一个HTTP格式的请求,HTTP服务器接收到请求后调用对应的业务类来处理,HTTP服务器要如何区分请求和需要调用的业务类方法?可以在HTTP服务器的代码里加上判断语句,是哪个请求就调用对应的业务方法进行处理,但这样的话,代码不仅繁琐逻辑比较混乱还耦合,不利于扩展,想添加新功能比较麻烦。于是有了servlet接口,实现了servlet接口的类被称为servlet,这样业务类就可以规范起来,但还是需要解决业务类的调用和实例化问题,于是有了servlet容器,它用来加载和管理servlet类。servlet接口和servlet容器这一整套规范就是servlet规范,tomcat  /  jetty就根据servlet规范实现了servlet容器,并且它们还含有HTTP服务器。

  Servlet容器工作流程:当客户请求某个资源时,HTTP服务器会用一个ServletRequest对象把客户的请求信息封装起来,然后调用 Servlet容器的service方法,Servlet容器拿到请求后,根据请求的URL和Servlet的映射关系,找到相应的Servlet,如果Servlet还没有被加载,就用反射机制创建这个Servlet,并调用Servlet的init方法来完成初始化,接着调用Servlet的service方法来处理请求,把ServletResponse对象返回给HTTP服务器,HTTP服务器会把响应发送给客户端.

Servlet接口

public interface Servlet {
    void init(ServletConfig config)throws ServletException;

    ServletConfig getServletConfig();

    void service(ServletRequest req, ServletResponse res)throws ServletException, IOException;

  String getServletInfo();
void destroy(); }

  这是servlet接口的五个方法,重要的是service方法,业务类就在这个方法中实现处理逻辑,里面的两个参数ServletRequest和ServletResponse按照通信协议分别封装了请求和响应信息。它们的子类HttpServletRequest和HttpServletResponse对应请求和响应,可以通过HttpServletRequest来获取session进行操作。

Filter和Listener

  servlet规范满足了大部分编程需求,但如果需要一些特殊的功能,就需要使用到Filter(过滤器)和Listener(监听器)。

  Filter(基于过程)接口允许我们做一些统一的定制化处理,工作原理:Web应用部署完成后, Servlet容器需要实例化Filter并把Filter链接成一个FilterChain。当请求进来时,获取第一个Filter并调用 doFilter方法,doFilter方法负责调用这个FilterChain中的下一个Filter。

  Listener(基于状态)接口用来监听并让我们可以选择加载时机。当Web应用在Servlet容器中运行时,Servlet容器内部会不断的发生各种事件,如Web应用的启动和停止、用户请求到达等。 Servlet容器提供了一些默认的监听器来监听这些事件,当事件发生时,Servlet容器会负责调用监听器的方法。我们可以定义自己的监听器去监听感兴趣的事件,将监听器配置在web.xml中。比如Spring就实现了自己的监听器,来监听ServletContext的启动事件,目的是当Servlet容器启动时,创建并初始化全局的Spring容器。

web应用

  一般情况下servlet是以web应用程序的方式部署的,根据servlet规范,web应用程序应该有一定的工作目录结构,用来存放类文件、配置文件和静态资源等。

|-WebApp
    |-WEB-INF/web.xml    --配置⽂件,⽤来配置Servlet等
    |-WEB-INF/lib/    --存放Web应⽤所需各种JAR包
    |-WEB-INF/classes/    --存放你的应⽤类,⽐如Servlet类
    |-META-INF/    --⽬录存放⼯程的⼀些信息

  servlet规范定义了ServletContext这个接口来对应一个web应用,应用部署好后,Servlet容器在启动时会加载Web应用,并为每个Web应用创建唯一的ServletContext对象。你可以把ServletContext看成是一个全局对象,一个Web应用可能有多个Servlet,这些Servlet可以通过全局的ServletContext来共享数据,这些数据包括Web应用的初始化参数、Web应用目录下的文件资源等。由于ServletContext持有所有的Servlet实例,可以通过它来实现Servlet请求的转发。

copy一段别人的题外话:

  Tomcat  /  Jetty在启动时给每个Web应用创建一个全局的上下文环境,这个上下文就是ServletContext,为后面的Spring容器提供宿主环境。

  Tomcat  /  Jetty在启动过程中触发容器初始化事件,Spring的ContextLoaderListener会监听到这个事件,它的contextInitialized方法会被调用,在这个方法中,Spring会初始化全局的Spring根容器,这个就是Spring的IoC容器,IoC容器初始化完毕后,Spring将其存储到ServletContext中,便于以后来获取。

  Tomcat&Jetty在启动过程中还会扫描Servlet,一个Web应用中的Servlet可以有多个,以SpringMVC中的Di spatcherServlet为例,这个Servlet实际上是一个标准的前端控制器,用以转发、匹配、处理每个Servlet 请求。

  Servlet一般会延迟加载,当第一个请求达到时,Tomcat  /  Jetty发现DispatcherServlet还没有被实例化,就调用DispatcherServlet的init方法,DispatcherServlet在初始化的时候会建立自己的容器,叫做SpringMVC容器,用来持有SpringMVC相关的Bean。同时,Spring MVC还会通过ServletContext拿到Spring根容器 ,并将Spring根容器设为SpringMVC容器的父容器,请注意,SpringMVC容器可以访问父容器中的Bean,但是父容器不能访问子容器的Bean,也就是说Spring根容器不能访问SpringMVC容器里的Bean。说的通俗点就是,在Controller里可以访问Service对象,但是在Service里不可以访问Controller对象。

posted @ 2020-08-14 16:05  演而优则导  阅读(89)  评论(0)    收藏  举报