1

底部的 TLDR:

根据JBossWS-cxf 用户指南,对于 Web 服务,web.xml 应包含以下内容

    <web-app xmlns="http://java.sun.com/xml/ns/j2ee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" 
    version="2.4">
        <servlet>
            <servlet-name>MyWebService</servlet-name>
            <servlet-class>com.sgb.MyWebService</servlet-class>
        </servlet>
        <servlet-mapping>
            <servlet-name>MyWebService</servlet-name>
            <url-pattern>/*</url-pattern>
        </servlet-mapping>
    </web-app>

Jboss 还期望在 WEB-INF 目录(而不是 cxf.xml)中有一个名为 jboss-cxf.xml 的描述符文件,它应该包含 jaxws:endpoint 标签,如下所示:

            <beans xmlns='http://www.springframework.org/schema/beans'
        xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' 
        xmlns:beans='http://www.springframework.org/schema/beans'
        xmlns:jaxws='http://cxf.apache.org/jaxws'
        xsi:schemaLocation='http://www.springframework.org/schema/beans 
                http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
            http://cxf.apache.org/jaxws >

        <bean id="MyWebService" class="com.sgb.MyWebService" />

        <jaxws:endpoint id="POJOEndpoint" implementor="#MyWebService" wsdlLocation="WEB-INF/wsdl/XYZ.wsdl" address="/warfilename">
            <jaxws:invoker>
                <bean class="org.jboss.wsf.stack.cxf.InvokerJSE" />
            </jaxws:invoker>
        </jaxws:endpoint>
    </beans>

然后我创建了我的服务实现类:

    package com.sgb;

    @javax.jws.WebService(... ... ... )
    public class MyWebService implements IMyWebService
    {
        public CreateResponse create(CreateRequest request)
        {
            ... ... ... <-- an instance of createService is created
            return createService.serve(request)
        }
    }

到目前为止,一切都很好。它工作正常。

但是,根据 Spring 的参考文档,为 Web 应用程序实例化应用程序上下文的便捷方法是像这样在 web.xml 中添加 ContextLoaderListener。

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/applicationContext.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

所以,我可以在我的 web.xml 中添加上面的内容,然后用@Service注释MyWebService类,并确保为组件扫描设置了包。它也应该成为春季管理的bean。

问题是,它没有。JbossWS-CXF 似乎正在实例化 MyWebService,因此未注入依赖项,从而导致空指针。

我能够以编程方式获取 applicationContextClassPathXmlApplicationContext("/WEB-INF/applicationContext.xml") 然后使用注入/创建我的依赖项appContext.getBean()

但我希望直接使用注释来注入/自动装配依赖项。

TLDR:

我目前拥有的是这个。(这个bean是由jboss而不是spring创建的):

    @javax.jws.WebService(... ... ... )
    public class MyWebService implements IMyWebService
    {
        private ApplicationContext appContext;
        public MyWebService(){
            appContext = new ClassPathXmlApplicationContext("/META-INF/spring/applicationContext-ws.xml");
        }

        public CreateResponse create(CreateRequest request)
        {
                            *** Use getBean() here to get my dependency. ***
            IXyzService createService = appContext.getBean("createService",IXyzService.class);
            return createService.serve(request)
        }
    }

我想要的是这样的:

    @javax.jws.WebService(... ... ... )
    @Service    <-- <-- <-- ** This is Spring managed bean**
    public class MyWebService implements IMyWebService
    {
        @Resource <-- <-- <-- **Dependency Injected by Spring**
        IXyzService createService;

        public CreateResponse create(CreateRequest request)
        {
            return createService.serve(request)
        }
    }

实现这一目标的最佳方法是什么???

4

1 回答 1

1

几天前我发现这确实是可能的,所以编辑我以前的答案。神奇的胶水是这样的:

@PostConstruct
public void postConstruct(){
    SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
}

总而言之,需要以下几部分:

1) 通过 web.xml 加载 spring 上下文

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath*:/META-INF/spring/appContext.xml</param-value>
</context-param>

<listener>
    <listener-class>
        org.springframework.web.context.ContextLoaderListener
    </listener-class>
</listener>

2)在实现CXF生成的接口的类中用@PostConstruct注解一个方法,如下所示:

@javax.jws.WebService(... ... ... )
public class MyWebService implements IMyWebService
{
    @Resource <-- <-- <-- **Dependency Injected by Spring**
    IXyzService createService;


    @PostConstruct
    public void postConstruct(){
        SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
    }

    public CreateResponse create(CreateRequest request)
    {
        return createService.serve(request)
    }
}

以上信息来自此链接:How to initialize Spring Framework inside CXF JAX-WS service 希望这有助于...

=== 上一个答案 ===

出色地。事实证明,它无法完成 - 据我所知,我现在使用的版本是正确的方法。

解释:

Apache CXF 可以与 Spring 一起使用,也可以不与 Spring 一起使用。

JbossCXF(在 AS 7.x 或 EAP 6.x 中)使用 CXF 作为没有 Spring 的默认 Web 服务堆栈。因此,当 Jboss 调用实现 Web 服务接口的类时(在我的示例中使用 @WebService() 注释的上面的 MyWebService,spring 容器尚未启动....就像 web.xml 或 jboss-cxf.xml 中的配置一样不允许它。

因此,需要在 SEI impl 类中手动启动 Spring 容器,因为服务类本身不能是 Spring 管理的 bean(显然)。

因此,需要使用 getBean() 方法在方法内实例化服务 bean。

一旦服务 Bean 被实例化,它们的依赖关系就会由 spring 容器自动管理,因为它们现在都是 spring 管理的 bean。

希望这可以帮助某人。

新加坡国标

于 2013-08-13T14:51:46.583 回答