Servlet注解和可插拔性(第八篇)
文章目录
- 8.1、注解和可插拔性
- 8.1.1、@WebServlet 注解
- 8.1.2、@WebFilter (web过滤器)
- 8.1.3、@WebInitParam
- 8.1.4、@WebListener
- 8.1.5、@MultipartConfig
- 8.1.6、其他注解和约定
- 8.2、可插拔性
- 8.2.1、模块化web.xml
- 8.2.2、web.xml 和web-fragment.xml的顺序
- 8.2.3、web.xml 、web-fragment.xml和注释组装描述符
- 8.2.4、共享库/运行时可拔插性
- 8.3、JSP容器插拔性
- 8.4、处理注解和片段
8.1、注解和可插拔性
- WEB-INF/classes 目录 编译java类
- WEB-INF/lib jar库
- 兼容Servlet 3.0的注解
8.1.1、@WebServlet 注解
支持web请求,被注释类必须实现javax.servlet.http.HttpServlet
例子
// 拦截/foo 的URI @WebServlet("/foo") public class CalculatorServlet extends HttpServlet{// ... }// 注解属性, 拦截/foo 或 /bar, 实现doGet方法 @WebServlet(name="MyServlet", urlPatterns={"/foo", "/bar"}) public class SampleUsingAnnotationAttributes extends HttpServlet{public void doGet(HttpServletRequest req, HttpServletResponse res) {} }
8.1.2、@WebFilter (web过滤器)
不能同时配置value和urlPatterns属性
被@WebFilter 必须要实现javax.servlet.Filter接口
例子
@WebFilter("/foo") public class MyFilter implements Filter{public void doFilter(HttpServletRequest req, HttpServletResponse res){// 实现doFilter方法} }
8.1.3、@WebInitParam
- 初始化参数,它是WebServlet 和WebFilter的参数
8.1.4、@WebListener
web监听器,监听某些特定事件
被@WebListener修饰的类,必须实现其中一个接口
- javax.servlet.ServletContextListener
- javax.servlet.ServletContextAttributeListener
- javax.servlet.ServletRequestListener
- javax.servlet.ServletRequestAttributeListener
- javax.servlet.http.HttpSessionListener
- javax.servlet.http.HttpSessionAttributeListener
- javax.servlet.http.HttpSessionIdListener
例子
@WebListener public class MyListener implements ServletContextListener{public void contextInitialized(ServletContextEvent sce){ServletContext sc = sce.getServletContext();sc.addServlet("myServlet", "Sample servlet","foo.bar.MyServlet", null, -1);sc.addServletMapping("myServlet", new String[]{"/urlpattern/*"})} }
8.1.5、@MultipartConfig
- 如果用这个注解,需要支持mime/multipart 类型, 同时Servlet必须实现getParts和getPart方法
- 配置中属性是绝对路径,如果配置相对路径,是相对于javax.servlet.context.tempdir, 这些路径都是需要通过java.io.File.isAbsolute的方法测试。
8.1.6、其他注解和约定
- 其他全部注解都在15章
- 每个应用都有默认的首页(index.htm(1) 和 index.jsp) ,这个配置在welcome-file-list中
8.2、可插拔性
8.2.1、模块化web.xml
多个web-fragment.xml 组成一个web.xml 模块化
web-fragment.xml需要在jar的WEB-INF/lib目录下
例子
<web-fragment> <servlet><servlet-name>welcome</servlet-name><servlet-class>WelcomeServlet </servlet-class></servlet><listener><listener-class> RequestListener</listener-class> </listener> </web-fragment>
8.2.2、web.xml 和web-fragment.xml的顺序
绝对顺序 在web.xml 有且只有一个 元素
- 通过name去确定web-fragment.xml, 就算name不存在,也会处理
- 可以配置
- 重复name异常
相对顺序:web-fragment.xml有且只有一个元素
- web.xm. 和WEB-INF/classes 必须在web-fragment标识ordering元素之前执行
- 重复的name异常,需要打印错误日志,报错,部署失败,提示修复,可以使用绝对路径排序
例子
//web-fragment.xml <web-fragment><name>MyFragment1</name><ordering><after><name>MyFragment2</name></after></ordering>.... </web-fragment>// web-fragment.xml <web-fragment><name>MyFrament2</name>... </web-fragment>// web-fragment.xml <web-fragment><name>MyFrament3</name><ordering><before><others/></before></ordering> </web-fragment>// web.xml <web-app>... </web-app>
上面处理过程
web.xml MyFrament3 MyFrament2 MyFrament1
这个例子阐释一些,但不是全部,还有一些规则
在某个元素之前执行,如果others表示在web-fragment最新执行
在某个元素之后执行
(可以包含在 和 )
- 如果在包含 会排在所有元素之前,如果有多个包含,那么这些包含 顺序无法确定
- 与刚刚相反, 如果包含会排到最后,但是如果有多个包含,那么这些包含 顺序无法确定
- 在或元素中,如果存在元素,但不是其父元素中唯一的元素,则在排序过程中必须考虑该父元素中的其他元素
- 如果元素直接出现在元素内,则运行时必须确保处理顺序中的该点包括未在部分中明确命名的任何Web片段。
如果web-fragment.xml和web.xml 不存在或 表示元素没有顺序要求
如果出现循环依赖时候,需要抛出异常,部署失败,可能需要提示用户配置绝对路径
例子(absolute-ordering)
//例子1 // web.xml <web-app><absolute-ordering><name>MyFragment3</name><name>MyFragment2</name></absolute-ordering>... </web-app>在这个例子中元素执行顺序 web.xml MyFragment3 MyFragment2
其他场景例子
//例子2 片段A <after><others/><name>C</name> </after>片段B <before><others/> </before>//片段C <after><others/> </after> // 片段D 、E 没有顺序 //片段F <before><others/><name>B</name> </before>最后顺序为 web.xml, F、B、D、E、C,A
//例子3 片段 <no id/>: <after><others/> </after> <before><name>C</name> <before>片段B<before><others/></before>片段 C : 没有顺序片段 D:<after><others/></after>片段 E:<before><others/></before>片段 F: 没有顺序// 结果可能如下其中一种 B和E顺序不稳定, C,D,<noid>不稳定, 只知道,<noid/>一定在C之前 ■ B,E,F,<noid>,C,D ■ B,E,F,<noid>,D,C ■ E,B,F,<noid>,C,D ■ E,B,F,<noid>,D,C ■ E,B,F,D,<noid>,C
//例子4 片段 A <after><name> B</name> </after>片段 B:没有顺序 片段 C <before><others/> </before> 片段 D: 没有顺序//可以结果 C B D A 或 C D B A 或 C B A D
8.2.3、web.xml 、web-fragment.xml和注释组装描述符
- 在定义监听器、servlet、过滤器时候,需要定义加载顺序,如果没有定义将使用如下规则
需要指定web-fragment.xm.或web.xml顺序
如果在web.xml和web-fragment.xml存在
- Filters链 匹配的顺序是按照web.xml的配置顺序
- servlet可以延迟初始化或立即初始化,如果立即初始化,那么这个初始化的顺序是按照load-on-startup元素配置的
- 监听器在web.xml配置的调用顺序
- 监听器实现javax.servlet.ServletContextListener的contextInitialized方法和销毁方法contextDestroyed方法
- 监听器实现javax.servlet.ServletRequestLIstener的requestInitialized方法和requestDestroyed方法
- 实现javax.servlet.http.HttpSessionListener的sessionCreated 和销毁方法sessionDestroyed方法
- 实现javax.servlet.ServletContextAttributeListener, javax.servlet.ServletRequestAttributeListener, javax.servlet.HttpSessionAttributeListener 调用它对应事件将会触发
如果一个servlet配置enabled元素是禁用状态,那么这个servlet对应url-pattern将不可用
当web.xml 和 web-fragment.xml 出现冲突的时候, web.xml中元素具有最高优先级(最终有效)
如果没有配置metadata-complete元数据, 或者在描述符设置它为false,然后只能通过合并注解和描述符获取元数据, 合并规则如下:
web-fragment.xml可以配置参数作为web.xml配置使用(也就可以将web.xml部分配置移动某个web-fragment.xml中)
web-fragment具体配置参考8.2.2
如果在web.xml中设置metadata-complete = true, 那么web-fragment.xml配置将会被忽略,如果在某一个web-fragment.xml 的metadata-complete 设置为true, 那么将会忽略absolute-ordering和ordering元素,只会扫描特定的jar的注解
在metadata-complete设置true之前,web 片段都会合并到web.xml文件
在合并web片段时候,以下是认为冲突了
- 多个 元素, 有相同的 但是不同
- 多个 元素,有相同 但是有不同
冲突解决原则
- 如果在web.xml 和web-fragment.xml 发生冲突,那么web.xml具有更高的优先级
- 如果两个web-fragment.xml发生冲突,需要解决,部署失败
解决冲突之后应该采用如下附加规则
在不同web-fragment.xml 可以添加不同
元素可以声明多次,最终还是以web.xml为准
如果某个Web片段中存在一个最小出现次数为零且最大出现为1的元素,而在主web.xml中丢失了,则主web.xml将从该Web片段继承设置。 如果主web.xml和Web片段中都存在该元素,则优先于主web.xml中的配置设置。 例如,如果主web.xml和一个Web片段都声明了相同的servlet,并且该Web片段中的servlet声明指定了元素,而主web.xml中的那个则没有, 那么来自Web片段的元素将在合并的web.xml中使用。
如果web.xml定义一个servlet,并没有配置 ,在两个web-fragement分别定义一个相同的servlet,但是它们配置的是不同的,这个时候将会有一个错误抛出,不能抉择
是附加的
在web.xml 和web-fragment.xml都声明了相同的, 那么最终都以web.xml
如果在web.xml和web-fragment.xml有多个相同 最后以web.xml的f为准
如果使用同一配置多个元素,被作为一个listener对待
合并产生的web.xml仅当其所有Web片段也都标记为时,才被视为。
web-fragment中配置的顶级的 和它包含内部元素 和 都会被忽略
jsp-property-group 额外添加的,在配置静态资源(META-INF/resources目录下),推荐使用jsp-config 使用url-pattern元素,其web-fragment.xml建一个子目录,防止jsp-property-group影响根目录的jsp
对于(env-entry, ejb-ref, ejb-local-ref, service-ref, resource-ref, resource-env-ref, message-destination-ref, persistence-context-ref 和 persistence-unit-ref) 引用遵循如下规则:
- 简单来在web.xml和web-fragment.xml相同元素,以web.xml为主,例如web.xml和web-fragment.xml都声明 使用相同, 那么最终生效是web.xml中的的元素
- 如果两个web-fragment.xml定义相同元素,只能抛出异常,不能确定那个生效
- 对于web-fragment.xml的元素,这些元素会合并到web.xml
在web-fragment.xml的其他注解合并规则(@Resource, @Resources, @EJB, @EJBs, @WebServiceRef, @WebServiceRefs, @PersistenceContext, @PersistenceContexts, @PersistenceUnit, 和 @PersistenceUnits)
- 如果将资源引用注释应用于类,则它等同于定义资源,但是不等同于定义注入目标。 在这种情况下,以上规则适用于注入目标元素。
- 如果在字段上使用资源引用注释,则等效于在web.xml中定义注入目标元素。 但是,如果描述符中没有注入目标元素,则来自片段的注入目标仍将合并到上述的web.xml中。
- 另一方面,如果主web.xml中有一个注入目标,并且有一个具有相同资源名称的资源引用注释,则将其视为资源引用注释的替代。 在这种情况下,由于在描述符中指定了注入目标,因此除了覆盖资源引用注释的值之外,还将应用上面定义的规则。
如果data-source 元素被定义到两个fragment中,不存在于web.xml中,这个时候抛出异常、部署失败。
例子
web.xml 没有资源引用定义web-fragment.xml <resource-ref><resource-ref-name="foo">...<injection-target><injection-target-class>com.foo.Bar.class</injection-target-class><injection-target-name>baz</injection-target-name></injection-target></resource-ref-name> </resource-ref>// 最终结果 <resource-ref><resource-ref-name="foo">...<injection-target><injection-target-class>com.foo.Bar.class</injection-target-class><injection-target-name>baz</injection-target-name></injection-target></resource-ref-name> </resource-ref>、
web.xml <resource-ref><resource-ref-name="foo"></resource-ref-name>... </resource-ref>片段1(web-fragment.xml) <resource-ref><resource-ref-name="foo"></resource-ref-name><injection-target><injection-target-class>com.foo.Bar.class</injection-target-class><injection-target-name>baz</injection-target-name></injection-target> </resource-ref>片段2(web-fragment.xml) <resource-ref><resource-ref-name="foo"></resource-ref-name><injection-target><injection-target-class>com.foo.Bar2.class</injection-target-class><injection-target-name>baz2</injection-target-name></injection-target> </resource-ref>//最终结果 <resource-ref><resource-ref-name="foo"></resource-ref-name><injection-target><injection-target-class>com.foo.Bar2.class</injection-target-class><injection-target-name>baz2</injection-target-name></injection-target><injection-target><injection-target-class>com.foo.Bar.class</injection-target-class><injection-target-name>baz</injection-target-name></injection-target> </resource-ref>
例子
@WebServlet(urlPatterns="/MyPattern", initParams={@WebInitParam(name="ccc", value="333")}) public class com.acme.Foo extends HttpServlet{.... }web.xml <servlet><servlet-class>com.acme.Foo</servlet-class><servlet-name>Foo</servlet-name><init-param><param-name>aaa</param-name><param-value>111</param-value></init-param> </servlet><servlet><servlet-class>com.acme.Foo</servlet-class><servlet-name>Fum</servlet-name><init-param><param-name>bbb</param-name><param-value>222</param-value></init-param> </servlet> <servlet-mapping><servlet-name>Foo</servlet-name><url-pattern>/foo/*</url-pattern> </servlet-mapping> <servlet-mapping><servlet-name>Fum</servlet-name><url-pattern>/fum/*</url-pattern> </servlet-mapping> //因为使用注解没有与web.xml的servlet-name 的名称相同,相等于新增一个servlet,如下xml格式 <servlet><servlet-class>com.acme.Foo</servlet-class><servlet-name>com.acme.Foo</servlet-name><init-param><param-name>ccc</param-name><param-value>333</param-value></init-param> </servlet>//如果上面web.xml用如下替换 <servlet><servlet-class>com.acme.Foo</servlet-class><servlet-name>com.acme.Foo</servlet-name><init-param><param-name>aaa</param-name><param-value>111</param-value></init-param> </servlet> <servlet-mapping><servlet-name>com.acme.Foo</servlet-name><url-pattern>/foo/*</url-pattern> </servlet-mapping> 与注解class WebServlet 组成最终有效的文件<servlet><servlet-class>com.acme.Foo</servlet-class><servlet-name>com.acme.Foo</servlet-name><init-param><param-name>aaa</param-name><param-value>111</param-value></init-param><init-param><param-name>ccc</param-name><param-value>333</param-value></init-param> </servlet> <servlet-mapping><servlet-name>com.acme.Foo</servlet-name><url-pattern>/foo/*</url-pattern> </servlet-mapping>
8.2.4、共享库/运行时可拔插性
- HandlesTypes
- ServletContainerInitializer
8.3、JSP容器插拔性
- JSP容器处理jsp数据和TLD资源
- servlet处理请求
8.4、处理注解和片段
Servlet注解和可插拔性(第八篇)相关推荐
- java 可插拔注解_20200311 8. 注解和可插拔性
8. 注解和可插拔性 8.1 注解和可插拔性 在 web 应用中,使用注解的类仅当它们位于 WEB-INF/classes 目录中,或它们被打包到位于应用的WEB-INF/lib 中的 jar 文件中 ...
- java 可插拔注解_servlet3.1规范翻译:第8章 注解和可插拔性
servlet3.1规范翻译:第8章 注解和可插拔性 . 这是Servlet3.0的新特性之一:这是Servlet3.0的新特性之一: 通过Annotation(注解)配置Servlet之前版本的Se ...
- Tomcat 中的可插拔以及 SCI 的实现原理
Tomcat 中的可插拔以及 SCI 的实现原理 转载: 侯树成 Tomcat那些事儿 2017-09-19 引子 常用计算机的朋友一定记得, U盘,硬盘等设备流行的时候,当时对于这项技术的介绍是热插 ...
- 我心中的核心组件(可插拔的AOP)~大话开篇及目录
我心中的核心组件(可插拔的AOP)~大话开篇及目录 http://www.cnblogs.com/lori/p/3247905.html 回到占占推荐博客索引 核心组件 我心中的核心组件,核心组件就是 ...
- 用开源代码如何建立网站_建立更可插拔的开源文化
用开源代码如何建立网站 如果有一个词经常使对话充斥着开源的好处,那是选择 . 我们经常庆祝800多个Linux发行版 ,无数的台式机,应用程序,框架等等. 选择似乎是一件好事. 有趣的是,选择也是一种 ...
- 跨平台长连接组件设计及可插拔改造
背景 我们在提出开发跨平台组件之前, iOS 和 Android 客户端分别使用一套长连接组件,需要双倍的人力开发和维护:在产品需求调整上,为了在实现细节上保持一致性也具有一定的难度:Web 端与客户 ...
- 在.NET Core中三种实现“可插拔”AOP编程方式(附源码)
一看标题肯定会联想到使用动态编织的方式实现AOP编程,不过这不是作者本文讨论的重点. 本文讨论另外三种在netcore中可实现的方式,Filter(过滤器,严格意义上它算是AOP方式),Dynamic ...
- 网线重新插拔后恢复正常_生活小窍门之网线不够长怎么办,毕亚兹网线连接器轻松搞定...
很多朋友在家中装修完时候,为了整齐和方便收纳都会把每个屋中的网口和光纤输出口集中到一起,放置到网络箱中,看起来更加整齐划一,但是装修时都不会考虑到网线要预留很长,很多时候都只留了很短的一节网线,还有的 ...
- Oracle 12c 数据库可插拔体系结构
在Oracle 12c数据库中,可插拔数据库拥有一些重要的结构,这些结构和非CDB数据库的结构不同. 下面是一些要点: CDB:Container Database PDB:Pluggable Dat ...
最新文章
- 超暖心!美国消防员钻冰窟窿救狗狗
- zoj-What day is that day?
- nodejs 单元测试
- SAP ABAP Platform 1909最新版的 docker 镜像
- LeetCode450题—— 删除二叉搜索树中的节点
- java在线聊天项目ppt_基于JavaEE的在线聊天聊天.ppt
- linux系统上手工建库步骤,Linux下Oracle手工建库过程
- zabbix监控mysql内存_zabbix通过自定义脚本监控nginx,php-fpm和mysql占用内存数和进程的个数...
- python3爬虫 - cookie登录实战
- MergeSort(C++)
- iMC iNode客户端上岗证
- springboot中汉字转拼音
- 进阶-第18__深度探秘搜索技术_基于slop参数实现近似匹配以及原理剖析和相关实验
- 携程是如何做React Native优化的
- 2016年上市新SUV斯柯达kodiaq大气造型
- android类似于ios剪切框图片,不必羡慕 iOS,Android 上也有这些好用的截图处理工具...
- ABP中使用MySql数据库
- win7英文版很多软件中文显示乱码解决方案
- 图像灰度、二值化、膨胀和腐蚀(纯Java篇)
- REXROTH力士乐比例阀4WRZE25W8-220-7X/6EG24N9K31/A1D3M
热门文章
- 2020双周训练训练日志
- matlab pid buck,基于MATLAB的BUCK电路设计与PID闭环仿真
- icloud有linux客户端吗,icloud drive:Windows 版 iCloud 客户端在哪下载
- Python爱浏览器,但浏览器不爱它:如何让Python运行在浏览器上
- Android开发详解之App升级程序一点通
- 注册时要求获取手机短信码的实现(java)
- 计算机制图如何绘制太极图,太极图,如何用PS绘制太极图?
- cadence schematic composer/ADE virtuoso IC61 怎么样修改器件annotation
- 【周刊】“熊孩子”乱敲键盘攻破 Linux 桌面;500 个值得学习的 AI 开源项目;Rust 升级成为微软一级项目...
- 学海无涯!腾讯、网易必问的20道题Android面试题,已拿offer入职