1

我需要将 Web 服务应用程序从 Tomcat 6(使用 JDK 1.5)迁移到 Tomcat 7(使用 JDK 1.6)(实际上是在 7.0.27 上测试)。JAX-WS 框架是 Metro 2.1。

我正在使用两个 ServletContextListener:

  1. “WebAppListener”:初始化应用程序(配置,数据库连接的设置......)。

  2. “com.sun.xml.ws.transport.http.servlet.WSServletContextListener”:创建 Web 服务的 Metro 监听器。

顺序很重要,因为我需要在我的 Web 服务上调用 @PostConstruct 方法之前完全初始化我的 Web 应用程序。

在 Tomcat 6 中,这非常有效:

INFO: Starting Servlet Engine: Apache Tomcat/6.0.36
mars 16, 2013 5:13:13 PM org.apache.catalina.startup.HostConfig deployWAR
INFO: Deploying web application archive WSWebApp.war
************************ IN WebAppListener.contextInitialized ***********************
************************ IN WSMyWebService.postConstruct ****************************

然而,在 Tomcat 7 中完全相同的战争:

mars 16, 2013 6:45:24 PM org.apache.catalina.startup.HostConfig deployWAR
INFO: Deploying web application archive C:\home\tomcat\webapps\WSWebApp.war
************************ IN WSMyWebService.postConstruct ****************************
************************ IN WebAppListener.contextInitialized ***********************

我认为调用侦听器的顺序是它们在 web.xml 中出现的顺序?

为什么在 Tomcat 7 中更改了此顺序?但更重要的是:我需要做什么才能恢复“Tomcat6”订单?

谢谢。

4

2 回答 2

3

答案在于 Servlet 规范 2.5 和 Servlet 规范 3.0 之间的区别。

Servlet 规范 2.5中,调用侦听器的顺序由它们在部署描述符 (web.xml) 中的声明顺序定义:

SRV.10.3.3 监听器注册。
Web 容器创建每个侦听器类的实例,并在应用程序处理第一个请求之前为事件通知注册它。Web 容器根据它们实现的接口以及它们在部署描述符中出现的顺序来注册监听器实例。在 Web 应用程序执行期间,侦听器按照注册的顺序被调用。

Servlet 规范 3.0中,调用侦听器的顺序由部署描述符 (web.xml) 中的元素<absolute-ordering>定义:

8.2.3 从 web.xml、webfragment.xml 和注解中组装描述符。
...
c。在此规范发布之前,上下文侦听器是以随机顺序调用的

恕我直言,这是错误的,如上面 2.5 版规范中所述。:-)

从 Servlet 3.0 开始,监听器按照它们在 web.xml 中声明的顺序被调用,如下所示
:javax.servlet.ServletContextListener 的实现在它们的 contextInitialized 方法中按照它们被声明的顺序被调用,并在它们的 contextDestroyed 方法中以相反的顺序被调用。

这根本不像你想象的那样有效,是我的麻烦、困惑和失去周末的根源。;-) 它与以前的顺序不同(2.5 规范)!

但还有更多......(AHA时刻即将到来!)

8.2.2 web.xml 和 web-fragment.xml 的排序 由于规范允许应用程序配置资源由多个配置文件(web.xml 和 web-fragment.xml)组成,从多个不同的地方发现和加载应用时,必须解决排序问题。
...
必须考虑两种情况以允许应用程序配置资源表达它们的排序偏好。
1.绝对排序: web.xml 中的<absolute-ordering>元素。一个。在这种情况下,必须忽略下面的情况 2 处理的排序首选项。
2.相对排序:一个<ordering>web-fragment.xml 中的元素。一个。web-fragment.xml 可能有一个 <ordering> 元素。如果是这样,该元素必须包含零个或一个 <before> 元素和零个或一个 <after> 元素。下面解释这些元素的含义。

所以,就我而言,我有两个选择:

  1. 坚持使用 2.5 版:这在 Tomcat 6 和 7 上运行良好,但只是将问题转移到未来。
  2. 迁移到规范的 3.0 版并相应地调整我的部署描述符:

    • 更新 web-app 元素中的版本和架构,当然:

    <web-app xmlns="http://java.sun.com/xml/ns/javaee " xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http ://java.sun.com/xml/ns/ javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd "版本 = "3.0" >

    • 添加一个 <absolute-ordering> 元素来定义监听器的处理顺序:

    <absolute-ordering> <name>bootstrap</name><name>ws</name><others/></absolute-ordering>
    <listener id="bootstrap ">
       <listener-class>lu.estiedi.ws。 WebAppBootstrap</listener-class>
    </listener>
       <listener id="ws" >
    <listener-class>com.sun.xml.ws.transport.http.servlet.WSServletContextListener</listener-class>
    </listener>

注意<others/>元素:如果它不存在,那么未命名的侦听器将不会被处理。

编辑:

这实际上并不能解决问题。它昨天在家里消失了,但今天早上在工作中解决方案不起作用。:-(

看起来 Metro 正在使用服务提供者ServletContainerInitializer,它在 Listeners 之前被调用

如果这是它应该工作的方式,那么 PosConstruct 方法总是在侦听器上的 contextInitialized 之前调用。那么,在创建 Web 服务之前,我们在哪里初始化我们的应用程序?

于 2013-03-17T14:05:39.470 回答
0

这不是关于监听器的顺序,而是关于 servlets 规范 3.0 的一个新特性,以及你可能正在使用像 METRO 这样的 JAX-WS 实现这一事实,我想。在 servlets 规范 3.0(第 8.2.4 章)中,有一种方法可以将 3rd 方插件或 API 添加到容器(在本例中为 Tomcat),例如 JAX-WS、JAX-RS、JSF 等实现。它也被称为广告 SCI (javax.servlet.ServletContainerInitializer)。简而言之,METRO JAX-WS jar 使用这种方式,因此不必在 web.xml 描述符文件中添加侦听器 (com.sun.xml.ws.transport.http.servlet.WSServletContextListener) 和 servlet 配置。它使用 sun-jaxws.xml 文件列出 ws 端点并在部署 Web 应用程序和执行之前实例化 ws 类,例如,侦听器的方法 contextInitialized。

为避免这种情况,只需按照说明在 Tomcat 中避免 SCI 机制:如何使 Tomcat 启动更快?

Context 元素上存在一个属性,containerSciFilter。它可用于禁用通过 SCI API 插入 Tomcat 的容器提供的功能:WebSocket 支持(在 Tomcat 7 及更高版本中)、JSP 支持(在 Tomcat 8 及更高版本中)。

可以通过查看 Tomcat JAR 中的 META-INF/services/javax.servlet.ServletContainerInitializer 文件来检测要过滤的类名。对于 WebSocket 支持,名称是 org.apache.tomcat.websocket.server.WsSci,对于 JSP 支持,名称是 org.apache.jasper.servlet.JasperInitializer。

它与 JAX-WS 一起为我工作,它只使用 web.xml 配置来部署 Web 服务。

于 2015-07-30T14:54:54.937 回答