第三章 Servlet容器模型_第1页
第三章 Servlet容器模型_第2页
第三章 Servlet容器模型_第3页
第三章 Servlet容器模型_第4页
第三章 Servlet容器模型_第5页
已阅读5页,还剩40页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第三章Servlet容器模型3.1ServletContext对象3.2侦听ServletContext对象的事件3.3过滤器基本概念当servlet容器启动时,它会初始化每一个部署好的Web应用程序。这时容器会为每个Web应用程序创建一个ServletContext对象。ServletContext对象3.1节我们可以在编写Servlet代码时,通过ServletContext对象获得与Web应用程序相关的信息。

注意,Web应用的信息应是其中所有Servlet共享的信息。WebApp1拥有一个ServletContext对象WebApp2拥有第二个ServletContext对象HelloworldApp拥有第三个ServletContext对象Web应用程序的初始化参数ServletContext对象3.1节每个WebApps目录下的子目录都被Tomcat看作一个Web应用每个应用都有一个配置文件,其中存放该应用的部署信息,其中包括该应用的初始化信息<web-app>

:<context-param><param-name>copyright</param-name><param-value>Copyright2004

</param-value></context-param>

:</web-app>

publicvoiddoGet(……){

ServletContextcontext=this.getServletContext();Stringc=context.getInitParameter(“copyright”);

:}Web应用程序的初始化参数ServletContext对象3.1节一、设置Web应用程序上下文初始化参数在web.xml中,利用<context-param>标记来定义Web应用上下文参数,它包含两个子元素:<param-name>:定义上下文参数的名称<param-value>:定义上下文参数的值Web应用程序的初始化参数ServletContext对象3.1节一、设置Web应用程序上下文初始化参数Web应用程序的初始化参数ServletContext对象3.1节一、设置Web应用程序上下文初始化参数<web-app>

:

:<context-param><param-name>copyright</param-name><param-value>Copyright2004Allrightsarereserved.</param-value></context-param>

:

:</web-app>Web应用程序的初始化参数ServletContext对象3.1节二、存取Web应用程序上下文初始化参数

Servlet可通过servlet容器为Web应用程序创建的ServletContext对象来获取web.xml中所定义的上下文初始化参数。在Servlet代码中,获取ServletContext对象引用的途径有两种:

调用某Servlet对象的getServletConfig()方法,获得容器传递给本Servlet的ServletConfig对象的引用,然后通过该ServletConfig对象的getServletContext方法获得ServletContext对象的引用:

ServletConfig

config=getServletConfig();

ServletContextcontext=config.getServletContext();

直接使用HttpServlet对象的getServletContext()方法获得对ServletContext对象的引用。

ServletContextsc=getServletContext();Web应用程序的初始化参数ServletContext对象3.1节二、存取Web应用程序上下文初始化参数

获得了对ServletContext对象的引用后,我们就可以利用该对象提供的方法来访问上下文初始化参数了。ServletContext的读取上下文初始化参数的方法与Servelt读取Servlet初始化参数的方法相似。publicStringgetInitParameter(String

name)

返回由name指定的上下文初始化参数的数值,例如:

Stringcopyright=context.getInitParameter(“copyright”);

本调用将返回在web.xml文件中定义的值

"Copyright2004Allrightsarereserved."。publicjava.util.Enumeration

getInitParameterNames()ServletContext对象的方法和属性

ServletContext对象3.1节获取与服务器相关信息读写上下文初始设置参数属性设置本地资源路径相关记录日志ServletContext对象的方法和属性ServletContext对象3.1节一、获取服务器相关的信息publicStringgetServerInfo()方法

返回Servlet容器的名称和版本号,例如在JBuilder9.0默认的tomcat平台上运行的返回值是ApacheTomcat/4.0.6。

publicStringgetServletContextName()方法

返回Web应用程序的名字,这个名字在web.xml中用<display-name>元素指定。如返回“HelloworldApp”。

