SpringBoot整合cxf开发WebService

865 阅读2分钟

SpringBoot整合cxf开发WebService

Apache CXF一个开源的Service框架,它实现了JCP与Web Service中一些重要标准。CXF简化了构造,集成,面 向服务架构(SOA)业务组件与技术的灵活复用。在CXF中,Service使用WSDL标准定义并能够使用各种不同的消息 格式(或binding)和网络协议(transports)包括SOAP、XML(通过HTTP或JMS)进行访问。CXF同样支持多种model 如:JAX-WS,JBI,SCA和CORBA service。CXF设计成可灵活部署到各种容器中包括Spring-based,JBI,SCA, Servlet和J2EE容器。

服务端代码

1.引入依赖

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.5.0</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>
    <!-- CXF Restful webservice -->
    <dependency>
        <groupId>org.apache.cxf</groupId>
        <artifactId>cxf-spring-boot-starter-jaxws</artifactId>
        <version>3.2.4</version>
        <exclusions>
            <!--The Bean Validation API is on the classpath but no implementation could be found-->
            <exclusion>
                <groupId>javax.validation</groupId>
                <artifactId>validation-api</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
</dependencies>

2.服务的发布

/**
 * 自动发布接口地址注解
 */
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoPublish {

    /**
     * 发布地址
     */
    String publishAddr();

}
@Component
public class PublishEndpoint implements ApplicationRunner {

    @Autowired
    private WebApplicationContext applicationConnect;
    @Autowired
    @Qualifier(Bus.DEFAULT_BUS_ID)
    private SpringBus bus;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        System.out.println("开始进行自动发布webService接口");

        String[] beanNames = applicationConnect.getBeanNamesForAnnotation(AutoPublish.class);
        for (String beanName : beanNames) {
            String publishAddr = applicationConnect.getType(beanName).getAnnotation(AutoPublish.class).publishAddr();

            EndpointImpl endpoint = new EndpointImpl(bus, applicationConnect.getBean(beanName));
            endpoint.publish(publishAddr);

            System.out.println(String.format("发布接口地址:[%s]", publishAddr));
        }

        System.out.println("weBservice接口自动发布结束");
    }
}

3.application.properties

server.port=8080
server.servlet.context-path=/demo
cxf.path=/cxf

4.新增服务接口

package com.example.demo.service;

@WebService
public interface IWebServiceTest {

    /**
     * webService测试接口
     */
    @WebMethod
    String getUserService(@WebParam(name = "name") String name);

}

5.新增服务接口实现类

package com.example.demo.service.impl;

@AutoPublish(publishAddr = "/iWebServiceTest")
@WebService(targetNamespace = "http://service.demo.example.com/")
@Component
public class IWebServiceTestImpl implements IWebServiceTest {

    @Override
    public String getUserService(String name) {
        return name + ",getUserService";
    }

}

6.验证服务发布
通过浏览器访问wsdl,wsdl路径即为发布的路径加上?wsdl
http://[127.0.0.1]:[端口号]/[server.servlet.context-path]/[cxf.path]/[@AutoPublish(publishAddr = "/iWebServiceTest")]?wsdl
例子:http://127.0.0.1:8080/demo/cxf/iWebServiceTest?wsdl
SoapUi工具测试接口,不要用localhost

客户端代码

/**
 * 模拟客户端访问测试
 * 使用httpClient访问
 */
public class ClientTest {

    public static void main(String[] args) {
        // 方式1:代理类工厂的方式,需要拿到对方的接口
        proxyFactoryMain();

        // 方式2:动态调用方式
        dynamicCallMain();
    }

    /**
     * 方式1:代理类工厂的方式,需要拿到对方的接口
     */
    public static void proxyFactoryMain() {
        try {
            // 接口地址
            String address = "http://127.0.0.1:8080/demo/cxf/IWebServiceTest?wsdl";

            // 代理工厂
            JaxWsProxyFactoryBean jaxWsProxyFactoryBean = new JaxWsProxyFactoryBean();
            // 设置代理地址
            jaxWsProxyFactoryBean.setAddress(address);
            // 设置接口类型
            jaxWsProxyFactoryBean.setServiceClass(IWebServiceTest.class);

            // 创建一个代理接口实现
            IWebServiceTest cs = (IWebServiceTest) jaxWsProxyFactoryBean.create();

            // 数据准备
            String userName = "Darby_";
            // 调用代理接口的方法调用并返回结果
            String result = cs.getUserService(userName);
            System.out.println("返回结果:" + result);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 方式2:动态调用方式
     */
    public static void dynamicCallMain() {
        // 创建动态客户端
        JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();
        Client client = dcf.createClient("http://127.0.0.1:8080/demo/cxf/IWebServiceTest?wsdl");

        // 需要密码的情况需要加上用户名和密码
        // client.getOutInterceptors().add(new ClientLoginInterceptor(USER_NAME, PASS_WORD));

        try {
            // invoke("方法名",参数1,参数2,参数3....);
            Object[] objects = client.invoke("getUserService", "Darby_");
            System.out.println("返回数据:" + objects[0]);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}