没有 sun-jaxws.xml 的 Tomcat 上的 JAX-WS Web 服务

Posted

技术标签:

【中文标题】没有 sun-jaxws.xml 的 Tomcat 上的 JAX-WS Web 服务【英文标题】:JAX-WS Web service on Tomcat without sun-jaxws.xml 【发布时间】: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,以及如何避免?

【问题讨论】:

【参考方案1】:

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

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

public final class WSServletContextListener

public class WSServlet


需要做什么:

    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 仔细阅读那篇文章,这一切似乎都是一厢情愿,没有太多参考:他博客文章中的链接已失效。我仍然设法找到了他所指的来源 here 和 readme.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。

以上是关于没有 sun-jaxws.xml 的 Tomcat 上的 JAX-WS Web 服务的主要内容,如果未能解决你的问题,请参考以下文章

tomcat安装后,在“服务”中为啥没有?

eclipse里面没有tomcat 7怎么办???

Tomcat 没有响应

tomcat500没有错误日志

tomcat有没有运行成功如何查看

tomcat没有绑定到此类加载器