Servlet3.1标准学习笔记三

36.在web应用中,使用注解的类仅当它们位于WEB-INF/classes目录中,或它们被打包到位于应用的WEB-INF/lib中的jar文件中时它们的注解才将被处理。
Web应用部署描述符的web-app元素包含一个新的"metadata-complete"属性。"metadata-complete"属性定义了web描述符是否是完整的,或是否应该在部署时检查jar包中的类文件和web fragments。如果“metadata-complete”设置为"true",部署工具必须忽略存在于应用类文件中的所有指定部署信息的servlet注解和web fragments。如果metadata-complete属性没有指定或设置为false,部署工具必须检查应用的类文件的主键,并扫描web fragments。
@WebServlet该注解用于在Web应用中定义Servlet组件。该注解在一个类上指定并包含声明Servlet的元数据。必须指定注解的urlPatterns或value属性。所有其他属性是可选的默认设置。当注解上唯一属性是url Patterns时推荐使用value且当也有使用其他属性时使用urlPatterns属性。在同一注解上同时使用value和urlPatterns属性是非法的。如果没有指定Servlet名字则默认是全限定类名。被注解的Servlet必须指定至少一个url模式进行部署。如果同一个Servlet类以不同的名字声明在部署描述符中,必须实例化一个新的Servlet实例。如果使用不同名字添加的同一个Servlet类使用“编程式添加和配置Servlet”的编程式API添加到ServletContext,使用@WebServlet注解声明的属性值必须被忽略,必须创建一个指定名字的Servlet的新的实例。
@WebServlet注解的类必须继承javax.servlet.http.HttpServlet类。
37.@WebFilter用于在Web应用中定义Filter。该注解在一个类上指定且包含声明过滤器的元数据。如果没有指定Filter名字则默认是全限定类名。注解的urlPatterns属性,servletNames属性或value属性必须被指定。当注解上唯一属性是url模式时推荐使用value且当有使用其他属性时使用urlPatterns属性。在同一注解上同事使用value和urlPatterns属性是非法的。
@WebFilter注解的类必须实现javax.servlet.Filter。
@WebInitParam用于指定必须传递到Servlet或Filter的任何初始化参数。它是WebServlet和WebFilter注解的一个属性。
@WebListener用来获得特定web应用上下文中的各种操作时间的监听器。
@MultipartConfig该注解当指定在Servlet上时,表示请求原文是mime/multipart类型。相应servlet的HttpServletRequest对象必须使用getParts和getPart方法遍历各个mime附件以获取mime附件。javax.servlet.annotation.MultipartConfig的location属性和<multipart-config>的<location>元素被解析为一个绝对路径且默认为javax.servlet.context.tempdir。如果指定了相对地址,它将是相对于tempdit位置。绝对路径与相对路径的测试必须使用java.io.File.isAbsolute。
当使用注解时,从WEB-INF/classes或WEB-INF/lib中的不同框架jar包/类加载监听器、Servlet的顺序是没有指定的。如果顺序是很重要的,那么请看web.xml模块部分和后面的web.xml和web-fragment.xml顺序部分。顺序仅能在部署描述符中指定。
38.web模块部署描述符片段(web fragment)是web.xml的部分或全部,可以在一个类库或框架jar包的META-INF目录指定和包括。在WEB-INF/lib目录中的普通的老的jar文件即使没有web-fragment.xml也可能被认为是一个fragment。
由于规范允许应用配置由多个配置文件组成(web.xml和web-fragment.xml)的资源,从应用中多个不同的位置发现和加载,顺序问题必须被解决。
web-fragment.xml可以有一个javaee:java-identifierType类型的顶级<name>元素,且在一个web-fragment.xml中仅能有一个<name>元素。如果存在一个<name>元素,它必须考虑用于artifact顺序(除非出现重复名异常)
39.ServletContainerInitializer和编程时注册特性可以在Servlet和JSP容器之间提供一个清晰的职责分离,通过由Servlet容器只负责解析web.xml和web-fragment.xml资源,而解析标签类库描述符(TLD)资源委托给JSP容器。
在此之前,web容器必须扫描TLD资源寻找任何Listener声明。使用Servlet3.0和后续版本后,该职责可以委托给JSP容器。JSP容器是内嵌到一个Servlet3.0兼容的Servlet容器中,可以提供它自己的ServletContainerInitializer实现,搜索传递到它的onStartup方法的ServletContext参数寻找任何TLD资源,扫描这些资源寻找Listener声明,并向ServletContext注册相关的Listener。
40.构建Web应用时,把请求转发给另一个servlet处理、或在response中包含另一个servlet的输出通常是很有用的。RequestDispatch接口提供了一种机制来实现这种功能。当请求启用异步处理时,AsyncContext允许用户将这个请求转发到servlet容器。
实现了RequestDispatcher接口的对象,可以从ServletContext中的下面方法得到:
(1)getRequestDispatcher 需要一个String类型的参数描述在ServletContext作用域内的路径。这个路径必须是相对于ServletContext的根路径,或以'/'开头,或者为空。该方法根据这个路径使用servlet路径规则来查找servlet,或者把它包装成RequestDispatcher对象并返回。如果基于给定的路径没有找到相应的servlet,那么返回这个路径内容提供的RequestDispatcher。
(2)getNamedDispatcher方法使用一个ServletContext知道的servlet名称作为参数。如果找到一个servlet,则把它包装成RequestDispatcher对象,并返回该对象。如果没有与给定名字相关的servlet,则该方法必须返回null。
ServletContext和ServletRequest中创建RequestDispatcher对象的方法使用的路径信息中允许附加可选的查询字符串信息。
要使用请求调度器,servlet可调用RequestDispatcher接口的include或forward方法。这些方法的参数既可以是javax.servlet.Servlet接口的service方法传来的request和response对象实例,也可以是request和response包装器的子类对象实例。对于后者,包装器实例必须包装容器传递到service方法中的request和response对象。
41.RequestDispatcher接口的include方法可能随时被调用。Include方法的目标servlet能够访问request对象的各个方法,但是调用response对象的方法会受到更多限制。它只能把信息写到response对象的ServletOutputStream或Writer中,或提交在最后写保留在response缓冲区中的内容,或通过显式地调用ServletResponse接口的flushBuffer方法。它不能设置响应头部信息或调用任何影响响应头部信息的方法,HttpServletRequest.getSession()和HttpServletRequest.getSession(boolean)方法除外。
如果默认的servlet是RequestDispatch.include()的目标servlet,而请求的资源不存在,那么默认的servlet必须抛出FileNotFoundException异常。如果这个异常没有被捕获和处理,以及响应还未提交,则响应状态码必须被设置为500。
42.RequestDispatcher接口的forward方法,只有在没有输出提交到客户端时,通过正在被调用的servlet调用。如果response缓冲区中存在尚未提交的输出数据,这些数据内容必须在目标servlet的service方法调用前清除。如果response已经提交,必须抛出一个IllegalStateException异常。
request对象暴露给目标servlet的路径元素(path elements)必须反映获得RequestDispatcher使用的路径。
唯一例外的是,如果RequestDispatcher是通过getNamedDispatcher方法获得。这种情况下,request对象的路径元素必须反映这些原始请求。
在RequestDispatcher接口的forward方法无异常返回前,响应的内容必须被发送和提交,且由Servlet容器关闭,除非请求处于异步模式。如果RequestDispatcher.forward()的目标发生错误,异常信息或传回所有调用它经过的过滤器和servlet,且最终传回给容器。
43.如果请求分发的目标servlet抛出运行时异常或受检查异常ServletException或IOException,异常应该传播到调用的servlet。所有其它的异常都应该包装成ServletException,异常的根本原因设置成原来的异常,因为它不应该被传播。
44.实现了AsyncContext接口的对象可从ServletRequest的一个startAsync方法中获得,一旦有了AsyncContext对象,你就能够使用它的complete()方法来完成请求处理,或使用下面描述的转发方法。
45.可以使用AsyncCont中下面的方法来转发请求:
(1)dispatch(path) 该方法的String参数描述一个在ServletContext作用域中的路径。这个路径必须是相对于ServletContext的根路径并以'/'开头。
(2)dispatch(servletContext,path)  该方法的String参数描述一个在ServletContext作用域中的路径。这个路径必须是相对于ServletContext的根路径并以'/'开头。
(3)dispatch() 这个方法没有参数,它使用原来的URI路径。如果AsyncContext已经通过startAsync(ServletRequest,ServletResponse)初始化,且传递过来的request是HttpServletRequest的实例,那么这个请求分发到HttpServletRequest.getRequestURI()返回的URI。
AsyncContext接口中的dispatch方法可被等待异步事件发生的应用程序调用。如果AsyncContext已经调用了complete方法,必须抛出IllegalStateException异常。所有不同的dispatch方法会立即返回并且不会提交response。
request对象暴露给目标servlet的路径元素必须反映AsyncContext.dispatch中指定的路径。
46.一个Web应用程序以结构化的目录层次结构存在。层次结构的根目录作为文件的归档目录,这些文件是应用的一部分。由于应用的上下文路径确定了Web应用内容的URL命名空间,Web容器必须拒绝Web应用定义的上下文路径,因为可能这个URL命名空间中导致潜在的冲突。
应用程序层次结构中存在一个名为“WEB-INF”的特殊目录。这个目录包含了与应用程序相关的所有东西,这些东西不在应用程序的归档目录中。大多数WEB-INF节点都不是应用程序公共文档树的一部分。除了静态资源和WEB-INF/lib目录下打包在JAR文件中META-INF/resources目录下的JSP文件之外,WEB-INF目录下包含的其他任何文件都不能由容器直接提供给客户端访问,然而,WEB-INF目录中的内容可以通过servlet代码调用ServletContext的getResource和getResourceAsStream方法来访问,并可使用RequestDispatcher调用公开这些内容。
WEB-INF目录中的内容有:
(1)/WEB-INF/web.xml部署描述文件。
(2)servlet和实用工具类目录/WEB-INF/classes/。此目录中类对应用程序类加载器必须是可见的。
(3)java归档文件区域/WEB-INF/lib/*.jar。这些文件中包括了sevlet,beans,静态资源和打包在JAR文件中的JSP文件,以及其他对Web应用程序有用的使用工具类。Web应用程序的加载器必须能够从这些归档文件中加载类。
Web应用程序类加载器必须先从WEB-INF/classes目录下加载类,然后从WEB-INF/lib目录下的JAR库中加载。此外,除了静态资源打包在JAR文件中的情况外,任何来自客户端的请求访问WEB-INF/目录中的资源必须返回一个SC_NOT-FOUND(404)的响应。
可以使用标准的Java归档工具把Web应用程序打包并签名到一个Web存档格式(WAR)文件中。
当打包成这种形式时,将生成一个META-INF目录,其中包含了对java归档工具有用的信息。尽管这个目录的内容可以通过servlet代码调用ServletContext的getResource和getResourceAsStream方法来访问,容器也不能把这个目录当做内容来响应客户端请求。此外,任何请求访问META-INF目录中的资源必须返回一个SC_NOT_FOUND(404)的响应。
47.容器用于加载WAR文件中servlet的类加载器必须允许开发人员使用getResource加载遵循正常JavaSE语义的WAR文件的JAR包中包含的任何资源。和Java EE许可协议中描述的一样,不属于Java EE产品的servlet容器不应该允许应用程序覆盖Java SE平台中的类。
一个类加载器的实现必须保证对部署到容器的每个web应用,调用Thread.currentThread.getContextClassLoader()返回一个实现了本节规定的约定的ClassLoader实例。此外,部署的每个Web应用程序的ClassLoader实例必须是一个单独的实例。容器必须在任何回调(包括监听器回调)到Web应用程序之前设置上面描述的线程上下文ClassLoader,一旦回调返回,需要把它设置成原来的ClassLoader。
48.在发生错误时,Web应用程序必须能够详细说明,应用程序中的其他资源被用来提供错误响应的内容主题。
49.如果Web容器接收到一个有效的局部请求,Web容器必须检查部署描述文件中定义的欢迎文件列表。欢迎文件列表是一个没有尾随或前导的局部URL有序列表。Web服务器必须把部署描述文件中按指定顺序的每个欢迎文件添加到局部请求,并检查WAR文件中的静态资源是否映射到请求URI。Web服务器必须再把部署描述文件中指定顺序的每个欢迎文件添加到局部请求,并检查servlet是否映射到请求URI。Web容器必须将请求到WAR文件中第一个匹配的资源。容器可使用转发、重定向、或容器指定的机制将请求发送到欢迎资源,这与直接请求没有什么区别。
50.当一个Web应用程序部署到容器中,在Web应用程序开始处理客户端请求之前,必须按照下述步骤顺序执行:
(1)实例化部署描述文件中<listener>元素表示的每个事件监听器的一个实例。
(2)对于已实例化的实现了ServletContextListener接口的监听器实例,调用contextInitialized()方法。
(3)实例化部署描述文件中<filter>元素标识的每个过滤器的一个实例,并调用每个过滤器实例的init()方法。
(4)包含<load-on-starup>元素的<servlet>元素,根据load-on-startup元素值定义的顺序为每个servlet实例化一个实例,并调用每个servlet实例的init()方法。
51.如果Web应用不包含任何servlet、过滤器或监听器组件或使用注解声明相同的,那么可以不需要web.xml文件。换句话说,只包含静态文件或JSP页面的应用程序不需要一个web.xml的存在。
52.Servlet事件监听器支持在ServletContext、HttpSession和ServletRequest状态改变时进行事件通知。Servlet上下文监听器是用来管理应用的资源或JVM级别持有的状态。HTTP会话监听器是用来管理从相同客户端或用户进入web应用的一系列请求管理的状态或资源。Servlet请求监听器是用来管理整个Servlet请求周期的状态。一步监听器用来管理异步事件。如超时和完成异步处理。
可以有多个监听器类监听每一个事件类型,且开发人员可以为每一个事件类型指定容器调用监听器bean的顺序。
监听器类在Web应用部署描述符中使用listener元素声明。它们根据类名列出的顺序就是它们被调用的顺序。与其他监听器不同,AsyncListener类型和监听器可能仅通过编程式注册(使用一个ServletRequest)。
Web容器创建每一个监听器类的一个实例,并在应用处理第一个请求之前为事件通知注册它。
在分布式Web容器中,HttpSession实例被限定到特定的JVM服务会话请求,且ServletContext对象被限定到Web容器所在的JVM。分布式容器不需要传播Servlet上下文事件或HttpSession事件到其他JVM。监听器类实例被限定到每个JVM的每个部署描述符声明一个。
53.在收到客户端请求时,web容器确定转发到哪一个Web应用。选择的Web应用必须具有最长的上下文路径匹配请求URL的开始。当映射到Servlet时,URL匹配的一部分是上下文。
用于映射到Servlet的路径是请求对象的请求URL减去上下文和路径参数部分。下面的URL路径映射规则按顺序使用。使用第一个匹配成功的且不会进一步尝试匹配:
(1)容器将尝试找到一个请求路径到servlet路径的精确匹配。成功匹配则选择该servlet。
(2)容器将递归地尝试匹配最长路径前缀。这是通过一次一个目录的遍历路径树完成的,使用'/'字符作为路径分隔符。最长匹配确定选择的servlet。
(3)如果URL最后一部分包含一个扩展名(如.jsp),servlet容器将视图匹配为扩展名处理请求的Servlet。扩展名定义在最后一部分的最后一个'.'字符之后。
(4)如果前三个规则都没有产生一个servlet匹配,容器将视图为请求资源提供相关的内容。如果定义中定义了一个‘default’Servlet,它将被使用。
容器必须使用区分大小写字符串的比较匹配。
在web应用部署描述符中,以下语法用于定义映射:
(1)以'/'字符开始,以'/*'后缀结尾的字符串用于路径匹配。
(2)'*.'开始的字符串用于扩展名映射。
(3)空字符串""是一个特殊的URL模式,其精确映射到应用的上下文根,即http://host:port/<context-root>/请求形式。在这种情况下,路径信息是'/'且servlet路径和上下文路径是空字符串("");
(4)只包含'/'字符的字符串表示应用的"default"servlet。在这种情况下,servlet路径请求时请求URL减去上下文路径,且路径信息时null.
(5)所有其他字符串仅用于精确匹配。
如果容器有一个内部的JSP容器,*.jsp扩展名映射到它,允许执行JSP页面的要求。该映射被称为隐式映射。如果Web应用定义了一个*.jsp映射,它的优先级高于隐式映射。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值