publicint

getMajorVersion()、publicint

getMinorVersion()方法

分别返回Web服务器所支持的JavaServletAPI的主版本号和次版本号,在Tomcat4.0.6服务器上支持的是ServletAPI2.3版本,所以前者返回2,后者返回3。ServletContext对象的方法和属性ServletContext对象3.1节二、存取Web应用程序上下文初始化参数publicStringgetInitParameter(String

name)

返回由name指定的上下文初始化参数的数值。

publicjava.util.Enumeration

getInitParameterNames()

本方法返回在web.xml中定义的所有上下文初始化参数的名字组成的枚举表。当我们不知道上下文参数的名称时可以使用本方法。ServletContext对象的方法和属性ServletContext对象3.1节三、ServletContext属性管理publicvoidsetAttribute(String

name,Object

object)

把一个对象绑定到一个用name指定名称的上下文属性上,该对象将成为ServletContext对象的一个属性,在整个Web应用范围内所有的servlet都可以用getAttribute()方法读取。例如:

ServletContextcontext=getServletContext();

context.setAttribute("category",productCategory);publicObjectgetAttribute(String

name)

返回按name指定的上下文属性的对象,如果调用之前没有使用setAttribute()方法设定name指定的属性,将返回null。例如:

ServletContextcontext=getServletContext();

CategoryproductCatory=(Category)context.getAttribute("category");publicEnumerationgetAttributeNames()

返回一个Enumeration,其中包含所有的上下文属性的名称。publicvoidremoveAttribute(String

name)

让name指定的上下文属性不可用,此后如果用getAttribute()方法返回此属性将返回null。ServletContext对象的方法和属性ServletContext对象3.1节四、与本地资源路径相关的方法

publicStringgetRealPath(String

path)

返回path指定的虚拟路径在服务器上的实际物理路径。

public.URL

getResource(Stringpath)

throws.MalformedURLException

取得由path指定的路径下的数据文件,此方法将返回一个URL对象。

publicjava.io.InputStream

getResourceAsStream(java.lang.String

path)

取得由path指定的服务器所在操作系统下的资源文件,此方法将返回一个InputStream对象。ServletContext对象的方法和属性ServletContext对象3.1节五、日志publicvoidlog(String

msg)

向Servlet日志文件写入一条消息

publicvoidlog(String

message,Throwable

throwable)

既在日志中写入一条消息,又写入Throwable异常的栈跟踪信息。

以Tomcat服务器为例,日志文件位于<Tomcat目录>\logs目录下。日志文件的命名格式为:localhost_log.<日期>.txt,例如localhost_log.2004-3-4.txt。第三章Servlet容器模型3.1ServletContext对象3.2侦听ServletContext对象的事件3.3过滤器基本概念监听ServletContext对象事件3.2节生命周期

ServletContext的生命周期与Web应用的生命周期是一致的。

事件

在ServletContext生命周期中,一般会有很多事件发生。Servlet容器对ServletContext对象的操作,如初始化、销毁、添加或删除属性等,都会触发事件。

侦听事件如果Web应用程序需要监视Servlet的上下文环境的变更,那么就需要编写一个实现ServletContextListener接口的Java类;

若监视绑定到ServletContext对象上的属性的变化,那么就需要编写一个实现ServletContextAttributeListener接口的Java类;需要用Servlet容器注册这些侦听类(即在web.xml文件中配置)ServletContextListener侦听器监听ServletContext对象事件3.2节ServletContextListener侦听器可以为Web应用部署实现ServletContextListener接口的类来达到监视Web应用程序生命周期的目的。该类称为ServletContextListener侦听器。javax.servlet.ServletContextListener接口publicvoidcontextInitialized(ServletContextEvent

sce)

在Web应用的初始化阶段,servlet容器调用ServletContextListener对象的本方法,通知侦听器ServletContext对象进入初始化阶段。publicvoidcontextDestroyed(ServletContextEvent

sce)

