【问题标题】:JAX-WS Web service on Tomcat without sun-jaxws.xml没有 sun-jaxws.xml 的 Tomcat 上的 JAX-WS Web 服务
【发布时间】:2013-05-08 10:01:35
【问题描述】:

在 Tomcat 上部署基于 JAX-WS 的 Web 服务时,我试图最小化所需的配置。随着 Servlet 3.0(Tomcat 7+ 支持)的引入,web.xml 可以被扔掉,但sun-jaxws.xml 仍然存在。这个blog post很有意思:

当然,使用 jax-ws 注解,甚至配置 sun-jaxws.xml 可以成为可选的,使其成为完全描述符 免费,但这需要指定一个默认的 url 模式,如 JSR-109 或 JAX-WS 中的 Jersey REST 服务中的自定义模式 规范。

是否可以在 Tomcat 上避免 sun-jaxws.xml,以及如何避免?

【问题讨论】:

    标签: java web-services jakarta-ee tomcat jax-ws


    【解决方案1】:

    遗憾的是,配置必须存在于某处。根据消息来源,这是强制性的。信不信由你,the location of the sun-jaxws.xml file is hard-coded 到 /WEB-INF/sun-jaxws.xml(谢谢,伙计们@Metro)。

    实际上,您需要控制以下类


    需要做什么:

    1. WSServletContextListener 显然不会被扩展。此侦听器根据 sun-jaxws.xml 和 jaxws-catalog 文件执行大部分初始化。就像我之前提到的,位置是硬编码的。所以你在这里阻力最小的路径是

      • 实现您自己的 vanilla servlet 侦听器(使用@WebListener)并调用new WSServletContextListener()。然后,您将自己的contextInitialized(ServletContext ctxt)contextDestroyed() 方法委托给WSServletContextListener 实例中的方法。

      • 使用代表 sun-jaxws 文件的 @XmlRootElement 类即时生成监听器实例化文件(我将在短时间内提供此示例,不要'现在没时间 :) )。

    IMO,这种可有可无的便利很麻烦,但理论上它应该可以工作。我会写一些样本,看看它们的播放效果。

    【讨论】:

    • +1,不知道 sun-jaxws.xml 的位置是硬编码的 :) 默认 url 模式应该使 sun-jaxws.xml 可选(请参阅我在我的问题),你知道吗?
    • @MiljenMikic 仔细阅读那篇文章,这一切似乎都是一厢情愿,没有太多参考:他博客文章中的链接已失效。我仍然设法找到了他所指的来源 herereadme.txt 仍然表明 sun-jaxws.xml 是必要的
    【解决方案2】:

    要在 Tomcat 中获得 JAX-WS 支持,您必须配置:

    • WEB-INF/sun-jaxws.xml
    • WSServletContextListener
    • WSServlet

    不幸的是,很难省略 WEB-INF/sun-jaxws.xml 文件,但由于 Servlet 3.0 API,有更简单的方法可以省略 web.xml 配置.

    你可以这样做:

    @WebServlet(name = "ServiceServlet" , urlPatterns = "/service", loadOnStartup = 1)
    public class Servlet extends WSServlet {
    
    }
    

    @WebListener
    public class Listener implements ServletContextAttributeListener, ServletContextListener {
    
        private final WSServletContextListener listener;
    
        public Listener() {
            this.listener = new WSServletContextListener();
        }
    
        @Override
        public void attributeAdded(ServletContextAttributeEvent event) {
            listener.attributeAdded(event);
        }
    
        @Override
        public void attributeRemoved(ServletContextAttributeEvent event) {
            listener.attributeRemoved(event);
        }
    
        @Override
        public void attributeReplaced(ServletContextAttributeEvent event) {
            listener.attributeReplaced(event);
        }
    
        @Override
        public void contextInitialized(ServletContextEvent sce) {
            listener.contextInitialized(sce);
        }
    
        @Override
        public void contextDestroyed(ServletContextEvent sce) {
            listener.contextDestroyed(sce);
        }
    }
    

    我已经在 Tomcat-8.5.23 版本上对其进行了测试,并且可以正常工作。但请记住,您仍然必须有 WEB-INF/sun-jaxws.xml 文件。

    <endpoints xmlns="http://java.sun.com/xml/ns/jax-ws/ri/runtime"
           version="2.0">
        <endpoint name="SampleService"
              implementation="com.ws.ServiceImpl"
              url-pattern="/service" />
    </endpoints>
    

    【讨论】:

    • 我知道我们可以省略web.xml 文件,这在问题的文本中已经提到过。问题是关于省略 sun-jaxws.xml 文件。
    • 啊,好吧,但我为其他可能不知道如何为这个问题省略 web.xml 文件的人添加了解决方案。例如,几周前我遇到了这个问题。
    • 有什么方法可以在这个xml配置中指定端口吗?
    【解决方案3】:

    我已经通过这种方式成功发布了 Web 服务。我使用 apache cfx 在 servletContextListener 中发布。

    @WebListener
    public class WebServicePublisListener implements ServletContextListener {
    
        /**
         * Default constructor. 
         */
        public WebServicePublisListener() {
            // TODO Auto-generated constructor stub
        }
    
        /**
         * @see ServletContextListener#contextInitialized(ServletContextEvent)
         */
        public void contextInitialized(ServletContextEvent sce)  { 
            JaxWsServerFactoryBean srvFactory = new JaxWsServerFactoryBean();
            srvFactory.setServiceClass(RandService.class);
            srvFactory.setAddress("/RandService");
            srvFactory.setServiceBean(new RandServiceImplement());
            srvFactory.create();
        }
    

    【讨论】:

    • 感谢您的回答。我应该用“JAX-WS RI”或“Metro”标签标记我的问题,因为sun-jaxws.xml 与这些实现有关。 Apache CXF 是 JAX-WS 的不同实现,所以它与sun-jaxws.xml 没有任何关系。
    【解决方案4】:

    您必须发布网络服务。您可以实现 ServletContextListener 并发布端点:

    @javax.servlet.annotation.WebListener 
    public class AppServletContextListener implements javax.servlet.ServletContextListener {
    
        public void contextInitialized(ServletContextEvent sce) { 
            Endpoint.publish("{protocol}://{host}:{port}/{context}/{wsName}", new MyHelloWorldWSImpl());
        } 
    
        public void contextDestroyed(ServletContextEvent sce) { 
            .... 
        }
    }
    

    sun-jaxws.xml 在规范中不是强制性的...如果您注意到,例如,glassfish (metro) 将其设为可选。此外,如果您将 EJB 3.1 公开为 Web 服务(使用 jaxws),您将在生成的构建中看不到 sun-jaxws.xml 文件。

    【讨论】:

    • 感谢您的回答。但是,我不想使用 Endpoint.publish(..) 基础架构,因为它代表了一个轻量级 HTTP 服务器——如果我想要的话,我就不会使用 Tomcat。接下来,Tomcat是一个servlet容器;换句话说,您不能在 Tomcat 上部署 EJB。我知道这在 Glassfish 中就像一个魅力,但那是因为 Glassfish 符合 JSR-109。
    • Tomcat 默认不支持 EJB。例如,您应该考虑使用 TomEE。我提到 EJB 只是为了作为一个例子来证明不需要 sun-jaxws.xml(它不是强制性的)。
    • 就个人而言,我总是更喜欢完整的应用程序服务器(例如 Glassfish)而不是 servlet 容器(例如 Tomcat)。但是,我们的客户使用 Tomcat,我很好奇是否可以简化在 Tomcat 上部署 Web 服务所需的配置。因此,我的问题专门针对 Tomcat,而不是 TomEE 或 Glassfish。
    猜你喜欢
    • 1970-01-01
    • 2012-02-18
    • 2016-06-22
    • 2010-12-16
    • 2011-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多