Java Servlet工作原理问答
2015-11-05 12:58
417 查看
http://www.importnew.com/17025.html
本文由 ImportNew - honoka 翻译自 stackoverflow。欢迎加入翻译小组。转载请见文末要求。
本文来自stackoverflow的问答,讨论了Java Servlet的工作机制,如何进行实例化、共享变量和多线程处理。
假设我有一个运行了大量
session 变量。
现在,如果有两名或更多使用者向这个服务发送请求,接下来 session 变量会发生什么变化?究竟是所有用户都是用共同的变量?还是不同的用户使用的变量都不一样?如果是后者,服务器如何区分不同用户?
另一个相似的问题,如果有
当 Servlet 容器(比如 Apache Tomcat)启动后,会部署和加载所有 web 应用。当web 应用被加载,Servlet
容器会创建一次
应用的
Servlet 容器停止,将卸载所有 web 应用,调用所有初始化的 Servlet 和过滤器的
与
当问题中的
0 的值,则同样会在启动的时候立即调用
“load-on-startup” 值,
Servlet 容器附加在一个 web 服务上,这个 web 服务会在某个端口号上监听 HTTP 请求,在开发环境中这个端口通常为 8080,生产环境中通常为 80。当客户端(web 浏览器)发送了一个 HTTP 请求,Servlet 容器会创建新的
URL 匹配
request 对象可以访问所有该 HTTP 请求中的信息,例如 request header 和 request body。response 对象为你提供需要的控制和发送 HTTP 响应方法,例如设置 header 和 body(通常会带有 JSP 文件中的 HTML 内容)。提交并完成HTTP 响应后,将回收 request 和 response 对象。
当用户第一次访问该 web 应用时,会通过
Servlet 容器将会创建
Servlet 容器在该次 HTTP 响应的
Cookie 名字,那个唯一的 session ID 作为
按照 HTTP cookie 规则(正常 web 浏览器和 web 服务端必须遵循的标准),当 cookie
有效时,要求客户端(浏览器)在后续请求的
容器将会确定每个进入的 HTTP 请求的
cookie,然后用它的值(session ID)从服务端内存中找到关联的
你可以在
30 分钟。超时到达之前
容器会创建一个新的
另一方面,客户端上的 session cookie 有一个默认存活时间,该事件和该浏览器实例运行时间一样长。所以,当客户端关闭该浏览器实例(所有标签和窗口)后,这个 session 就会被客户端回收。新浏览器实例不再发送与该 session 关联的 cookie。一个新的
的 cookie。
只要客户端一直与相同浏览器实例的web应用交互并且没有超时,HttpSession就会存在。
页面)到达的这段时间。不会被其他地方共享。
web 应用运行时都是活跃的。它们被所有 session 中的请求共享。
你设置在
即便如此,你最关心的可能是线程安全。你现在应该学习到 Servlet 和 filter 被所有请求共享。那是 Java 的一个优点,使得多个不同线程(读取 HTTP 请求)可以使用同一个实例。否则为每个请求重新创建线程的开销实在过于昂贵。
但你应该也意识到永远不要将任何 request 或 session 域中的数据赋值给 servlet 或 filter 的实例变量。它将会被所有其他 session 中的所有请求共享。那是非线程安全的!下面的示例对这种情况进行了展示:
JSF、Servlet
和 JSP 之间有什么不同?
Java
中管理 Session 的最佳选择
Servlet
中的 doGet 与 doPost
Servlet
似乎会同步处理多并发请求
原文链接: stackoverflow 翻译: ImportNew.com - honoka
译文链接: http://www.importnew.com/17025.html
[ 转载请保留原文出处、译者和译文链接。]
本文由 ImportNew - honoka 翻译自 stackoverflow。欢迎加入翻译小组。转载请见文末要求。
导读
本文来自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并设置一个拥有新
sessionID
的 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 中的所有请求共享。那是非线程安全的!下面的示例对这种情况进行了展示:
请参考:
JSF、Servlet和 JSP 之间有什么不同?
Java
中管理 Session 的最佳选择
Servlet
中的 doGet 与 doPost
Servlet
似乎会同步处理多并发请求
原文链接: stackoverflow 翻译: ImportNew.com - honoka
译文链接: http://www.importnew.com/17025.html
[ 转载请保留原文出处、译者和译文链接。]
关于作者: honoka
相关文章推荐
- (JAVA)获取图片轮廓
- Spring 3整合Quartz 2实现定时任务(转)
- 单例模式的三种写法
- java厚积薄发之String常用方法
- 桶排序算法之Java实现
- 浅析Java中的final关键字
- Java RMI 介绍和例子以及Spring对RMI支持的实际应用实例
- java中static作用详解
- Java多线程
- java 获取当前月第一天和最后一天
- java数组中,然后把奇数放在数组的左边,偶数放在右边,方法一
- spring 使用logback打印调试日志
- 深入理解java中的synchronized关键字
- JAVA字符串格式化-String.format()的使用
- SpringMVC介绍之约定优于配置
- Spring中的@Transactional 放在 类级别 和 方法级别 上有什么不同?
- Java高精度四则运算(无括号限制)
- Eclipse is running in a JRE, but a JDK is required 解决方法
- Eclipse 修改 工程名称
- java:23种设计模式全解析之一