前言

前面我们已经整合spring-ws实现了web service的服务端:Spring Boot整合spring-ws开发web service

接下来就是实现客户端进行调用了。

添加依赖

客户端,同样的需要先添加依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-ws</artifactId>
</dependency>
<dependency>
    <groupId>wsdl4j</groupId>
    <artifactId>wsdl4j</artifactId>
</dependency>

获取wsdl文件

服务端由一个xsd文件开始,客户端则是由一个wsdl文件开始。

获取wsdl文件也十分简单,用浏览器访问web service地址,然后另存为即可。当然也可以直接用url地址来生成代码,只不过我习惯本地另存为后再生成。

完整的wsdl文件内容如下:

<wsdl:definitions 
    xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" 
    xmlns:sch="http://www.ktanx.com/ws" 
    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" 
    xmlns:tns="http://www.ktanx.com/ws" targetNamespace="http://www.ktanx.com/ws">
    <wsdl:types>
        <xs:schema 
            xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://www.ktanx.com/ws">
            <xs:element name="getCountryRequest">
                <xs:complexType>
                    <xs:sequence>
                        <xs:element name="name" type="xs:string"/>
                    </xs:sequence>
                </xs:complexType>
            </xs:element>
            <xs:element name="getCountryResponse">
                <xs:complexType>
                    <xs:sequence>
                        <xs:element name="country" type="tns:country"/>
                    </xs:sequence>
                </xs:complexType>
            </xs:element>
            <xs:complexType name="country">
                <xs:sequence>
                    <xs:element name="name" type="xs:string"/>
                    <xs:element name="population" type="xs:int"/>
                    <xs:element name="capital" type="xs:string"/>
                    <xs:element name="currency" type="tns:currency"/>
                </xs:sequence>
            </xs:complexType>
            <xs:simpleType name="currency">
                <xs:restriction base="xs:string">
                    <xs:enumeration value="GBP"/>
                    <xs:enumeration value="EUR"/>
                    <xs:enumeration value="PLN"/>
                </xs:restriction>
            </xs:simpleType>
        </xs:schema>
    </wsdl:types>
    <wsdl:message name="getCountryResponse">
        <wsdl:part element="tns:getCountryResponse" name="getCountryResponse"></wsdl:part>
    </wsdl:message>
    <wsdl:message name="getCountryRequest">
        <wsdl:part element="tns:getCountryRequest" name="getCountryRequest"></wsdl:part>
    </wsdl:message>
    <wsdl:portType name="CountriesPort">
        <wsdl:operation name="getCountry">
            <wsdl:input message="tns:getCountryRequest" name="getCountryRequest"></wsdl:input>
            <wsdl:output message="tns:getCountryResponse" name="getCountryResponse"></wsdl:output>
        </wsdl:operation>
    </wsdl:portType>
    <wsdl:binding name="CountriesPortSoap11" type="tns:CountriesPort">
        <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
        <wsdl:operation name="getCountry">
            <soap:operation soapAction=""/>
            <wsdl:input name="getCountryRequest">
                <soap:body use="literal"/>
            </wsdl:input>
            <wsdl:output name="getCountryResponse">
                <soap:body use="literal"/>
            </wsdl:output>
        </wsdl:operation>
    </wsdl:binding>
    <wsdl:service name="CountriesPortService">
        <wsdl:port binding="tns:CountriesPortSoap11" name="CountriesPortSoap11">
            <soap:address/>
        </wsdl:port>
    </wsdl:service>
</wsdl:definitions>

添加maven的jaxb2插件生成代码

跟服务端根据xsd来生成代码类似,客户端同样可以根据wsdl来生成代码。maven插件依赖:

<plugin>
    <groupId>org.jvnet.jaxb2.maven2</groupId>
    <artifactId>maven-jaxb2-plugin</artifactId>
    <version>0.12.3</version>
    <executions>
        <execution>
            <goals>
                <goal>generate</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <schemaLanguage>WSDL</schemaLanguage>
        <generatePackage>com.dexcoder.ws</generatePackage>
        <generateDirectory>${basedir}/src/main/java</generateDirectory>
        <schemas>
            <schema>
                <fileset>
                    <!-- Defaults to schemaDirectory. -->
                    <directory>${basedir}/src/main/resources/schemas</directory>
                    <!-- Defaults to schemaIncludes. -->
                    <includes>
                        <include>*.wsdl</include>
                    </includes>
                    <!-- Defaults to schemaIncludes -->
                    <!--<excludes>-->
                    <!--<exclude>*.xs</exclude>-->
                    <!--</excludes>-->
                </fileset>
                <!--<url>http://localhost:8080/ws/countries.wsdl</url>-->
            </schema>
        </schemas>
    </configuration>
</plugin>

同样mvn install之后将生成客户端代码。这里生成的代码跟我们前面发布的服务端代码应该是一样的,当然包名可能不同这个由你指定。

在生成代码的同时会生成META-INF文件夹,这个可以移到resources目录下或者直接删除都没有关系。生成后的项目结构图:

项目结构

编写ws客户端

生成了代码之后,编写客户端变的很容易,具体代码如下:

public class WsClient extends WebServiceGatewaySupport {

    public GetCountryResponse getCountry(String name) {

        GetCountryRequest request = new GetCountryRequest();
        request.setName(name);

        GetCountryResponse response = (GetCountryResponse) getWebServiceTemplate().marshalSendAndReceive(
            "http://localhost:8080/ws/countries.wsdl", request);

        return response;
    }
}

配置ws客户端

编写完一切代码之后,同样需要配置到spring boot才行,ContextPath指定刚才生成代码所在的包名,它会到该包下去寻找相应的类自动进行数据转换:

@Configuration
public class WSConfig {

    @Bean
    public Jaxb2Marshaller marshaller() {
        Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
        marshaller.setContextPath("com.dexcoder.ws");
        return marshaller;
    }

    @Bean
    public WsClient wsClient(Jaxb2Marshaller marshaller) {
        WsClient client = new WsClient();
        client.setDefaultUri("http://localhost:8080/ws/countries.wsdl");
        client.setMarshaller(marshaller);
        client.setUnmarshaller(marshaller);
        return client;
    }
}

运行

到这里所有的调用代码都已经完成了,剩下的就是运行来检测是否调用成功。

这里我们来编写一个Controller来简单测试一下。

@RestController
public class IndexController {

    @Autowired
    private WsClient wsClient;

    @RequestMapping("callws")
    public Object callWs() {
        GetCountryResponse response = wsClient.getCountry("hello");
        return response.getCountry();
    }
}

使用了RestController,直接将调用ws返回的数据用json格式输出到页面。

启动spring boot,访问http://localhost:8081/callws 这里把端口换成了8081,因为默认的8080已经被前面的服务端占用了。

可以看到成功调用了ws的服务端并返回了数据,hello部分为我们发送过去的参数:

ws客户端返回数据

你可能感兴趣的内容
Spring Boot中使用 MongoDB 3.0 收藏,4188 浏览
2条评论
Vicene 1年前

我调用的时候 报这个错误org.springframework.ws.soap.client.SoapFaultClientException: 服务器未能识别 HTTP 头 SOAPAction 的值: 。

w8875885 1年前

怎么解决的?

selfly

交流QQ群:32261424
Owner