Tomcat apachecxf+;Spring Java配置(无XML)

Tomcat apachecxf+;Spring Java配置(无XML),tomcat,jax-ws,cxf,spring-java-config,Tomcat,Jax Ws,Cxf,Spring Java Config,尝试使用Tomcat7Maven插件和CXF部署JAX-WS端点 2.7.8. 作为一个优先事项,我不希望有任何XML配置 Spring或CXF。我看到一些使用cxfservlet.xml 和CXFServlet,但没有一个完全使用Java配置。查看CXFServlet源代码,它会查找CXFServlet.xml或servlet上下文中键'config-location'下的任何内容。我尝试以编程方式注册端点,而不是在cxfservlet.xml中注册,但它不起作用;当访问服务时,我得到了404

尝试使用Tomcat7Maven插件和CXF部署JAX-WS端点 2.7.8. 作为一个优先事项,我不希望有任何XML配置 Spring或CXF。我看到一些使用
cxfservlet.xml
和CXFServlet,但没有一个完全使用Java配置。查看CXFServlet源代码,它会查找
CXFServlet.xml
或servlet上下文中键
'config-location'
下的任何内容。我尝试以编程方式注册端点,而不是在
cxfservlet.xml
中注册,但它不起作用;当访问服务时,我得到了404。有什么想法吗

@Configuration
@ImportResource({ "classpath:META-INF/cxf/cxf.xml" })
public class CXFConfig {
    @Autowired
    Bus cxfBus;

    // More code

    @Bean
    public Endpoint calculator() {
        EndpointImpl endpoint = new EndpointImpl(cxfBus, new Calculator());
        endpoint.setAddress("/CalculatorService");
        return endpoint;
    }
}

所需要的只是上面的
endpoint.publish()
调用。

我相信,如果您将bean传递到factory.setServiceBeans中,它就会工作

package br.com.app.spring;

import java.util.Arrays;

import javax.ws.rs.ext.RuntimeDelegate;

import org.apache.cxf.bus.spring.SpringBus;
import org.apache.cxf.endpoint.Server;
import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;
import org.codehaus.jackson.jaxrs.JacksonJsonProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;

import br.com.app.JaxRsApiApplication;
import br.com.app.services.EditionRest;
import br.com.app.services.EditionService;

@Configuration
@ImportResource(
    { 
        "classpath:META-INF/cxf/cxf.xml", 
        "classpath:META-INF/cxf/cxf-extension-xml.xml",
        "classpath:META-INF/cxf/cxf-servlet.xml" 
    })
