对 一个Servlet类型,服务器只创建一个实例对象 的理解

对 一个Servlet类型,服务器只创建一个实例对象 的理解,第1张

Servlet如何处理多个请求访问?
Servlet容器默认是采用单实例多线程的方式处理多个请求的:
1当web服务器启动的时候(或客户端发送请求到服务器时),Servlet就被加载并实例化(只存在一个Servlet实例);
2容器初始化化Servlet主要就是读取配置文件(例如tomcat,可以通过servletxml的<Connector>设置线程池中线程数目,初始化线程池通过webxml,初始化每个参数值等等。
3当请求到达时,Servlet容器通过调度线程(Dispatchaer Thread) 调度它管理下线程池中等待执行的线程(Worker Thread)给请求者;
4线程执行Servlet的service方法;
5请求结束,放回线程池,等待被调用;
(注意:避免使用实例变量(成员变量),因为如果存在成员变量,可能发生多线程同时访问该资源时,都来 *** 作它,照成数据的不一致,因此产生线程安全问题)
从上面可以看出:
第一:Servlet单实例,减少了产生servlet的开销;
第二:通过线程池来响应多个请求,提高了请求的响应时间;
第三:Servlet容器并不关心到达的Servlet请求访问的是否是同一个Servlet还是另一个Servlet,直接分配给它一个新的线程;如果是同一个Servlet的多个请求,那么Servlet的service方法将在多线程中并发的执行;
第四:每一个请求由ServletRequest对象来接受请求,由ServletResponse对象来响应该请求。
Servlet容器如何同时来处理多个请求
Java的内存模型JMM(Java Memory Model) ,JMM主要是为了规定了线程和内存之间的一些关系。根据JMM的设计,系统存在一个主内存(Main Memory),Java中所有实例变量都储存在主存中,对于所有线程都是共享的。每条线程都有自己的工作内存(Working Memory),工作内存由缓存和堆栈两部分组成,缓存中保存的是主存中变量的拷贝,缓存可能并不总和主存同步,也就是缓存中变量的修改可能没有立刻写到主存中;堆栈中保存的是线程的局部变量,线程之间无法相互直接访问堆栈中的变量。
Servlet采用多线程来处理多个请求同时访问。servlet依赖于一个线程池来服务请求。线程池实际上是一系列的工作者线程集合。Servlet使用一个调度线程来管理工作者线程。
当容器收到一个Servlet请求,调度线程从线程池中选出一个工作者线程,将请求传递给该工作者线程,然后由该线程来执行Servlet的service方法。当这个线程正在执行的时候,容器收到另外一个请求,调度线程同样从线程池中选出另一个工作者线程来服务新的请求,容器并不关心这个请求是否访问的是同一个Servlet当容器同时收到对同一个Servlet的多个请求的时候,那么这个Servlet的service()方法将在多线程中并发执行。
Servlet容器默认采用单实例多线程的方式来处理请求,这样减少产生Servlet实例的开销,提升了对请求的响应时间,对于Tomcat可以在serverxml中通过<Connector>元素设置线程池中线程的数目。
注意:服务器可以使用多个实例来处理请求,代替单个实例的请求排队带来的效益问题。服务器创建一个Servlet类的多个Servlet实例组成的实例池,对于每个请求分配Servlet实例进行响应处理,之后放回到实例池中等待下此请求。这样就造成并发访问的问题。
此时,局部变量(字段)也是安全的,但对于全局变量和共享数据是不安全的,需要进行同步处理。而对于这样多实例的情况SingleThreadModel接口并不能解决并发访问问题。 SingleThreadModel接口在servlet规范中已经被废弃了

application对象

什么是application对象?

( )当Web服务器启动时 Web服务器会自动创建一个application对象 application对象一旦创建 它将一直存在 直到Web服务器关闭

一个Web服务器通常有多个Web服务目录(网站) 当Web服务器启动时 它自动为每个Web服务目录都创建一个application对象 这些application对象各自独立 而且和Web服务目录一一对应

访问同一个网站的客户都共享一个application对象 因此 application对象可以实现多客户间的数据共享

访问不同网站的客户 对应的application对象不同

( )application对象的生命周期 从Web服务器启动 直到Web服务器关闭

注意 一个Web应用程序启动后 将会自动创建一个application对象 而且在整个应用程序的运行过程中只有一个application对象 也即所有访问该网站的客户都共享一个application对象

( )application对象的作用范围 application对象是一个应用程序级的对象 它作用于当前Web应用程序 也即作用于当前网站 所有访问当前网站的客户都共享一个application对象

具体来说 不管哪个客户来访问网站A 也不管客户访问网站A下哪个页面文件 都可以对网站A的application对象进行 *** 作 因为 所有访问网站A的客户都共用一个application对象

因此 当在application对象中存储数据后 所有访问网站A的客户都能够对其进行访问 实现了多客户之间的数据共享

( )application对象的基类是 javax servlet ServletContext类

注意 有些Web服务器不直接支持使用application对象 必须用ServletContext类来声明application对象 再调用getServletContext()方法来获取当前页面的application对象

( )ServletContext类 用于表示应用程序的上下文

一个ServletContext类的对象表示一个Web应用程序的上下文

具体来说 在Web服务器中 提供了一个Web应用程序的运行时环境 专门负责Web应用程序的部署 编译 运行以及生命周期的管理 通过ServletContext类 可以获取Web应用程序的运行时环境信息

常识 JSP引擎 Servlet引擎 JSP容器和Servlet容器 都是指Web服务器 Web服务器用于管理所有Web应用程序

( )application对象的常用方法 如下所示

方法名 描述 StringgetAttribute(Stringname) 根据属性名称获取属性值 EnumerationgetAttributeNames() 获取所有的属性名称 voidsetAttribute(Stringname Objectobject) 设置属性 指定属性名称和属性值 voidremoveAttribute(Stringname) 根据属性名称删除对应的属性 ServletContextgetContext(Stringuripath) 获取指定URL的ServletContext对象 StringgetContextPath() 获取当前Web应用程序的根目录 StringgetInitParameter(Stringname) 根据初始化参数名称 获取初始化参数值 intgetMajorVersion() 获取ServletAPI的主版本号 intgetMinorVersion() 获取ServletAPI的次版本号 StringgetMimeType(Stringfile) 获取指定文件的MIME类型 StringgetServletInfo() 获取当前Web服务器的版本信息 StringgetServletContextName() 获取当前Web应用程序的名称 voidlog(Stringmessage) 将信息写入日志文件中

使用application对象存储数据

( )设置application对象的属性和获取application对象的属性

测试代码

TestApplication jsp

<%@pagelanguage=&# ;java&# ;contentType=&# ;text/;charset=GBK&# ;%>

<%request setCharacterEncoding(&# ;GBK&# ;);%>

<>

<body>

<formname=&# ;form &# ;action=&# ; method=&# ;post&# ;>

用户名

<inputtype=&# ;text&# ;name=&# ;username&# ;value=&# ; >

<br>

密码

<inputtype=&# ;password&# ;name=&# ;pwd&# ;value=&# ; >

<br>

<inputtype=&# ;submit&# ;name=&# ;btSubmit&# ;value=&# ;提交&# ;>

</form>

<%

application setAttribute(&# ;username&# ; request getParameter(&# ;username&# ;));

application setAttribute(&# ;pwd&# ; request getParameter(&# ;pwd&# ;));

%>

</body>

</>

测试代码

TestCommon jsp

在TestCommon jsp页面中 通过application对象获取属性 注意TestApplication jsp和TestCommon jsp这两个页面之间没有任何关联 只要通过application对象设置了属性 那么就可以在任何页面 通过application对象获取属性或者删除属性

<%@pagelanguage=&# ;java&# ;contentType=&# ;text/;charset=GBK&# ;%>

<%request setCharacterEncoding(&# ;GBK&# ;);%>

<>

<body>

用户名 <%=application getAttribute(&# ;username&# ;)%><br>

密码 <%=application getAttribute(&# ;pwd&# ;)%><br>

</body>

</>

( )删除application对象的属性

测试代码

TestCommon jsp

在TestCommon jsp页面中 删除application对象的属性

<%@pagelanguage=&# ;java&# ;contentType=&# ;text/;charset=GBK&# ;%>

<%request setCharacterEncoding(&# ;GBK&# ;);%>

<>

<body>

<%&# ;删除属性&# ;%>

<%

application removeAttribute(&# ;username&# ;);

application removeAttribute(&# ;pwd&# ;);

%>

用户名 <%=application getAttribute(&# ;username&# ;)%><br>

密码 <%=application getAttribute(&# ;pwd&# ;)%><br>

</body>

</>

使用application对象实现网站计数器

测试代码

TestApplication jsp

<%@pagelanguage=&# ;java&# ;contentType=&# ;text/;charset=GBK&# ;%>

<%@pageimport=&# ;java util &# ;%>

<%request setCharacterEncoding(&# ;GBK&# ;);%>

<>

<body>

<%!

ServletContextapplication;

synchronizedvoidcountPeople(){

application=getServletContext();

Integernumber=(Integer)application getAttribute(&# ;number&# ;);

if(number==null){

number=newInteger( );

application setAttribute(&# ;number&# ; number);

}else{

number=newInteger(number intValue()+ );

application setAttribute(&# ;number&# ; number);

}

}

%>

<%

if(session isNew()){

countPeople();

}

intpersonCount=((Integer)application getAttribute(&# ;number&# ;)) intValue();

%>

<p>欢迎访问本网站 您是第<%=personCount%>个访问用户!

</body>

</>

使用application对象获取初始化参数

( )一般来说 在web xml文件中 设置初始化参数有如下两种方式

n设置系统范围内的初始化参数

n针对单个Servlet文件或JSP文件设置初始化参数

对于系统范围内的初始化参数 可通过ServletContext接口的getInitParameter(Stringname)方法 根据指定的参数名 获取对应的参数值

对于针对单个Servlet文件或JSP文件设置初始化参数 可通过ServletConfig接口的getInitParameter(Stringname)方法 根据指定的参数名 获取对应的参数值 ( )如何设置系统范围内的初始化参数

在web xml文件中 可利用context param元素来设置系统范围内的初始化参数 context param元素应该包含param name param value以及可选的description子元素 如下所示 <context param> <param name>support email</param name> <param value></param value> </context param>

web xml文件的示例

<xmlversion=&# ; &# ;encoding=&# ;UTF &# ;>

<web appversion=&# ; &# ;

xmlns=&# ;;

xmlns:xsi=&# ;;charset=GBK&# ;%>

<%request setCharacterEncoding(&# ;GBK&# ;);%>

<>

<body>

<%&# ;使用application对象获取系统范围内的初始化参数&# ;%>

<fontcolor=&# ;Red&# ;>使用application对象获取初始化参数 </font>

<br>

<%

StringappName=getServletContext() getInitParameter(&# ;appName&# ;);

StringappVersion=getServletContext() getInitParameter(&# ;appVersion&# ;);

%>

应用程序的名称 <%=appName%><br>

应用程序的版本 <%=appVersion%>

</body>

</>

修改web xml文件 添加蓝色字体部分

<xmlversion=&# ; &# ;encoding=&# ;UTF &# ;>

<web appversion=&# ; &# ;

xmlns=&# ;;

xmlns:xsi=&# ;;charset=GBK&# ;

pageEncoding=&# ;GBK&# ;%>

<%request setCharacterEncoding(&# ;GBK&# ;);%>

<>

<body>

<h >使用application对象获取Web应用程序的环境信息</h >

<p>

<fontcolor=&# ;Red&# ;>获取当前Web服务器的版本信息 </font><%=application getServerInfo()%><br>

<fontcolor=&# ;Red&# ;>获取ServletAPI的主版本号 </font><%=application getMajorVersion()%><br>

<fontcolor=&# ;Red&# ;>获取ServletAPI的次版本号 </font><%=application getMinorVersion()%>

<p>

<fontcolor=&# ;Red&# ;>获得指定URL的ServletContext对象 </font>

<%

ServletContextsc=application getContext(&# ;/ch /TestApplication jsp&# ;);

out println(sc getServerInfo());

%>

<p>

<%&# ;需要在web xml设置display name元素&# ;%>

<fontcolor=&# ;Red&# ;>获取当前Web应用程序的名称 </font><%=application getServletContextName()%>

<p>

<fontcolor=&# ;Red&# ;>获取当前Web应用程序的上下文路径 </font><%=application getContextPath()%>

</body>

</>

测试结果

session对象和application对象的比较

( )两者的作用范围不同

session对象是用户级的对象 而application对象是应用程序级的对象

一个用户一个session对象 每个用户的session对象不同 在用户所访问网站的多个页面之间共享同一个session对象

一个Web应用程序一个application对象 每个Web应用程序的application对象不同 但一个Web应用程序的多个用户之间共享同一个application对象

在同一个网站下

n每个用户的session对象不同

n所用用户的application对象相同

在不同网站下

n每个用户的session对象不同

n每个用户的application对象不同

( )两者的生命周期不同

session对象的生命周期 用户首次访问网站创建 用户离开该网站(不一定要关闭浏览器)消亡

application对象的生命周期 启动Web服务器创建 关闭Web服务器销毁

lishixinzhi/Article/program/Java/hx/201404/30479

session是存储在服务器端的,cookie是存储在客户端的,所以session的安全性要高于cookie。
再者,我们获取的session里的信息是通过存放在会话cookie里的sessionId获取的。
因为session是存放在服务器里的,所以session里的东西不断增加会增加服务器的负担,我们会把一些重要的东西放在session里,不太重要的放在客户端cookie里。
cookie分为两大类,一个是会话cookie和持久化cookie,他们的生命周期和浏览器是一致的,浏览器关了会话cooki也就消失了,而持久化会存储在客户端硬盘中。

首先纠正一下 servlet并不是在服务器启动的时候执行init()方法实例化的而是在服务器启动后你访问该servlet的时候才调用init()实例化的,实例化之后就会调用service()方法在服务器关闭的时候会执行destroy()方法 这个只要在每个方法里输出一句话就能验证至于为什么嘛我觉得应该是你访问servlet的时候需要调用service()方法所以会在那时候实例化吧

request从浏览器向服务器只能传递字符串或者JSON对象(也是字符串),通过requestgetParameter("varName")获取(这个方法的返回值固定为String类型),想在request中设置对象如:requestsetAttribute("obj",obj),服务器是取不到的,因为不管你通过表单提交,还是ajax请求,在服务器都是创建的新的request对象。一个request的生命周期是一个请求开始,到服务器器响应结束,新的请求会创建新的request对象。
从服务器向浏览器看起来可以传递对象,其实际上也只是传递的字符串(html标准标签),
在后台requestsetAttribute("obj",obj),在页面requestgetAttribute("obj")(返回值为Object类型,需要强制类型转换),是传的对象,但是这仅仅是在servlet和java类之间的传递,因为所有java代码的执行都在服务器端,不会有任何java对象从服务器传递到浏览器,当然仍然可以传json对象到浏览器,不得不说json也是字符串,算是soap(简单对象传输协议)吧。

客户端和服务器端可以简单理解为一个客户端上运行 一个服务端运行
BS架构的程序, 比如你打开网页, 服务端运行 查询数据,组织数据,输出html工作
客户端主要为IE等浏览器解释HTML语言,展示效果,运行JS脚本等工作


欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zz/13165972.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-06-14
下一篇 2023-06-14

发表评论

登录后才能评论

评论列表(0条)

保存