Spring Boot cxf implementation of WebService quick start

Speaking of web services that have become popular in recent years, there is a tendency to replace traditional soap web services. However, some unique or relatively old systems still use traditional soap web services, such as airline and airline ticket query interfaces. This article mainly explains spring boot integration cxf release webservice service and spring boot integration cxf client call webservice service.

maven dependency

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <exclusions>
            <exclusion>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-tomcat</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-jetty</artifactId>
    </dependency>

    <!-- CXF webservice -->
    <dependency>
        <groupId>org.apache.cxf</groupId>
        <artifactId>cxf-spring-boot-starter-jaxws</artifactId>
        <version>3.2.4</version>
    </dependency>
    <!-- CXF webservice -->

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.hamcrest</groupId>
        <artifactId>hamcrest-all</artifactId>
        <version>1.3</version>
        <scope>test</scope>
    </dependency>
</dependencies>

Service interface

First define a simple user class User:

package com.xncoding.webservice.model;

public class User {
    private Long id;
    private String name;
    private Integer age;

    public User() {
    }

    public User(Long id, String name, Integer age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }

    // getter and setter
}

Note that the above package name is the reverse order of the targetNamespace defined by the interface below.

Create a simple service interface, define two methods, one returns a string, one returns an entity class User:

package com.xncoding.webservice.service;

import com.xncoding.webservice.model.User;

import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;

@WebService(name = "CommonService", // 暴露服务名称
        targetNamespace = "http://model.webservice.xncoding.com/"// 命名空间,一般是接口的包名倒序
)
public interface ICommonService {
    @WebMethod
    public String sayHello(@WebParam(name = "userName") String name);

    @WebMethod
    public User getUser(@WebParam(name = "userName") String name);
}

Interface implementation

Next implement this interface and write the corresponding business logic:

package com.xncoding.webservice.service.impl;

import com.xncoding.webservice.model.User;
import com.xncoding.webservice.service.ICommonService;
import org.springframework.stereotype.Component;

import javax.jws.WebService;

@WebService(serviceName = "CommonService", // 与接口中指定的name一致
        targetNamespace = "http://model.webservice.xncoding.com/", // 与接口中的命名空间一致,一般是接口的包名倒
        endpointInterface = "com.xncoding.webservice.service.ICommonService"// 接口地址
)
@Component
public class CommonServiceImpl implements ICommonService {

    
    public String sayHello(String name) {
        return "Hello ," + name;
    }

    
    public User getUser(String name) {
        return new User(1000L, name, 23);
    }
}

Configuration class

Next write the configuration class of cxf:

@Configuration
public class CxfConfig {
    @Autowired
    private Bus bus;

    @Autowired
    ICommonService commonService;

    /**
     * JAX-WS
     **/
    @Bean
    public Endpoint endpoint() {
        EndpointImpl endpoint = new EndpointImpl(bus, commonService);
        endpoint.publish("/CommonService");
        return endpoint;
    }
}

Here the Commonserviceinterface is published under the path /services/CommonService, the wsdl document path ishttp://localhost:{port}/services/CommonService?wsdl

If you want to customize the access URL of wsdl, you can customize it in application.yml:

cxf:
  path: /services  # 替换默认的/services路径

Direct Client There are two ways to access the client access

Agent factory

This method needs to get the other party's interface

@Test
public void cl1() {
    try {
        // 接口地址
        // 代理工厂
        JaxWsProxyFactoryBean jaxWsProxyFactoryBean = new JaxWsProxyFactoryBean();
        // 设置代理地址
        jaxWsProxyFactoryBean.setAddress(wsdlAddress);
        // 设置接口类型
        jaxWsProxyFactoryBean.setServiceClass(ICommonService.class);
        // 创建一个代理接口实现
        ICommonService cs = (ICommonService) jaxWsProxyFactoryBean.create();
        // 数据准备
        String userName = "Leftso";
        // 调用代理接口的方法调用并返回结果
        String result = cs.sayHello(userName);
        System.out.println("返回结果:" + result);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

Dynamic calling method 

public void cl3() {
    // 创建动态客户端
    JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();
    Client client = dcf.createClient(wsdlAddress);
    Object[] objects;
    try {
        // invoke("方法名",参数1,参数2,参数3....);
        objects = client.invoke("getUser", "张三");
        System.out.println("返回类型:" + objects[0].getClass());
        System.out.println("返回数据:" + objects[0]);
        User user = (User) objects[0];
        System.out.println("返回对象User.name=" + user.getName());
    } catch (java.lang.Exception e) {
        e.printStackTrace();
    }
}

Note that if the method returns an object, then the object's package must be in reverse order of targetNamespace.

Generate client code

This is the recommended way to generate client code based on the access path of wsdl. There are two generation methods

Apache's wsdl2java tool

wsdl2java -autoNameResolution http://xxx?wsdl

JDK comes with tools (recommended)

JDK has a built-in wsimport tool, which is the recommended way to generate.

wsimport -encoding utf-8 -p com.xncoding.webservice.client -keep http://xxx?wsdl -s d:/ws -B-XautoNameResolution

among them: 

-encoding :指定编码格式(此处是utf-8的指定格式)
-keep:是否生成Java源文件
-s:指定.java文件的输出目录
-d:指定.class文件的输出目录
-p:定义生成类的包名,不定义的话有默认包名
-verbose:在控制台显示输出信息
-b:指定jaxws/jaxb绑定文件或额外的schemas
-extension:使用扩展来支持SOAP1.2

 The above command will d:/wsgenerate the corresponding client code under the directory.

Client usage examples:

CommonService_Service c = new CommonService_Service();
com.xncoding.webservice.client.User user = c.getCommonServiceImplPort().getUser("Tom");
assertThat(user.getName(), is("Tom"));

GitHub source

springboot-cxf

Published 203 original articles · won praise 6 · views 4475

Guess you like

Origin blog.csdn.net/weixin_42073629/article/details/105609303