在Web应用的结束阶段,servlet容器会调用ServletContextListener对象的本方法,通知侦听器ServletContext对象进入销毁阶段。ServletContextListener侦听器监听ServletContext对象事件3.2节启动Servlet容器时,Servlet容器为每个包含Servlet的Web应用实例化一个ServletContext对象启动Servlet容器时,Servlet容器还根据部署描述符,为每个Web应用实例化各种侦听器。随后,容器向其下所有Web应用的ServletContextlistener侦听器发送contextInitialized事件消息。当Servlet容器关闭时,Servlet容器向容器中所有应用的ServletContextlistener侦听器发送contextDestroyed事件消息。ServletContextListener侦听器监听ServletContext对象事件3.2节ServletContextEvent对象

在上述两个事件中,容器通过传递ServletContextEvent对象来告诉侦听器发生的事件的具体信息。ServletContextEvent是一个事件类。当Web应用程序启动或关闭时,Servlet容器将事件包装成ServletContextEvent对象,并将该对象作为参数传递给ServletContext对象的侦听器类的两个方法。ServletContextEvent对象提供了一个getServletContext()方法,侦听器可以用它来获得对触发该事件的ServletContext对象的引用:

publicServletContext

getServletContext();ServletContextListener侦听器监听ServletContext对象事件3.2节publicclassContextListenerimplementsServletContextListener{publicvoidcontextInitialized(ServletContextEvent

sce){

ServletContextcontext=sce.getServletContext();

context.log(context.getServletContextName()+"initialated.");}publicvoidcontextDestroyed(ServletContextEvent

sce){

ServletContextcontext=sce.getServletContext();

context.log("context.getServletContextName()+"destroyed.");}}ServletContext的初始化事件处理函数从事件对象sce中获取当前ServletContext对象的引用调用ServletContext的log方法,将ServletContext名字写入日志。ServletContextListener侦听器监听ServletContext对象事件3.2节ServletContextListener侦听器的部署:在web.xml文件中,用<listener>元素进行定义,用<listener-class>子元素指定侦听器的实现类。Servlet容器启动时,会根据web.xml文件内容,创建一个侦听器的实例并注册该侦听器。当ServletContext发生了相应的事件时就通知侦听器进行处理。<listener>

<listener-class>

com.mycompany.servlet.ContextListener

</listener-class>

</listener>ServletContextListener侦听器监听ServletContext对象事件3.2节ServletContextListener侦听器的测试:1、在Tomcat中部署包含侦听器的Web应用;

2、启动Tomcat,则侦听器就会在日志文件中添加一行信息;

3、关闭Tomcat,侦听器同样会在日志文件中添加一行信息。:

2004-11-0211:38:50ContextLifeCycle

initialated.

:2004-11-0211:39:22ContextLifeCycledestroyed.

:当调用ServletContext对象的setAttribute()方法改变已经绑定到ServletContext对象的某个属性的值的时候,容器会调用侦听器的该方法。ServletContextAttributeListener侦听器监听ServletContext对象事件3.2节ServletContextAttributeListener侦听器ServletContext的属性是由Web应用程序中所有的servlet所共享的。为保证属性在整个Web应用范围内的一致性,有必要监视ServletContext对象的任何属性的改变。

ServletContextAttributeListener侦听器就是为了这一目的而设立的。该侦听器是一个实现了接口ServletContextAttributeListener的Java类。ServletContextAttributeListener接口publicvoidattributeAdded(ServletContextAttributeEvent

scab)publicvoidattributeRemoved(ServletContextAttributeEvent

scab)publicvoidattributeReplaced(ServletContextAttributeEvent

scab)当调用ServletContext对象的setAttribute()方法将某个属性绑定到ServletContext对象时,容器会调用侦听器的该方法。当调用ServletContext对象的removeAttribute()方法将某个属性从ServletContext对象中删除时,容器会调用侦听器的这个方法。当调用ServletContext对象的setAttribute()方法将某个属性绑定到ServletContext对象时,容器会调用侦听器的attributeAdded方法。ServletContextAttributeListener侦听器监听ServletContext对象事件3.2节当调用ServletContext对象的setAttribute()方法改变已经绑定到ServletContext对象的某个属性的值的时候,容器会调用侦听器的这个方法。当调用ServletContext对象的removeAttribute()方法将某个属性从ServletContext对象中删除时,容器会调用侦听器的这个方法。ServletContextAttributeListener侦听器监听ServletContext对象事件3.2节ServletContextAttributeEvent类

在上述三个事件中,容器通过传递ServletContextAttributeEvent对象来告诉侦听器发生的事件的具体信息。ServletContextAttributeEvent类是一个事件类。

当Servlet容器捕获对ServletContext属性的操作事件时,它将事件包装成一个ServletContextAttributeEvent对象,并将该对象作为参数传递给属性侦听器类的三个方法。ServletContextAttributeEvent类继承自ServletContextEvent类。

除了getServletContext()方法,还包含StringgetName()

返回正在创建、替换或者删除的属性的名称ObjectgetValue()

返回正在创建、替换或者删除的属性的对象值。ServletContextAttributeListener侦听器监听ServletContext对象事件3.2节publicclassContextListenerimplementsServletContextAttributeListener{publicvoidattributeAdded(ServletContextAttributeEventscab){

ServletContextcontext=scab.getServletContext();

context.log(scab.getName()+“setto"+scab.getValue().toString());}publicvoidattributeRemoved(ServletContextAttributeEventscab){

ServletContextcontext=scab.getServletContext();

context.log(scab.getName()+"removed.");}publicvoidattributeReplaced(ServletContextAttributeEventscab){

ServletContextcontext=scab.getServletContext();

context.log(scab.getName()+"replacedto"+scab.getValue().toString());}}当调用ServletContext对象的setAttribute()方法将某个属性绑定到ServletContext对象时,容器会调用侦听器的该方法。获取ServletContext对象的引用利用获得的ServletContext对象,将事件对象的信息写入日志。ServletContextAttributeListener侦听器监听ServletContext对象事件3.2节ServletContextAttributeListener侦听器的部署

在web.xml文件中,用<listener>元素进行定义,用<listener-class>子元素指定侦听器的实现类。<listener><listener-class>

com.mycompany.servlet.MyAttributeListener</listener-class></listener>第三章Servlet容器模型3.1ServletContext对象3.2侦听ServletContext对象的事件3.3过滤器应用场景一过滤器3.3节MyCompany公司在使用Tomcat网站和Servlet技术发布他们的产品。最近发现该网站的Web应用“Admin”有安全方面的设计漏洞。公司希望有一种解决方案,在所有用户访问Web应用“Admin”前,根据访问者的请求信息,对访问者的身份进行验证。

公司有以下要求:公司不打算对“Admin”本身进行重新设计,而是用“打补丁”方式完成。希望支持首先实现的身份验证方式是用户名/密码验证。但公司希望在不久的将来,可以方便地增加其他更安全的身份验证方式。可以将用户的请求信息记录到管理日志中。MySearch是一家提供搜索服务的公司,用户可以在网上访问其搜索主页http://www.MyS/Search,输入关键字表达式来搜索自己需要的资源。/Search将该表达式进行分析后转发给Google、YaHoo!等合作伙伴。公司最近使用Servlet技术将其/Search应用重新进行了设计。为了过滤掉对某些不健康关键字的搜索,公司希望为/Search应用添加请求过滤功能。应用场景二过滤器3.3节基本概念过滤器3.3节过滤器(Filter)

过滤器是Servlet2.3技术规范引入了一种新的Web应用程序组件。过滤器位于客户和基层Web应用程序之间,用于检查和修改两者之间流过的请求和响应。过滤器作为一种Web应用程序组件,可以传输或者修改用户请求与servlet响应。它可以在用户请求到达servlet之前对请求进行处理,也可以在响应离开servlet之后修改响应信息。在请求到达servlet之前,过滤器可以截取该请求并检查请求内容。除了检查之外,还可以定制请求,如修改请求标题或者请求数据等。具体的方法是对传递过来的ServletRequest对象进行操作,达到检查和修改的目的。被过滤器处理后的请求发给servletservlet执行其任务并可能产生响应。过滤器可以截获响应信息并进行修改,例如修改响应标题或者响应数据。具体的方法是通过操作servlet对象传递给它的ServletResponse对象来达到目的。处理完毕之后将修改后的响应信息发送给客户端。基本概念过滤器3.3节可以过滤的响应流在过滤器截获响应对象的时候,如果输出流被servlet关闭了,那么过滤器就不能够再改变输出流中的响应信息。因此如果需要修改响应信息,在servlet的实现代码中,应当是使用刷新输出流,而不能够关闭输出流。如:PrintWriterout=response.getPrintWriter();…out.flush();//如果希望有过滤器截获并处理响应信息,此处不能用out.close()代替out.flush()。基本概念过滤器3.3节过滤器链我们可以实现多个过滤器,这些过滤器就形成了一个“过滤器链”,过滤器链的实现与维护工作是由servlet容器负责实现的。过滤器链中不同过滤器的先后顺序是在部署文件web.xml中设定的。最先截取客户请求的过滤器将最后才能截取servlet响应信息。创建过滤器LogFilter过滤器3.3节过滤器是一个简单的Java类,它的主要特征是实现了Filter接口:packagefilters;

importjava.io.*;importjavax.servlet.*;importjavax.servlet.http.*;

publicfinalclassLogFilter

implementsFilter{

:

:

:}FilterChain参数对于正确的过滤器操作至关重要,FilterChain对象代表了多个过滤器形成的过滤器链。为了将请求/响应沿过滤器链继续传送,在每个过滤器的doFilter方法中必须调用FilterChain对象的doFilter方法。Web容器调用本方法,说明过滤器正被嵌入到Web容器中去。容器只在实例化过滤器时才会调用该方法一次。初始化方法必须在被调用做过滤工作前正确完成。容器为这个方法传递一个FilterConfig对象,其中包含着与Filter相关的配置信息。每当请求和响应经过过滤器链时,容器都要调用一次该方法。需要注意的是过滤器的一个实例可以同时服务于多个请求,因此,特别需要注意多线程的同步问题。过滤器API过滤器3.3节Filter接口所有过滤器都必须实现javax.servlet.Filter接口。该接口定义了三个方法,这三个方法分别在过滤器生命周期的不同阶段被调用:publicvoidinit(FilterConfig

filterConfig)

publicvoiddoFilter(ServletRequest

req,ServletResponse

res,FilterChain

chain)

publicvoiddestroy()过滤器的doFilter()方法实现中,任何出现在FilterChain的doFilter方法之前的代码都被看作为预处理过滤器逻辑,在这一阶段,进入的请求是可用的,可在这里对请求进行修改,但不能修改响应信息,因为Web资源的响应处理还没有发生。任何出现在FilterChain的doFilter()方法之后的代码构成了过滤器逻辑的后期处理。在这一阶段中,外发的来意Web资源的响应信息已经处理完毕,可以在这里修改响应信息。此时修改请求没有任何意义,因为请求已经处理完毕。最后被调用的方法是destroy()方法。该方法同样由servlet容器调用,指出将从服务中删除该过滤器。如果过滤器使用了其他资源,需要在这个方法中释放这些资源。过滤器API过滤器3.3节FilterConfig接口当容器对Filter对象进行初始化时,容器调用Filter的init方法,并传入一个实现FilterConfig接口的对象。Filter可使用该对象获得一些有用的信息。FilterConfig接口包含以下方法:publicStringgetFilterName()

publicStringgetInitParamter(Stringname)

publicEnumerationgetInitParamterNames()publicServletContext

getServletContext()获得过滤器的名称信息。该名称是在部署描述符中说明的。获得过滤器的初始化字符串。初始化字符串也是在部署描述符中说明的。获得一个枚举器,以遍历过滤器的所有初始化字符串。获得过滤器所在Web应用的ServletContext对象引用。过滤器API过滤器3.3节FilterChain接口对于一个Servlet,用户可以定义多个Filter。这些Filter由容器组织成一个过滤器链。在每个Filter对象中,可以使用容器传入doFilter方法的FilterChain参数引用该过滤器链。FilterChain接口定义了一个doFilter方法,用于将请求/响应继续沿链向后传送。publicvoiddoFilter(ServletRequest

req,ServletResponse

res)

实现过滤器LogFilter过滤器3.3节LogFilter的init方法的实现//保存容器传递给过滤器的FilterConfig对象FilterConfig

filterConfig=null;//过滤器生成时由容器调用publicvoidinit(FilterConfig

filterConfig)throwsServletException{

this.filterConfig=filterConfig;//保存容器传来的FilterConfig对象的引用}实现过滤器LogFilter过滤器3.3节LogFilter的Destroy方法的实现//过滤器被销毁前由容器调用该方法,释放过滤器占用的资源publicvoiddestroy(){

filterConfig=null;//过滤器销毁之前释放filterConfig对象,进行垃圾回收}LogFilter的DoFilter方法的实现

//当有请求来临时,请求通过本方法进入过滤器publicvoiddoFilter(ServletRequestrequest,ServletResponse

response,FilterChainchain)

throwsIOException,ServletException

{

longstartTime=System.currentTimeMillis();//访问时间戳

StringremoteAddress=request.getRemoteAddr();//从请求获取远程地址

StringremoteHost=request.getRemoteHost();//从请求获取远程主机名

HttpServletRequest

httpRequest=(HttpServletRequest)request;

StringreqURI=httpRequest.getRequestURI();//客户请求的资源URI

Stringbrowser=httpRequest.getHeader(“User-Agent”);//客户使用的浏览器

chain.doFilter(request,response);

longendTime=System.currentTimeMillis();

longworkTime=endTime-startTime;

ServletContextsc=filterConfig.getServletContext();

sc.log("RequestfromIP:"+remoteAddress+"("+remoteHost+")"+//写入日志

"Usingbrowser("+browser+")"+"andwantedtoaccessresource"+

reqURI+"andused"+workTime+"ms");

}对请求对象进行以下预处理逻辑:存储当前时间,表示客户请求到达的时间;从ServletRequest对象中获取客户的远程地址、远程主机名、客户请求资源的URI,然后通过读取USER-AGENT标题获得客户端浏览器的类型。预处理逻辑完成后,必须调用下游过滤器。这只需要简单的调用FilterChain对象的doFilter()方法:chain.doFilter(request,response);下游的doFilter()方法调用返回后,我们就可以处理后期逻辑了。后期逻辑处理。这时请求已经被目标servlet响应并产生了响应信息包装在ServletResponse对象中。如果有必要的话,可以在后续的代码中继续对响应信息进行处理,这时需注意,应保证不要使用Close方法将输出流关闭,而是使用Flush方法部署过滤器过滤器3.3节

在创建过滤器之后必须将它添加到部署描述符中,这样容器才会将过滤器投入到服务中去。

配置工作由两部分组成。

声明过滤器设置过滤器映射部署过滤器过滤器3.3节一、声明过滤器<filter> <filter-name>LogFilter</filter-name> <filter-class>filters.LogFilter</filter-class> <init-param>

<param-name>filterVersion</param-name> <param-value>1.0</param-value>

<init-param>

<init-param>

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论