浏览器-Tomcat服务器-请求与响应

  浏览器访问服务器,本质就是请求资源。
  比如请求静态资源:index.html,我们在浏览器地址栏输入:www.a.com/index.html,浏览器为了支持HTTP协议,发送的数据必须符合HTTP协议数据的格式,也就是这样:

  GET /index.html HTTP/1.1
  Accept-Language:zh-cn
  Connection:Keep-Alive
  Host:www.a.com
  User-Agent:Mozila/4.0(compatible;MSIE5.01;Window NT5.0)
  Accept-Encoding:gzip,deflate


  这些信息就成了请求信息,浏览器利用Socket,通过网络IO流发往服务器。如果做个比喻的话,浏览器比作男生,服务器比作女生,我想表达的意思是,浏览器是主动链接,并且主动请求数据,也就是想要的资源,而服务器存在资源,她只会等待浏览器主动请求她,她才会做出响应。

  此时服务器必须已经开启,因为她要监听某一个端口才能知道有人给她发信息了,这里比如是 80 端口。服务器监听80端口,有点类似于事件驱动编程的感觉,服务器利用ServerSocket,得到请求信息。服务器解析请求信息,得到需要请求的资源。这里先简单一分为二:


1 请求静态资源:

  服务器将会去服务器实现定义好的工作目录下,也是我们网站发布打包后的文件存放的地方,寻找a.html文件,若找到使用IO流,将文件加载到内存中,设置状态码为200,再输出到网络IO流,发送给浏览器,浏览器接收到响应信息,截取响应体,使用渲染引擎(所谓的内核)进行渲染。若找不到文件,则服务器设置响应头为404,我们可以自定义一句话来说明原因,大多数服务器返回404 File Not Found。这就是我们加载静态文件的流程。

2 请求动态资源servlet:

  先说说动态语言,即运行时才能得知变量的类型。而动态资源,就是未执行的.class文件,得到浏览器的请求信息,服务器执行一系列的事先定义好的.class文件,得到一个动态的结果返回给浏览器。

  做个比喻,好比静态资源就是你要买一辆普通的车,你就直接到车店,发送请求给车店,车店得到请求,解析它,知道你要买哪辆,然后返回给你汽车(有些痴人说梦哈)。动态资源呢,就是,你要私人定制一个豪华车,然后你就去汽车厂,发送请求给汽车厂,汽车厂得到请求之后,解析它,获得一些有用信息:车大小,里面配置,外表装饰等等,请注意,这里没有现成的车直接返回,而是得通过一系列的生产车间动态生成,等到生产完成,返回定制汽车,连接关闭。

  比喻打完,开始说正常流程。服务器得到浏览器发来的请求信息之后,解析它,得到了要执行的类名。这里就用到了【反射】,个人感觉反射技术很伟大,虽然确实降低性能,但是降低了类与类之间的耦合,就好比动态资源,我不清楚如果没有反射,我们将如何获得动态资源。得到想要的类名,利用反射,得到该类的对象,执行想要的方法,然后返回结果。

3 Servlet继承体系

 

4 Servlet生命周期

  生命周期方法
    init():当它第一次被创建的时候,执行该方法(只执行一次).
    service():对客户端响应方法。
    destroy():当它被销毁时,执行该方法。

  一个Servlet服务对应的只有一个Servlet对象,达到了“一个对象,多处服务”的效果,节约内存。用白话来解释就是,我们所有人访问的这个Servlet服务,使用的都是同一个Servlet对象。接下来给出Servlet对象从出生到死亡的步骤:

    1 实例化对象(使用构造方法)
    2 初始化(使用init()函数)
    3 服务(使用service()函数)
    4 销毁(调用destroy()函数)

  网站的过程是第一个人访问,然后很多人访问,最后服务器关闭。

  第一个人访问网站 更多人访问网站 服务器关闭
调用的方法 调用上述1,2,3方法 调用上述3方法 调用上述4方法

  Servlet路径

  长路径优先,这里指,<url-pattern>内容</url-pattern>
      绝对路径精确匹配,优先级高。例:/A/B
      路径匹配,通配符匹配           例:/*
      扩展名匹配,优先级最低        例:*.html

      注意:匹配不能混用。


  多线程问题:因为我们操作的是同一个Servlet对象。
      如果定义全局变量,可能会出现线程安全问题。

  ServletConfig:只属于这个Servlet的私有配置信息

  Servlet通过ServletConfig获取配置信息,如下:

<servlet>
      <servlet-name>名字</servlet-name>
      <servlet-class>类的完全限定名</servlet-class>
      <init-param>
          <param-name>fruit</param-name>
          <param-value>apple</param-value>
      </init-param>
  </servlet>

  这里我们通过ServletConfig来获得里面的配置信息,注意,这里的配置信息是私有的,只属于这个Servlet对象。

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out=response.getWriter();
        out.println("fruit:"+getInitParameter("fruit"));
        out.flush();
        out.close();
}

  ServletContext:属于这个Web应用程序的所有Servlet对象的共有配置信息

  一个ServletContext对应一个应用。
  一个ServletConfig对应一个Servlet。
  目的:
    1 实现数据的共享。比如登陆时的名字,用户的权限,和Session很类似。

      在一个Servlet类中,添加了一个全局数据,getServletContext().setAttribute("role", "manager");

      在另一个Servlet类中,就能得到此数据,getServletContext().getAttribute("role");

      2016-09-08  15:56:22   ???这里的疑问,难道ServletContext底层和Session有关???抛出疑问。。。

    2 共享web.xml信息。(必须是全局配置信息)
        配置全局<context-param></context-param>

  <context-param>
      <param-name>名字</param-name>
      <param-value>值</param-value>
  </context-param>

    3 获取应用下任意资源的绝对路径(硬盘。。)
        getServletContext().getRealPath("路径");

 

 

 

  注:此文章针对Java应用服务器Tomcat,至于其它服务器的请求和响应原理,我没做考证,所以我没将猜测说出来。

                                                                                                                                                                                

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
原文地址:https://www.cnblogs.com/kingofkai/p/5824529.html