关闭

Java Servlet工作原理问答

标签: servletjavasessionstack overflow
778人阅读 评论(0) 收藏 举报
分类:

导读

本文来自stackoverflow的问答,讨论了Java Servlet的工作机制,如何进行实例化、共享变量和多线程处理。

问题:Servlet是如何工作的?Servlet 如何实例化、共享变量、并进行多线程处理?

假设我有一个运行了大量 Servlet 的 web 服务器。通过 Servlet 之间传输信息得到 Servlet 上下文,并设置 session 变量。

现在,如果有两名或更多使用者向这个服务发送请求,接下来 session 变量会发生什么变化?究竟是所有用户都是用共同的变量?还是不同的用户使用的变量都不一样?如果是后者,服务器如何区分不同用户?

另一个相似的问题,如果有 n 名用户访问一个特定的 Servlet,那么该 Servlet 是仅在第一个用户首次访问的时候实例化,还是分别为每个用户实例化?

回答(BalusC):

ServletContext
当 Servlet 容器(比如 Apache Tomcat)启动后,会部署和加载所有 web 应用。当web 应用被加载,Servlet 容器会创建一次 ServletContext,然后将其保存在服务器的内存中。web 应用的 web.xml 被解析,找到其中所有 servlet、filter 和 Listener 或 @WebServlet、@WebFilter 和 @WebListener 注解的内容,创建一次并保存到服务器的内存中。对于所有过滤器会立即调用 init()。当 Servlet 容器停止,将卸载所有 web 应用,调用所有初始化的 Servlet 和过滤器的 destroy() 方法,最后回收 ServletContext 和所有 Servlet、Filter 与 Listener 实例。

当问题中的 Servlet 配置的 load-on-startup 或者 @WebServlet(loadOnStartup) 设置了一个大于 0 的值,则同样会在启动的时候立即调用 init() 方法。“load-on-startup”中的值表示那些 Servlet 会以相同顺序初始化。如果配置的值相同,会遵循 web.xml 中指定的顺序或 @WebServlet 类加载的顺序。另外,如果不设置 “load-on-startup” 值,init() 方法只在第一次 HTTP 请求命中问题中的 Servlet 时才被调用。

HttpServletRequest 与 HttpServletResponse
Servlet 容器附加在一个 web 服务上,这个 web 服务会在某个端口号上监听 HTTP 请求,在开发环境中这个端口通常为 8080,生产环境中通常为 80。当客户端(web 浏览器)发送了一个 HTTP 请求,Servlet 容器会创建新的 HttpServletRequest 和 HttpServletResponse 对象,传递给已创建好并且请求的 URL 匹配 url-pattern 的 Filter 和 Servlet 实例中的方法,所有工作都在同一个线程中处理。

request 对象可以访问所有该 HTTP 请求中的信息,例如 request header 和 request body。response 对象为你提供需要的控制和发送 HTTP 响应方法,例如设置 header 和 body(通常会带有 JSP 文件中的 HTML 内容)。提交并完成HTTP 响应后,将回收 request 和 response 对象。

HttpSession
当用户第一次访问该 web 应用时,会通过 request.getSession() 第一次获得 HttpSession。之后 Servlet 容器将会创建 HttpSession,生成一个唯一的 ID(可以通过 session.getId() 获取)并储存在服务器内存中。然后 Servlet 容器在该次 HTTP 响应的 Set-Cookie 头部设置一个 Cookie,以 JSESSIONID 作为 Cookie 名字,那个唯一的 session ID 作为 Cookie 的值。

按照 HTTP cookie 规则(正常 web 浏览器和 web 服务端必须遵循的标准),当 cookie 有效时,要求客户端(浏览器)在后续请求的 Cookie 头中返回这个 cookie。使用浏览器内置的 HTTP 流量监控器,你可以查看它们(在 Chrome、Firefox23+、IE9+ 中按 F12,然后查看 Net/Network 标签)。Servlet 容器将会确定每个进入的 HTTP 请求的 Cookie 头中是否存在名为JSESSIONID 的 cookie,然后用它的值(session ID)从服务端内存中找到关联的 HttpSession。

你可以在 web.xml 中设置 session-timeout ,默认值为 30 分钟。超时到达之前 HttpSession 会一直存活。所以当客户端不再访问该 web 应用超过 30 分钟后,Servlet 容器就会回收这个 session。后续每个请求,即使指定 cookie 名称也不能再访问到相同的 session。Servlet 容器会创建一个新的 Cookie。

另一方面,客户端上的 session cookie 有一个默认存活时间,该事件和该浏览器实例运行时间一样长。所以,当客户端关闭该浏览器实例(所有标签和窗口)后,这个 session 就会被客户端回收。新浏览器实例不再发送与该 session 关联的 cookie。一个新的 request.getSession() 将会返回新的 HttpSession 并设置一个拥有新 session ID 的 cookie。

概述

ServletContext 与 web 应用存活时间一样长。它被所有 session 中的所有请求共享。
只要客户端一直与相同浏览器实例的web应用交互并且没有超时,HttpSession就会存在。
HttpServletRequest 和 HttpServletResponse 的存活时间为客户端发送完成到完整的响应(web 页面)到达的这段时间。不会被其他地方共享。
所有 Servlet、Filter 和 Listener 对象在 web 应用运行时都是活跃的。它们被所有 session 中的请求共享。
你设置在 HttpServletRequest、HttpServletResponse 和 HttpSession 中的所有属性在问题中的对象存活时都会一直保持存活。
线程安全
即便如此,你最关心的可能是线程安全。你现在应该学习到 Servlet 和 filter 被所有请求共享。那是 Java 的一个优点,使得多个不同线程(读取 HTTP 请求)可以使用同一个实例。否则为每个请求重新创建线程的开销实在过于昂贵。

