zoukankan      html  css  js  c++  java
  • 翻译-使用Spring调用SOAP Web Service

    原文链接: http://spring.io/guides/gs/consuming-web-service/

    调用SOAP web service

    本指南将指导你使用Spring调用一个基于SOAP的web service的整个过程。

    指南内容

    你将构建一个客户端,使用SOAP用来从远端的基于WSDL的web service获取天气数据。请访问http://wiki.cdyne.com/index.php/CDYNE_Weather进一步获取该天气服务的信息。

    该服务根据邮编返回天气预测。你可以使用自己的邮编。

    准备事项

    • 大约15分钟

    • 钟爱的编辑器或IDE

    • JDK1.6或更高版本

    • Gradle 1.11+ 或 Maven 3.0+

    • 你也可以直接参阅该指南导入代码,或通过Spring工具集(Spring Tool Suite,简称STS)通过网页浏览代码,从而帮助你学习该章节内容。源码下载地址:https://github.com/spring-guides/gs-consuming-web-service.git

    如何完成该指南

    如同大多数的示例教程一样,你可以从头开始并完成每个步骤,或者你也可以跳过已经熟悉的基础章节。无论怎样,最终你要得到可以工作的代码。

    从头开始,请移动到使用Gradle构建章节。

    跳过基础部分,请做以下事情:

    • 下载并解压该向导的源代码,或者使用Git复制一份: git clone https://github.com/spring-guides/gs-consuming-web-service.git

    • 切换到gs-consuming-web-service/initial

    • 跳到基于WSDL生成领域对象章节。

    当完成后,你可以使用gs-consuming-web-service/complete目录中的代码检查你的结果。

    使用Gradle构建

    首先你要设置一个基本的build脚本。当构建Spring应用程序时,你可以使用任何构建系统,但是这里只包括了使用MavenGradle的代码。如果你两者都不熟悉,请访问使用Gradle构建Java项目使用Maven构建Java项目

    创建目录结构

    在你选择的存放项目的目录中,创建如下的子目录结构。例如,在*nix系统中使用mkdir -p src/main/java/hello

    1
    2
    3
    4
    
    └── src
        └── main
            └── java
                └── hello
    

    创建Gradle 构建文件

    下面是一个初始的Gradle build文件

    build.gradle
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    
    configurations {
        jaxb
    }
    
    buildscript {
        repositories {
            maven { url "http://repo.spring.io/libs-release" }
            mavenLocal()
            mavenCentral()
        }
        dependencies {
            classpath("org.springframework.boot:spring-boot-gradle-plugin:1.1.6.RELEASE")
        }
    }
    
    apply plugin: 'java'
    apply plugin: 'eclipse'
    apply plugin: 'idea'
    apply plugin: 'spring-boot'
    
    repositories {
        mavenLocal()
        mavenCentral()
        maven { url 'http://repo.spring.io/libs-release' }
    }
    
    // tag::wsdl[]
    task genJaxb {
        ext.sourcesDir = "${buildDir}/generated-sources/jaxb"
        ext.classesDir = "${buildDir}/classes/jaxb"
        ext.schema = "http://wsf.cdyne.com/WeatherWS/Weather.asmx?wsdl"
    
        outputs.dir classesDir
    
        doLast() {
            project.ant {
                taskdef name: "xjc", classname: "com.sun.tools.xjc.XJCTask",
                        classpath: configurations.jaxb.asPath
                mkdir(dir: sourcesDir)
                mkdir(dir: classesDir)
    
                xjc(destdir: sourcesDir, schema: schema,
                        package: "hello.wsdl") {
                    arg(value: "-wsdl")
                    produces(dir: sourcesDir, includes: "**/*.java")
                }
    
                javac(destdir: classesDir, source: 1.6, target: 1.6, debug: true,
                        debugLevel: "lines,vars,source",
                        classpath: configurations.jaxb.asPath) {
                    src(path: sourcesDir)
                    include(name: "**/*.java")
                    include(name: "*.java")
                }
    
                copy(todir: classesDir) {
                    fileset(dir: sourcesDir, erroronmissingdir: false) {
                        exclude(name: "**/*.java")
                    }
                }
            }
        }
    }
    // end::wsdl[]
    
    dependencies {
        compile("org.springframework.boot:spring-boot-starter")
        compile("org.springframework.ws:spring-ws-core")
        compile(files(genJaxb.classesDir).builtBy(genJaxb))
    
        jaxb "com.sun.xml.bind:jaxb-xjc:2.1.7"
    }
    
    jar {
        from genJaxb.classesDir
    }
    
    task wrapper(type: Wrapper) {
        gradleVersion = '1.11'
    }
    
    task afterEclipseImport {
        dependsOn genJaxb
    }
    

    Spring Boot gradle插件提供了很多便利的特性:

    • 将classpath中的所有jar包构建单个可运行的jar包,从而更容易执行和传播服务。

    • 搜索public static void main()方法并标记为可运行的类。

    • 提供了一个内置的依赖管理器,设置依赖版本以匹配Spring Boot依赖。你可以覆盖为任何你希望的版本,但默认会使用Boot选择的版本。

    使用Maven构建

    首先你需要设置一个基本的构建脚本。你可以使用任何构建系统来构建Spring应用程序,但这里包含了Maven的代码。如果你对Maven不熟,请访问使用Maven构建Java项目

    创建目录结构

    在你选择的存放项目的目录中,创建如下的子目录结构。例如,在*nix系统中使用mkdir -p src/main/java/hello

    1
    2
    3
    4
    
    └── src
        └── main
            └── java
                └── hello
    
    pom.xml
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    
    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>org.springframework</groupId>
        <artifactId>gs-consuming-web-service</artifactId>
        <version>0.1.0</version>
    
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>1.1.6.RELEASE</version>
        </parent>
    
        <properties>
            <!-- use UTF-8 for everything -->
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.ws</groupId>
                <artifactId>spring-ws-core</artifactId>
            </dependency>
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>2.3.2</version>
                </plugin>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
                <!-- tag::wsdl[] -->
                <plugin>
                    <groupId>org.jvnet.jaxb2.maven2</groupId>
                    <artifactId>maven-jaxb2-plugin</artifactId>
                    <executions>
                        <execution>
                            <goals>
                                <goal>generate</goal>
                            </goals>
                        </execution>
                    </executions>
                    <configuration>
                        <schemaLanguage>WSDL</schemaLanguage>
                        <generatePackage>hello.wsdl</generatePackage>
                        <forceRegenerate>true</forceRegenerate>
                        <schemas>
                            <schema>
                                <url>http://wsf.cdyne.com/WeatherWS/Weather.asmx?wsdl</url>
                            </schema>
                        </schemas>
                    </configuration>
                </plugin>
                <!-- end::wsdl[] -->
            </plugins>
        </build>
    
        <repositories>
            <repository>
                <id>spring-releases</id>
                <name>Spring Releases</name>
                <url>http://repo.spring.io/libs-release</url>
            </repository>
        </repositories>
        <pluginRepositories>
            <pluginRepository>
                <id>spring-releases</id>
                <url>http://repo.spring.io/libs-release</url>
            </pluginRepository>
        </pluginRepositories>
    
    </project>
    

    注意:你可能注意到我们指定了maven-complier-plugin的版本。通常并不推荐这样做。这里主要是为了解决我们的CI系统默认运行在该插件的早期版本(java5之前)的一个问题。

    Spring Boot Maven插件提供了很多便利的特性:

    • 将classpath中的所有jar包构建单个可运行的jar包,从而更容易执行和传播服务。

    • 搜索public static void main()方法并标记为可运行的类。

    • 提供了一个内置的依赖管理器,设置依赖版本以匹配Spring Boot依赖。你可以覆盖为任何你希望的版本,但默认会使用Boot选择的版本。

    使用Spring工具集构建

    如果你拥有Spring工具集,只需简单的直接导入该指南

    注意:如果你阅读过生成SOAP web service,你可能会疑惑为什么该指南没有使用spring-boot-starter-ws?这是因为Spring Boot Starter只用于服务器端程序。Starter提供了诸如嵌入式Tomcat等功能,而服务调用则不需要这些。

    基于WSDL生成领域对象

    SOAP web service的接口描述在WSDL文件中。JAXB提供了一个简单的方式来从WSDL(或者WSDL中包含在<Types/>节点中的XSD)生成Java类。可以访问http://wsf.cdyne.com/WeatherWS/Weather.asmx?wsdl获取该天气服务的WSDL。

    你需要下列插件来使用maven从WSDL生成Java类:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    
    <plugin>
        <groupId>org.jvnet.jaxb2.maven2</groupId>
        <artifactId>maven-jaxb2-plugin</artifactId>
        <executions>
            <execution>
                <goals>
                    <goal>generate</goal>
                </goals>
            </execution>
        </executions>
        <configuration>
            <schemaLanguage>WSDL</schemaLanguage>
            <generatePackage>hello.wsdl</generatePackage>
            <forceRegenerate>true</forceRegenerate>
            <schemas>
                <schema>
                    <url>http://wsf.cdyne.com/WeatherWS/Weather.asmx?wsdl</url>
                </schema>
            </schemas>
        </configuration>
    </plugin>
    

    该代码将通过指定的WSDL的URL生成类,并放置在hello.wsdl包中。

    你也可以使用下列代码在Gradle中完成同样的事:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    
    task genJaxb {
        ext.sourcesDir = "${buildDir}/generated-sources/jaxb"
        ext.classesDir = "${buildDir}/classes/jaxb"
        ext.schema = "http://wsf.cdyne.com/WeatherWS/Weather.asmx?wsdl"
    
        outputs.dir classesDir
    
        doLast() {
            project.ant {
                taskdef name: "xjc", classname: "com.sun.tools.xjc.XJCTask",
                        classpath: configurations.jaxb.asPath
                mkdir(dir: sourcesDir)
                mkdir(dir: classesDir)
    
                xjc(destdir: sourcesDir, schema: schema,
                        package: "hello.wsdl") {
                    arg(value: "-wsdl")
                    produces(dir: sourcesDir, includes: "**/*.java")
                }
    
                javac(destdir: classesDir, source: 1.6, target: 1.6, debug: true,
                        debugLevel: "lines,vars,source",
                        classpath: configurations.jaxb.asPath) {
                    src(path: sourcesDir)
                    include(name: "**/*.java")
                    include(name: "*.java")
                }
    
                copy(todir: classesDir) {
                    fileset(dir: sourcesDir, erroronmissingdir: false) {
                        exclude(name: "**/*.java")
                    }
                }
            }
        }
    }
    

    由于gradle还没有jaxb插件,所以它调用了一个ant任务,代码看起来比maven稍显复杂。 在maven和gradle两个示例中,JAXB领域对象生成过程被包括在构建工具的生命周期中,所以无需额外步骤来运行。

    创建天气服务客户端

    创建一个web service客户端,你只需要扩展WebServiceGatewaySupport类并编写操作代码:

    src/main/java/hello/WeatherClient.java
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    
    package hello;
    
    import java.text.SimpleDateFormat;
    
    import org.springframework.ws.client.core.support.WebServiceGatewaySupport;
    import org.springframework.ws.soap.client.core.SoapActionCallback;
    
    import hello.wsdl.Forecast;
    import hello.wsdl.ForecastReturn;
    import hello.wsdl.GetCityForecastByZIP;
    import hello.wsdl.GetCityForecastByZIPResponse;
    import hello.wsdl.Temp;
    
    public class WeatherClient extends WebServiceGatewaySupport {
    
        public GetCityForecastByZIPResponse getCityForecastByZip(String zipCode) {
            GetCityForecastByZIP request = new GetCityForecastByZIP();
            request.setZIP(zipCode);
    
            System.out.println();
            System.out.println("Requesting forecast for " + zipCode);
    
            GetCityForecastByZIPResponse response = (GetCityForecastByZIPResponse) getWebServiceTemplate().marshalSendAndReceive(
                    request,
                    new SoapActionCallback(
                            "http://ws.cdyne.com/WeatherWS/GetCityForecastByZIP"));
    
            return response;
        }
    
        public void printResponse(GetCityForecastByZIPResponse response) {
            ForecastReturn forecastReturn = response.getGetCityForecastByZIPResult();
    
            if (forecastReturn.isSuccess()) {
                System.out.println();
                System.out.println("Forecast for " + forecastReturn.getCity() + ", "
                        + forecastReturn.getState());
    
                SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
                for (Forecast forecast : forecastReturn.getForecastResult().getForecast()) {
                    System.out.print(format.format(forecast.getDate().toGregorianCalendar().getTime()));
                    System.out.print(" ");
                    System.out.print(forecast.getDesciption());
                    System.out.print(" ");
                    Temp temperature = forecast.getTemperatures();
                    System.out.print(temperature.getMorningLow() + "u00b0-"
                            + temperature.getDaytimeHigh() + "u00b0 ");
                    System.out.println();
                }
            } else {
                System.out.println("No forecast received");
            }
        }
    
    }
    

    该客户端包含了两个方法。getCityForecastByZip用于实际的SOAP交换;printResponse打印收到的响应结果。我们重点关注第一个方法。

    在该方法中,GetCityForecastByZIPGetCityForecastByZIPResponse类衍生于WSDL中,被前一个步骤描述过的JAXB生成。该方法创建了GetCityForecastByZIP请求对象并设置了zipCode参数。打印出邮编后,使用WebServiceGatewaySupport基类提供的WebServiceTemplate来进行实际的SOAP交换。它传入GetCityForecastByZIP请求对象,以及一个SoapActionCallback来传入SOAPAction头,因为WSDL说明其需要在<soap:operation/>元素中使用该头。该方法将返回值转换为GetCityForecastByZIPResponse对象,然后返回该对象。

    配置web service组件

    Spring WS使用了Spring框架的OXM模块。该模块拥有Jaxb2Marshaller类来序列化和反序列化XML请求。

    src/main/java/hello/WeatherConfiguration.java
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    
    package hello;
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.oxm.jaxb.Jaxb2Marshaller;
    
    @Configuration
    public class WeatherConfiguration {
    
        @Bean
        public Jaxb2Marshaller marshaller() {
            Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
            marshaller.setContextPath("hello.wsdl");
            return marshaller;
        }
    
        @Bean
        public WeatherClient weatherClient(Jaxb2Marshaller marshaller) {
            WeatherClient client = new WeatherClient();
            client.setDefaultUri("http://wsf.cdyne.com/WeatherWS/Weather.asmx");
            client.setMarshaller(marshaller);
            client.setUnmarshaller(marshaller);
            return client;
        }
    
    }
    

    marshaller被指向了生成的领域对象集合,将使用这些对象来实现XML和POJO之间的序列化和反序列化。

    我们使用了上面显示的天气服务URI创建和配置了weatherClient。他也被配置使用JAXB marshaller。

    生成可执行的应用程序

    该应用程序被打包后可运行与命令行,传入一个邮编则会得到一个天气预报。

    src/main/java/hello/Application.java
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    
    package hello;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.context.ApplicationContext;
    
    import hello.wsdl.GetCityForecastByZIPResponse;
    
    public class Application {
    
        public static void main(String[] args) {
            ApplicationContext ctx = SpringApplication.run(WeatherConfiguration.class, args);
    
            WeatherClient weatherClient = ctx.getBean(WeatherClient.class);
    
            String zipCode = "94304";
            if (args.length > 0) {
                zipCode = args[0];
            }
            GetCityForecastByZIPResponse response = weatherClient.getCityForecastByZip(zipCode);
            weatherClient.printResponse(response);
        }
    
    }
    

    main()方法调用了SpringApplication辅助方法,并向其run()方法传入了WeatherConfiguration.class参数。这会使Spring从WeatherConfiguration中读取注解元数据,并作为Spring应用程序上下文中的一个组件进行管理。

    注意:该应用程序硬编码了邮编94304,Palo Alto, CA。在该指南的最后,你可以看到如何添加不同的邮编而不用修改代码。

    构建可执行的jar包

    你可以创建一个包含所有必须的依赖,类,及资源的可执行的JAR文件。这很方便传输,版本管理以及独立于部署生命周期来部署服务,跨不同的环境,诸如此类。

    1
    
    gradlew build
    

    然后你可以运行WAR文件:

    1
    
    java -jar build/libs/gs-consuming-web-service-0.1.0.jar
    

    如果你使用的是maven,你可以使用mvn spring-boot:run来运行程序,或者你可以使用mvn clean package构建JAR文件,并使用下面命令来运行:

    1
    
    java -jar target/gs-consuming-web-service-0.1.0.jar
    

    注意:上面的产出物是一个可运行JAR文件。你也可以创建一个经典的WAR文件。 

    运行服务

    如果使用的是Gradle,可以使用以下命令来运行服务:

    1
    
    gradlew clean build && java -jar build/libs/gs-consuming-web-service-0.1.0.jar
    

    注意:如果你使用的是Maven,可以使用以下命令来运行服务:mvn clean package && java -jar target/gs-consuming-web-service-0.1.0.jar

    你也可以通过Gradle直接运行该程序:

    1
    
    gradlew bootRun
    

    注意:使用mvn的话,命令是mvn spring-boot:run

    可以看到日志输出。该服务应该在几秒钟内启动并运行起来。

    1
    
    Requesting forecast for94304ForecastforPaloAlto, CA2013-01-03PartlyCloudy°-57°2013-01-04PartlyCloudy41°-58°2013-01-05PartlyCloudy41°-59°2013-01-06PartlyCloudy44°-56°2013-01-07PartlyCloudy41°-60°2013-01-08PartlyCloudy42°-60°2013-01-09PartlyCloudy43°-58°
    

    你也可以使用不同的邮编:java -jar build/libs/gs-consuming-web-service-0.1.0.jar 34769

    1
    
    Requesting forecast for34769ForecastforSaintCloud, FL2014-02-18Sunny51°-79°2014-02-19Sunny55°-81°2014-02-20Sunny59°-84°2014-02-21PartlyCloudy63°-85°2014-02-22PartlyCloudy63°-84°2014-02-23PartlyCloudy63°-82°2014-02-24PartlyCloudy62°-80°
    

    总结

    恭喜你!你开发了一个客户端来使用Spring调用一个基于SOAP的web service。

  • 相关阅读:
    文本环加载动画html代码
    自己总结的特殊符号,大家有用可以复制
    《名侦探柯南》动画登陆bilibili
    复古风,vivo申请滑盖结构的手机外观专利
    GitHub 热榜第一!可交互全球疫情地图
    最新免费领哔哩哔哩会员教程
    百度网盘免费领取会员
    Apple Watch Series 6或将增加焦虑监测和睡眠追踪功能
    谷歌更新其社区人员流动报告 帮助了解民众遵守封锁令的情况
    计算5的n次幂html代码
  • 原文地址:https://www.cnblogs.com/huang0925/p/3965210.html
Copyright © 2011-2022 走看看