servlet总结(一)到底servlet是什么?


2016-06-19 到 2016-07-28
> eat, move, shit,eat,move,shit,……
> 当自己抽烟或者迷茫的时候,就标识自己需要灌灌鸡汤,或者抬头看看路。应该如果在这样低着头走下去,每天早上心情就会变得跟上坟差不多了。所以说鸡汤很重要,信念很重要,方法很重要。

servlet的小节

一、什么是servlet?

要说明servlet首先必须说明servlet的容器。这两者之间的关系,可以说是枪和子弹的关系,子弹可以单独的存在,但是意义不是很大。当子弹放进枪里面的时候,才会有强大的作用。

说到servlet的容器,常见的有两种tomcat和jetty,自己都使用过,但是tomcat比较的常见,并且应用比较的广泛,所以就按照这个为准。tomcat就是servlet容器,既然是容器,就可以包含多个的servlet,这样就会牵扯到多个servlet之间的关系和管理,等等的功能,这就是servlet容器提供的功能了,让servlet的功能运行额更加的完好。就像五四手枪和沙漠之鹰一样,都可以最大限度的发挥子弹的作用。

首先看一下tomcat的容器的模型:

Tomcat的容器模型

Context 容器是直接管理 Servlet 在容器中的包装类 Wrapper。而Wrapper更像枪中的那个子弹的外壳 ,包括着一个一个的servlet的。现在更能感受到servlet就像是一个一个的标准。

我们直观的感受servlet,就是:javax.servlet 和 javax.servlet.http 包中类,但是事实上servlet指的是一种规范,当http请求的时候,数据是怎么到服务器的。以及服务器拿到请求以后,响应后,怎么返回给客户端的规范。所以:

servlet只是一个规范,定义服务请求和响应的大致式样。 Java servlet 类将那些低层的结构包装在 Java 类中,这些类所包含的便利方法使其在 Java 语言环境中更易于处理。正如您正使用的特定 servlet 容器的配置文件中所定义的,当用户通过 URL 发出一个请求时,这些 Java servlet 类就将之转换成一个 HttpServletRequest,并发送给 URL 所指向的目标。当服务器端完成其工作时,Java 运行时环境(Java Runtime Environment)就将结果包装在一个 HttpServletResponse 中,然后将原 HTTP 响应送回给发出该请求的客户机。在与 Web 应用程序进行交互时,通常会发出多个请求并获得多个响应。所有这些都是在一个会话语境中,Java 语言将之包装在一个 HttpSession 对象中。在处理响应时,您可以访问该对象,并在创建响应时向其添加事件。它提供了一些跨请求的语境。

我们可以看一下在servlet的规范中,典型的类不太多,只是用来说明web的请求和数据的返回,主要的类如下所示: servlet的类

关于HTTPServletResquest和HttpServletResponse,HttpSession已经说过了,但是每次的请求总会有一些留存的数据或者缓存的数据,就是Cookie,然后就是一个工具类:HttpUtils。

知晓了这些,我们的就能够理解servlet的容器的工作的原理,这个容器需要配置,以便servlet暴露给外部的世界。正如我看到的,通过该容器中的各种配置文件,您在 URL(由用户在浏览器中输入)与服务器端组件之间搭建了一座桥梁,这些组件将处理您需要该 URL 转换的请求。在运行应用程序时,该容器将加载并初始化 servlet,管理其生命周期。

当我们说 servlet 具有生命周期时,只是指在调用 servlet 时,事情是以一种可预见的方式发生的。换言之,在任何 servlet 上创建的方法总是按相同的次序被调用的

下面是一个典型场景: 用户在浏览器中输入一个 URL。Web 服务器配置文件确定该 URL 是否指向一个由运行于服务器上的 servlet 容器所管理的 servlet。 1. 如果还没有创建该 servlet 的一个实例(一个应用程序只有一个 servlet 实例),那么该容器就加载该类,并将之实例化。 2. 该容器调用 servlet 上的 init()。 3. 该容器调用 servlet 上的 service(),并在包装的 HttpServletRequest 和 HttpServletResponse 中进行传递。 4. 该 servlet 通常访问请求中的元素,代表其他服务器端类来执行所请求的服务并访问诸如数据库之类的资源,然后使用该信息填充响应。 5. 如果有必要,在 servlet 的有用生命结束时,该容器会调用 servlet 上的 destroy() 来清除它。 如何“运行”servlet

二、servlet的运行

“运行”servlet 就像运行 Java 程序一样。一旦配置了容器,使容器了解 servlet,并知道某些 URL 会致使容器调用该 servlet,该容器就将按照预定的次序调用生命周期方法。因此,运行 servlet 主要是指正确配置它,然后将浏览器指向正确的 URL。当然,servlet 中的代码正是发现有趣的业务逻辑的地方。您不必担心低层事件的进展,除非发生某种错误。

Servlet体系是建立在Java多线程的基础之上的,它的生命周期是由Tomcat来维护的。有上面所说明的生命周期,可以推测出:当客户端第一次请求Servlet的时候,tomcat会根据web.xml配置文件实例化servlet,当又有一个客户端访问该servlet的时候,不会再实例化该servlet,也就是多个线程在使用这个实例。所以说对于一个servlet一般只有一个实例。

serlvet容器一般的采用多线程来处理多个请求同时访问,Tomcat容器维护了一个线程池来服务请求。线程池实际上是等待执行代码的一组线程叫做工作组线程(Worker Thread),Tomcat容器使用一个调度线程来管理工作组线程(Dispatcher Thead)。

tomcat响应servlet的请求

当容器收到一个Servlet请求,Dispatcher线程从线程池中选出一个工作组线程,将请求传递给该线程,然后由该线程来执行Servlet的service方法。当这个线程正在执行的时候,容器收到另一个请求,调度者线程将从线程池中选出另外一个工作组线程来服务则个新的请求,容器并不关心这个请求是否访问的是同一个Servlet还是另一个Servlet。当容器收到对同一个Servlet的多个请求的时候,那这个servlet的service方法将在多线程中并发的执行。所以如果servlet中请求的有全局的变量(或者依赖于请求的变量),那么此时的servlet就不是线程安全的。

例如:

public class TestServlet extends HttpServlet {
     private int count = 0;  
     @Override
     protected void service(HttpServletRequest request, HttpServletResponse response)
             throws ServletException, IOException {
         response.getWriter().println("<HTML><BODY>");
         response.getWriter().println(this + " ==> ");
         response.getWriter().println(Thread.currentThread() + ": <br>");
         for(int i=0;i<5;i++){
             response.getWriter().println("count = " + count + "<BR>");
             try {
                 Thread.sleep(1000);  
                 count++;  
             } catch (Exception e) {
                 e.printStackTrace();
             }
         }
         response.getWriter().println("</BODY></HTML>");
     }
 }

三,servlet 容器的设计

https://www.ibm.com/developerworks/cn/java/j-lo-tomcat1/

理解了原理之后,我们可以写出来自己的servlet容器。

总结就是:servlet只是一套的协议。作用在web服务器上面。规范每一次的请求和请求对应的回复。



上一篇  servlet总结(二)servlet规范和servlet的容器是什么? 下一篇   第六个周末-坚持住