但你应该也意识到永远不要将任何 request 或 session 域中的数据赋值给 servlet 或 filter 的实例变量。它将会被所有其他 session 中的所有请求共享。那是非线程安全的!下面的示例对这种情况进行了展示:

public class ExampleServlet extends HttpServlet {

    private Object thisIsNOTThreadSafe;

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        Object thisIsThreadSafe;

        thisIsNOTThreadSafe = request.getParameter("foo"); // BAD!! Shared among all requests!
        thisIsThreadSafe = request.getParameter("foo"); // OK, this is thread safe.
    } 
}
2
1
查看评论

Java Servlet工作原理问答

导读 本文来自stackoverflow的问答,讨论了Java Servlet的工作机制,如何进行实例化、共享变量和多线程处理。 问题:Servlet是如何工作的?Servlet 如何实例化、共享变量、并进行多线程处理? 假设我有一个运行了大量 Servlet 的 web 服务器。通过 Ser...
  • u013063153
  • u013063153
  • 2015-11-04 21:42
  • 273

基于Servlet的技术问答网站系统实现(附源码)

这一篇博客将详细介绍一个基于Servlet的问答网站的实现,有详细的代码。 可能篇幅较长,以代码为主,有兴趣的童鞋看完可以尝试动手搭建一个属于自己的问答社区。 工具:Eclipse,数据库用到了MySQL,这次项目中未使用jsp,全部以Servlet注解的方式连接HTML和Servlet,JDK最好...
  • weixin_36380516
  • weixin_36380516
  • 2017-04-13 22:30
  • 4345

Java Servlet【2】Servlet工作原理(生命周期)

在Servlet【1】的博客中已经写到如何使用实现Servlet接口的方法来写Servlet程序,并写在web.xml文件中进行配置,成功运行,那么现在就说说Servlet的工作原理。同时这也是面试题之一。在本文最前说到了工作机制,当Servlet被第一次访问后,就被加载至内存,以后该实例对各个请求...
  • linweieran
  • linweieran
  • 2015-08-16 22:46
  • 925

【java】Servlet生命周期和工作原理

上篇博客介绍了Servlet 的调用流程,这篇博客介绍Servlet的生命周期和工作原理。 生命周期: Servlet生命周期包含了以下几个阶段:     1.加载和实例化      当检测到需要Servlet的第一个请求时,读取xml文...
  • u013046597
  • u013046597
  • 2016-07-30 17:15
  • 989

深入理解Tomcat系列之六:Servlet工作原理

前言Servlet是Web开发中的核心技术,作为一名合格的开发人员,就必须清楚Servlet的工作原理。本章没有对Servlet技术本身进行详细的说明,只是针对开发过程中一次Servlet的请求的处理过程进行分析的。Servlet实际上就是一个java类,只不过可以和浏览器进行一些数据的交换。有Se...
  • u011116672
  • u011116672
  • 2016-03-27 21:31
  • 5535

JSP/Servlet 工作原理(转载)

Servlet Servlet 没有 main 方法,不能够独立的运行,它的运行需要容器的支持,Tomcat 是最常用的 JSP/Servlet 容器。 Servlet 运行在 Servlet 容器中,并由容器管理从创建到销毁的整个过程。 对于用户到达Servlet的请求,Servlet容器会创建特...
  • insistGoGo
  • insistGoGo
  • 2014-03-08 23:20
  • 18132

Servlet的原理解析——我能看懂,相信你能

Servlet是在服务器上运行的小程序.而在java中应用程序多是在容器中进行生命周期的管理(这里指Tomact容器). Servlet基本的架构图   首先是  web页面通过提交表单tomact获取传递过来的数据...
  • bestone0213
  • bestone0213
  • 2015-08-10 14:25
  • 512

2016-08-20-java-写了一个问答机器人的程序

引用的数据来源是在聚合数据网站找的数据 key的话。。。。 package socket; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io...
  • guofengs
  • guofengs
  • 2016-08-20 10:02
  • 876

Java EE之Servlet技术

Java EE之Servlet技术java Servlet介绍Java Servlet是java EE标准规范之一。Servlet是Java Web 技术的核心基础,因此掌握好Servlet是很有必要的。掌握Servlet的工作原理是成为一名合格的 Java Web技术开发人员的基本要求。Servl...
  • nicewuranran
  • nicewuranran
  • 2016-06-15 22:25
  • 3142

java基础知识问答

线程与进程的区别归纳 a.地址空间和其它资源:进程间相互独立,同一进程的各线程间共享。某进程内的线程在其它进程不可见 b.通信:进程间通信IPC,线程间可以直接读写进程数据段(如全局变量)来进行通信——需要进程同步和互斥手段的辅助,以保证数据的一致性 c.调度和切换:线程上下文切换比进程上下文切...
  • u010255818
  • u010255818
  • 2017-03-09 11:30
  • 185
    个人资料
    • 访问:2425756次
    • 积分:30994
    • 等级:
    • 排名:第185名
    • 原创:501篇
    • 转载:316篇
    • 译文:43篇
    • 评论:1082条
    联系方式(点击)
    546190761
    Loving in Android
    技术 | 交流 | 娱乐 可以加下博主的群-- 312303901


    大家没事可以在群里闲聊Android, IOS,C/C++, Linux等技术问题,心得,学习体会等

    PS:博主仍是计算机行业的一名小学生

    The Weather
    博客专栏
    最新评论
    BruceZhang
    时间