public class CXFConfig {

@Bean(destroyMethod = "shutdown")
public SpringBus cxf() {
    return new SpringBus();
}

@Bean
public EditionService editionRest() {
    return new EditionRest();
}

@Bean
public JaxRsApiApplication jaxRsApiApplication() {
    return new JaxRsApiApplication();
}

@Autowired
@Bean
public Server jaxRsServer(JacksonJsonProvider provider) {

    JAXRSServerFactoryBean factory = RuntimeDelegate.getInstance().createEndpoint(jaxRsApiApplication(), JAXRSServerFactoryBean.class);
    factory.setServiceBeans(Arrays.<Object> asList(editionRest()));
    factory.setProviders(Arrays.<Object> asList(provider));

    return factory.create();
}

@Bean
public JacksonJsonProvider jsonProvider() {
    return new JacksonJsonProvider();
}
}
package br.com.app.spring;
导入java.util.array;
导入javax.ws.rs.ext.RuntimeDelegate;
导入org.apache.cxf.bus.spring.SpringBus;
导入org.apache.cxf.endpoint.Server;
导入org.apache.cxf.jaxrs.JAXRSServerFactoryBean;
导入org.codehaus.jackson.jaxrs.JacksonJsonProvider;
导入org.springframework.beans.factory.annotation.Autowired;
导入org.springframework.context.annotation.Bean;
导入org.springframework.context.annotation.Configuration;
导入org.springframework.context.annotation.ImportResource;
导入br.com.app.JaxRsApiApplication;
导入br.com.app.services.EditionRest;
导入br.com.app.services.EditionService;
@配置
@进口来源(
{ 
“类路径:META-INF/cxf/cxf.xml”,
“classpath:META-INF/cxf/cxf extension xml.xml”,
“类路径:META-INF/cxf/cxf servlet.xml”
})
公共类CXFConfig{
@Bean(destromethod=“shutdown”)
公共SpringBus cxf(){
返回新的SpringBus();
}
@豆子
公共编辑服务编辑REST(){
返回新的EditionRest();
}
@豆子
公共JAXSAPIApplication JAXSAPIApplication(){
返回新的JAXSRPIApplication();
}
@自动连线
@豆子
公共服务器JAXRServer(JacksonJsonProvider提供程序){
JAXRSServerFactoryBean工厂=RuntimeDelegate.getInstance().createEndpoint(JAXRSPIApplication(),JAXRSServerFactoryBean.class);
setServiceBeans(Arrays.asList(editionRest());
setProviders(Arrays.asList(provider));
返回factory.create();
}
@豆子
公共JacksonJsonProvider jsonProvider(){
返回新的JacksonJsonProvider();
}
}

这个线程肯定让我走上了让CXF在纯Spring Java配置中运行的正确道路,但它没有提供所需的一切

就我个人而言,纯Java配置意味着没有
web.xml
文件,我认为这个答案假设存在。例如,SpringBoot不使用
web.xml
文件

因此,要在不使用任何XML文件的情况下注册CXF端点,您需要一个配置文件,该文件还将加载
CXFServlet

import org.apache.cxf.Bus;
import org.apache.cxf.jaxws.EndpointImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;

import javax.xml.ws.Endpoint;

@Configuration
@ImportResource({"classpath:META-INF/cxf/cxf.xml"})
public class JavaConfiguration {

    @Autowired
    private Bus bus;

    @Bean
    public Endpoint myServiceEndpoint() {
        EndpointImpl endpoint = new EndpointImpl(bus, new MyService());
        endpoint.publish("/myservice");
        return endpoint;
    }

    @Bean
    public ServletRegistrationBean cxfServlet() {
        ServletRegistrationBean servlet = new ServletRegistrationBean(new CXFServlet(), "/services/*");
        servlet.setLoadOnStartup(1);
        return servlet;
    }
}
以上是在Spring中成功加载CXF端点所需的所有配置


我还创建了一个示例来演示这一点。

这里发布的所有内容都不是100%免费的XML配置-所有帖子都使用类路径:META-INF/cxf/cxf.XML,这也在web上的大多数教程中使用。但是有一个解决方案:将org.apache.cxf.bus.spring.SpringBus定义为@Bean,并配置name=bus.DEFAULT\u bus\u ID,从org.apache.cxf.bus提交

如其他答案中所述,必须实例化org.apache.cxf.jaxws.EndpointImpl,包括bean SpringBus和SEI实现类的转发。此外,必须调用EndpointImpl的publish()方法,包括包含URL结尾的字符串:

package de.jonashackt.tutorial.configuration;

import javax.xml.ws.Endpoint;

import org.apache.cxf.Bus;
import org.apache.cxf.bus.spring.SpringBus;
import org.apache.cxf.jaxws.EndpointImpl;
import org.apache.cxf.transport.servlet.CXFServlet;
import org.springframework.boot.context.embedded.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import de.codecentric.namespace.weatherservice.WeatherService;
import de.jonashackt.tutorial.endpoint.WeatherServiceEndpoint;

@Configuration
public class WebServiceConfiguration {

    @Bean
    public ServletRegistrationBean dispatcherServlet() {
        return new ServletRegistrationBean(new CXFServlet(), "/soap-api/*");
    }

    @Bean(name = Bus.DEFAULT_BUS_ID)
    public SpringBus springBus() {
        return new SpringBus();
    }    

    @Bean
    public WeatherService weatherService() {
        return new WeatherServiceEndpoint();
    }

    @Bean
    public Endpoint endpoint() {
        EndpointImpl endpoint = new EndpointImpl(springBus(), weatherService());
        endpoint.publish("/WeatherSoapService");
        return endpoint;
    }
}

如果您想了解有关Apache CXF和SpringBoot的更多信息,我建议您看看。

如果您使用的是Spring Boot,您可以使用:

<dependency>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-spring-boot-starter-jaxws</artifactId>
    <version>${cxf.version}</version> <!-- 3.1.7 or higher -->
</dependency>

.

@harmeething虽然我没有尝试过,但您是否尝试过创建另一个返回端点的方法?关于注册
CXFServlet
,您是对的。我确实注册了它,但与CXF配置不在同一位置,因此在我的回答中没有显示它。web.xml的SpringJava替代方案与CXF无关,如果您需要更多配置,您将无法像上面所做的那样。web.xml的Spring替代方案是
AbstractAnnotationConfigDispatchersServletInitializer
——如何做到这一点。但您正在将xml导入Java中……这是什么“纯Java”?这取决于您所说的“无xml”。最初的文章是关于在不编写XML的情况下配置Java客户机的;没有人说过不通过Java配置导入XML。导入
cxf.xml
可以使客户端不必编写额外的代码,我更喜欢在代码中这样做。对我来说,“无xml”意味着从Spring 4.x(包括Spring Boot)开始使用Java配置来定义bean。xml通过Spring的xml配置定义bean。顺便说一句:导入cxf.xml并声明一个自动连线Bean需要3行代码-与“无xml”方法相同:)导入源代码({“classpath:META-INF/cxf/cxf.xml})怎么样?3行代码?@AbhijitSarkar
无JavaConfig
意味着
无xml
。。。在
cxf.xml
中定义Spring bean显然会取消该示例的资格。另一方面,如果使用Spring,那么Web服务可能已经使用了自动连接/注入,因此最好使用@Controller注释/声明WeatherService,并将其作为参数注入endpoint()。@Abhijit我不同意。如果在提出问题时不存在解决方案,那么为旧问题添加新答案没有什么错。另外,
cxf-spring-boot-starter-jaxws
的存在表明人们确实将cxf与boot一起使用。
import javax.xml.ws.Endpoint;
import org.apache.cxf.Bus;
import org.apache.cxf.jaxws.EndpointImpl;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class WebServiceConfig {

    @Bean
    public Endpoint endpoint(Bus cxfBus) {
        EndpointImpl endpoint = new EndpointImpl(cxfBus, new Calculator());
        endpoint.publish("/CalculatorService");
        return endpoint;
    }
}