假设我有一个Web服务器,其中包含许多Servlet。为了在这些servlet之间传递信息,我正在设置会话和实例变量。
现在,如果有2个或更多用户向该服务器发送请求,那么会话变量将如何处理?
它们对所有用户都是通用的还是对每个用户都不同?
如果它们不同,那么服务器如何区分不同的用户?
还有一个类似的问题,如果有n用户正在访问特定的servlet,那么仅当第一个用户第一次访问该servlet时才实例化该servlet,还是单独为所有用户实例化该servlet?
换句话说,实例变量将如何处理?
ServletContext
当servlet容器(例如ApacheTomcat)启动时,它将部署并加载所有Web应用程序。加载Web应用程序后,Servlet容器将创建ServletContext一次并将其保存在服务器的内存中。Web应用程序的web.xml所有包含的web-fragment.xml
文件进行解析,每个<servlet>
,<filter>
和<listener>
发现(或每一类注释用@WebServlet,@WebFilter并@WebListener分别)被实例化一次,并保存在服务器的内存。对于每个实例化的过滤器,其init()方法均通过new调用FilterConfig。
当a的Servleta<servlet>``<load-on-startup>
或@WebServlet(loadOnStartup)value
大于时0,则init()在启动期间还会使用new调用其方法ServletConfig。这些servlet以该值指定的相同顺序进行初始化(1为1st,2为2nd等)。如果多于一个的servlet指定了相同的值,则每个这些小服务程序的如它们出现在加载以相同的顺序web.xml,web-fragment.xml
或@WebServlet类加载。如果不存在“启动时加载”值,则init()当HTTP请求首次访问该servlet时,将调用该方法。
当Servlet容器完成上述所有初始化步骤后,ServletContextListener#contextInitialized()
将调用。
当servlet容器关闭时,它卸载所有Web应用程序,调用destroy()其全部初始化servlet和过滤器,所有的方法ServletContext,Servlet,Filter和Listener实例丢弃。最后,ServletContextListener#contextDestroyed()
将被调用。
HttpServletRequest和HttpServletResponse
Servlet容器连接到Web服务器,该Web服务器在某个端口号上侦听HTTP请求(端口8080通常在开发过程中使用,而端口80在生产中使用)。当客户端(例如,使用Web浏览器或以编程方式使用的用户URLConnection)发送HTTP请求时,Servlet容器将创建newHttpServletRequest和HttpServletResponse对象,并将它们通过Filter链中定义的任何对象(最后是Servlet实例)传递。
对于filter,将doFilter()调用该方法。当servlet容器的代码调用时chain.doFilter(request, response)
,请求和响应将继续到下一个过滤器,如果没有剩余的过滤器,则单击servlet。
对于servlet,将service()调用该方法。默认情况下,此方法根据来确定doXxx()要调用的方法之一 request.getMethod()
。如果servlet中没有确定的方法,则在响应中返回HTTP 405错误。
request对象提供对有关HTTP请求的所有信息的访问,例如URL,标头,查询字符串和正文。响应对象提供了以所需方式控制和发送HTTP响应的功能,例如,允许您设置标头和正文(通常使用从JSP文件生成的HTML内容)。提交并完成HTTP响应后,请求和响应对象都将被回收并可供重用。
HttpSession
当客户端首次访问该Web应用程序和/或通过首次访问该应用程序HttpSession
时request.getSession()
,Servlet
容器将创建一个新HttpSession对象,生成一个长而唯一的ID(您可以通过获取session.getId()
),并将其存储在服务器的记忆。Servlet容器还在HTTP响应Cookie的Set-Cookie标头中设置aJSESSIONID作为其名称,并将唯一会话ID作为其值。
根据HTTP cookie规范(任何体面的Web浏览器和Web服务器都必须遵守的合同),Cookie只要cookie有效,客户端(Web浏览器)就需要在标头的后续请求中将该cookie发送回去(也就是说,唯一ID必须指向未过期的会话,并且域和路径正确。使用浏览器的内置HTTP流量监视器,您可以验证Cookie是否有效(在Chrome / Firefox 23 + / IE9 +中按F12,然后检查“网络/网络”标签)。Servlet容器将检查Cookie每个传入HTTP请求的标头中是否存在具有该名称的cookie,JSESSIONID并使用其值(会话ID)HttpSession从服务器的内存中获取关联。
HttpSession活,直到它停留已经空闲(即,在请求未使用)超过规定的超时值<session-timeout>
,在设定web.xml。超时值默认为30分钟。因此,当客户端访问Web应用程序的时间不超过指定的时间时,Servlet容器将破坏会话。每个后续请求,即使指定了cookie,也将无法再访问同一会话;servlet容器将创建一个新会话。
在客户端,只要浏览器实例正在运行,会话cookie就会保持活动状态。因此,如果客户端关闭浏览器实例(所有选项卡/窗口),则会话将被丢弃在客户端侧。在新的浏览器实例中,与会话关联的cookie将不存在,因此将不再发送。这将导致HttpSession创建一个全新的会话,并使用一个全新的会话cookie。
简而言之
ServletContext
生活,只要Web应用程序的生命。它在所有会话的所有请求之间共享。HttpSession
生活,只要客户端与同一个浏览器实例中的Web应用程序进行交互,和会话未在服务器端超时。它在同一会话中的所有请求之间共享。HttpServletRequest
和HttpServletResponse
现场从servlet接收来自客户端的HTTP请求的时间,直到完全缓解(网页)已经到来。它没有在其他地方共享。Servlet
,所有Filter
和Listener
实例都会存在。它们在所有会话的所有请求之间共享。ServletContext
,HttpServletRequest
并且HttpSession
只要将生活中的问题生活中的对象。对象本身代表了诸如JSF,CDI,Spring等之类的bean管理框架中的“作用域”。这些框架将其范围内的bean作为attribute其最接近的匹配范围存储。您还应该意识到,永远不要将任何请求或会话范围的数据分配为Servlet或过滤器的实例变量。它将在其他会话中的所有其他请求之间共享。那不是线程安全的!下面的示例说明了这一点:
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.
}
}
我是使用会话变量的新手,尽管我在网上搜索了解会话变量,但我一直在苦苦挣扎。 所以基本上我有一个页面(search.php)。我加载一个基于搜索表单的动态数据表。加载表后,我通过AJAX执行以下操作: 正如您在Success和单击table row记录时所看到的,我的想法是通过AJAX发布一个变量以供以后使用。并将用户重定向到update.php页面。 然后,我希望使用发布的AJAX变量在sessi
问题内容: 我想知道是否有某种方式可以在两个或多个Servlet之间共享变量或对象,我的意思是某种“标准”方式。我认为这不是一个好习惯,但是是构建原型的更简单方法。 我不知道这是否取决于所使用的技术,但我将使用Tomcat 5.5 我想共享一个简单类的对象的Vector(仅公共属性,字符串,int等)。我的意图是在数据库中拥有一个静态数据,当Tomcat停止时,它显然会丢失。(仅用于测试) 问题答
问题内容: 我想像这样在多个线程之间共享一个变量: 我想在主线程和帮助线程之间共享,这是我创建的两个不同的Java类。有什么办法吗?谢谢! 问题答案: 二者并可以参照包含该变量的类。 然后,可以使该变量为 volatile ,这意味着 对该变量的更改在两个线程中立即可见。 有关更多信息,请参见本文。 易变变量 共享已同步的可见性功能,但不共享原子性功能。这意味着线程将自动 查看volatile变量
你可以在怎么使用变量中所描述的方式来创建,初始化,保存及加载单一的变量.但是当创建复杂的模块时,通常你需要共享大量变量集并且如果你还想在同一个地方初始化这所有的变量,我们又该怎么做呢.本教程就是演示如何使用tf.variable_scope() 和tf.get_variable()两个方法来实现这一点. 问题 假设你为图片过滤器创建了一个简单的模块,和我们的卷积神经网络教程模块相似,但是这里包括两
一般情况下,当一个传递给Spark操作(例如map和reduce)的函数在远程节点上面运行时,Spark操作实际上操作的是这个函数所用变量的一个独立副本。这些变量被复制到每台机器上,并且这些变量在远程机器上 的所有更新都不会传递回驱动程序。通常跨任务的读写变量是低效的,但是,Spark还是为两种常见的使用模式提供了两种有限的共享变量:广播变量(broadcast variable)和累加器(acc
Shared variables (共享变量)是为所有模板定义的变量。可以使用 setSharedVariable 方法向配置中添加共享变量: Configuration cfg = new Configuration(Configuration.VERSION_2_3_22); ... cfg.setSharedVariable("warp", new WarpDirective()); cfg