# 消費SOAP Web服務
本指南將引導您完成使用Spring使用基于SOAP的Web服務的過程。
## 你會建立什么
您將構建一個客戶端,該客戶端使用 從基于WSDL的遠程Web服務中獲取國家/地區數據數據 [SOAP](https://en.wikipedia.org/wiki/SOAP) 。 您可以按照 查找有關國家/地區服務的更多信息并自己運行該服務 [本指南](https://spring.io/guides/gs/producing-web-service/) 。
該服務提供國家/地區數據。 您將能夠根據國家名稱查詢有關國家的數據。
## 你需要什么
* 約15分鐘
* 最喜歡的文本編輯器或IDE
* [JDK 1.8](http://www.oracle.com/technetwork/java/javase/downloads/index.html) 或更高版本
* [Gradle 4+](http://www.gradle.org/downloads) 或 [Maven 3.2+](https://maven.apache.org/download.cgi)
* 您還可以將代碼直接導入到IDE中:
* [彈簧工具套件(STS)](https://spring.io/guides/gs/sts)
* [IntelliJ IDEA](https://spring.io/guides/gs/intellij-idea/)
## 如何完成本指南
像大多數Spring 一樣 [入門指南](https://spring.io/guides) ,您可以從頭開始并完成每個步驟,也可以繞過您已經熟悉的基本設置步驟。 無論哪種方式,您最終都可以使用代碼。
要 **從頭開始** ,請繼續進行“ [從Spring Initializr開始”](https://spring.io/guides/gs/consuming-web-service/#scratch) 。
要 **跳過基礎知識** ,請執行以下操作:
* [下載](https://github.com/spring-guides/gs-consuming-web-service/archive/master.zip) 并解壓縮本指南的源存儲庫,或使用 對其進行克隆 [Git](https://spring.io/understanding/Git) : `git clone [https://github.com/spring-guides/gs-consuming-web-service.git](https://github.com/spring-guides/gs-consuming-web-service.git)`
* 光盤進入 `gs-consuming-web-service/initial`
* 前進以 [基于WSDL生成域對象](https://spring.io/guides/gs/consuming-web-service/#initial) 。
**完成后** ,您可以根據中的代碼檢查結果 `gs-consuming-web-service/complete`.
如果閱讀了《 生產SOAP Web服務》 ,您可能會想知道為什么本指南不使用 spring-boot-starter-ws? 該Spring Boot啟動器僅適用于服務器端Web服務。 該入門程序可以帶入嵌入式Tomcat等功能,而無需進行Web調用。
## 在本地運行目標Web服務
請遵循 的步驟, [隨附指南中](https://spring.io/guides/gs/producing-web-service/) 或克隆 [存儲庫](https://github.com/spring-guides/gs-producing-web-service) 并運行服務(例如,通過使用 `mvn spring-boot:run`)從 `complete`目錄。 您可以通過訪問來驗證它是否有效 `[http://localhost:8080/ws/countries.wsdl](http://localhost:8080/ws/countries.wsdl)`在您的瀏覽器中。 如果您不這樣做,您稍后會在JAXB工具中看到一個令人困惑的異常。
## 從Spring Initializr開始
對于所有Spring應用程序,您應該從 開始 [Spring Initializr](https://start.spring.io) 。 Initializr提供了一種快速的方法來提取應用程序所需的所有依賴項,并為您完成了許多設置。 該示例僅需要Spring Web Services依賴項。
以下清單顯示了 `pom.xml` 選擇Maven時創建的文件:
~~~
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>consuming-web-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>consuming-web-service</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
~~~
以下清單顯示了 `build.gradle` 選擇Gradle時創建的文件:
~~~
plugins {
id 'org.springframework.boot' version '2.3.2.RELEASE'
id 'io.spring.dependency-management' version '1.0.8.RELEASE'
id 'java'
}
group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter'
testImplementation('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
}
test {
useJUnitPlatform()
}
~~~
## 修改構建文件
Spring Initializr創建的構建文件需要大量的工作才能完成本指南。 另外,對 `pom.xml` (對于Maven)和 `build.gradle` (對于Gradle)有很大的不同。
### Maven
For Maven, you need to add a dependency, a profile, and a WSDL generation plugin.
以下清單顯示了您需要在Maven中添加的依賴項:
~~~
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web-services</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
~~~
以下清單顯示了要使其與Java 11一起使用時需要在Maven中添加的配置文件:
~~~
<profiles>
<profile>
<id>java11</id>
<activation>
<jdk>[11,)</jdk>
</activation>
<dependencies>
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
</dependency>
</dependencies>
</profile>
</profiles>
~~~
“ [基于WSDL生成域對象”](https://spring.io/guides/gs/consuming-web-service/#initial) 部分介紹了WSDL生成插件。
以下清單顯示了最終的 `pom.xml` 文件:
~~~
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.2.RELEASE</version>
<!-- lookup parent from repository -->
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>consuming-web-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>consuming-web-service</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- tag::dependency[] -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web-services</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- end::dependency[] -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<!-- tag::profile[] -->
<profiles>
<profile>
<id>java11</id>
<activation>
<jdk>[11,)</jdk>
</activation>
<dependencies>
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
</dependency>
</dependencies>
</profile>
</profiles>
<!-- end::profile[] -->
<build>
<plugins>
<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>
<version>0.14.0</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
<configuration>
<schemaLanguage>WSDL</schemaLanguage>
<generatePackage>com.example.consumingwebservice.wsdl</generatePackage>
<schemas>
<schema>
<url>http://localhost:8080/ws/countries.wsdl</url>
</schema>
</schemas>
</configuration>
</plugin>
<!-- end::wsdl[] -->
</plugins>
</build>
</project>
~~~
### Gradle
For Gradle, you need to add a dependency, a configuration, a `bootJar` section, and a WSDL generation plugin.
The following listing shows the dependency you need to add in Gradle:
~~~
implementation ('org.springframework.boot:spring-boot-starter-web-services') {
exclude group: 'org.springframework.boot', module: 'spring-boot-starter-tomcat'
}
implementation 'org.springframework.ws:spring-ws-core'
// For Java 11:
implementation 'org.glassfish.jaxb:jaxb-runtime'
compile(files(genJaxb.classesDir).builtBy(genJaxb))
jaxb "com.sun.xml.bind:jaxb-xjc:2.1.7"
~~~
注意排除了Tomcat。 如果允許Tomcat在此版本中運行,則將與提供國家/地區數據的Tomcat實例發生端口沖突。
以下清單顯示了 `bootJar` 您需要在Gradle中添加的部分:
~~~
bootJar {
baseName = 'gs-consuming-web-service'
version = '0.0.1'
}
~~~
“ [基于WSDL生成域對象”](https://spring.io/guides/gs/consuming-web-service/#initial) 部分介紹了WSDL生成插件。
以下清單顯示了最終的 `build.gradle` 文件:
~~~
plugins {
id 'org.springframework.boot' version '2.3.2.RELEASE'
id 'io.spring.dependency-management' version '1.0.8.RELEASE'
id 'java'
}
group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'
// tag::configurations[]
configurations {
jaxb
}
// end::configurations[]
repositories {
mavenCentral()
}
// tag::wsdl[]
task genJaxb {
ext.sourcesDir = "${buildDir}/generated-sources/jaxb"
ext.classesDir = "${buildDir}/classes/jaxb"
ext.schema = "http://localhost:8080/ws/countries.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: "com.example.consumingwebservice.wsdl") {
arg(value: "-wsdl")
produces(dir: sourcesDir, includes: "**/*.java")
}
javac(destdir: classesDir, source: 1.8, target: 1.8, 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 {
// tag::dependency[]
implementation ('org.springframework.boot:spring-boot-starter-web-services') {
exclude group: 'org.springframework.boot', module: 'spring-boot-starter-tomcat'
}
implementation 'org.springframework.ws:spring-ws-core'
// For Java 11:
implementation 'org.glassfish.jaxb:jaxb-runtime'
compile(files(genJaxb.classesDir).builtBy(genJaxb))
jaxb "com.sun.xml.bind:jaxb-xjc:2.1.7"
// end::dependency[]
testImplementation('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
}
test {
useJUnitPlatform()
}
// tag::bootjar[]
bootJar {
baseName = 'gs-consuming-web-service'
version = '0.0.1'
}
// end::bootjar[]
~~~
## Generate Domain Objects Based on a WSDL
The interface to a SOAP web service is captured in [WSDL](https://en.wikipedia.org/wiki/Web_Services_Description_Language). JAXB provides a way to generate Java classes from WSDL (or rather, the XSD contained in the `<Types/>` section of the WSDL). You can find the WSDL for the country service at `[http://localhost:8080/ws/countries.wsdl](http://localhost:8080/ws/countries.wsdl)`.
要從Maven中的WSDL生成Java類,您需要以下插件設置:
~~~
<plugin>
<groupId>org.jvnet.jaxb2.maven2</groupId>
<artifactId>maven-jaxb2-plugin</artifactId>
<version>0.14.0</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
<configuration>
<schemaLanguage>WSDL</schemaLanguage>
<generatePackage>com.example.consumingwebservice.wsdl</generatePackage>
<schemas>
<schema>
<url>http://localhost:8080/ws/countries.wsdl</url>
</schema>
</schemas>
</configuration>
</plugin>
~~~
此設置將為在指定URL處找到的WSDL生成類,并將這些類放入 `com.example.consumingwebservice.wsdl`包裹。 要生成該代碼,請運行 `./mvnw compile` 然后看 `target/generated-sources` 如果您想檢查它是否有效。
要對Gradle進行同樣的操作,您將在構建文件中需要以下內容:
~~~
task genJaxb {
ext.sourcesDir = "${buildDir}/generated-sources/jaxb"
ext.classesDir = "${buildDir}/classes/jaxb"
ext.schema = "http://localhost:8080/ws/countries.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: "com.example.consumingwebservice.wsdl") {
arg(value: "-wsdl")
produces(dir: sourcesDir, includes: "**/*.java")
}
javac(destdir: classesDir, source: 1.8, target: 1.8, 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")
}
}
}
}
}
~~~
As Gradle does not (yet) have a JAXB plugin, it involves an Ant task, which makes it a bit more complex than in Maven. To generate that code run `./gradlew compileJava` and then look in `build/generated-sources` if you want to check that it worked.
在這兩種情況下,JAXB域對象生成過程都已連接到構建工具的生命周期中,因此一旦構建成功,就無需運行任何額外的步驟。
## 創建國家服務客戶
要創建Web服務客戶端,您必須擴展 [`WebServiceGatewaySupport`](https://docs.spring.io/spring-ws/sites/2.0/apidocs/org/springframework/ws/client/core/support/WebServiceGatewaySupport.html) 對您的操作進行分類和編碼,如下例所示(摘自 `src/main/java/com/example/consumingwebservice/CountryClient.java`)顯示:
~~~
package com.example.consumingwebservice;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ws.client.core.support.WebServiceGatewaySupport;
import org.springframework.ws.soap.client.core.SoapActionCallback;
import com.example.consumingwebservice.wsdl.GetCountryRequest;
import com.example.consumingwebservice.wsdl.GetCountryResponse;
public class CountryClient extends WebServiceGatewaySupport {
private static final Logger log = LoggerFactory.getLogger(CountryClient.class);
public GetCountryResponse getCountry(String country) {
GetCountryRequest request = new GetCountryRequest();
request.setName(country);
log.info("Requesting location for " + country);
GetCountryResponse response = (GetCountryResponse) getWebServiceTemplate()
.marshalSendAndReceive("http://localhost:8080/ws/countries", request,
new SoapActionCallback(
"http://spring.io/guides/gs-producing-web-service/GetCountryRequest"));
return response;
}
}
~~~
The client contains one method (`getCountry`) that does the actual SOAP exchange.
在這種方法中, `GetCountryRequest` 和 `GetCountryResponse`類是從WSDL派生的,并且是在JAXB生成過程中 (在 [生成的 基于WSDL的生成域對象中進行了介紹](https://spring.io/guides/gs/consuming-web-service/#initial) )。 它創建了 `GetCountryRequest` 請求對象并使用 `country`參數(國家名稱)。 在打印出國家名稱后,它使用 [`WebServiceTemplate`](https://docs.spring.io/spring-ws/sites/2.0/apidocs/org/springframework/ws/client/core/WebServiceTemplate.html) 由...提供 `WebServiceGatewaySupport`基類做實際的SOAP交換。 它通過了 `GetCountryRequest` 請求對象(以及 `SoapActionCallback`傳遞 的 [SOAPAction](https://www.w3.org/TR/2000/NOTE-SOAP-20000508/#_Toc478383528) 帶有請求 標頭),如WSDL描述的那樣, `<soap:operation/>`元素。 它將響應轉換為 `GetCountryResponse` 對象,然后將其返回。
## 配置Web服務組件
Spring WS使用Spring Framework的OXM模塊,該模塊具有 `Jaxb2Marshaller` 序列化和反序列化XML請求,如以下示例(來自 `src/main/java/com/example/consumingwebservice/CountryConfiguration.java`)顯示:
~~~
package com.example.consumingwebservice;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.oxm.jaxb.Jaxb2Marshaller;
@Configuration
public class CountryConfiguration {
@Bean
public Jaxb2Marshaller marshaller() {
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
// this package must match the package in the <generatePackage> specified in
// pom.xml
marshaller.setContextPath("com.example.consumingwebservice.wsdl");
return marshaller;
}
@Bean
public CountryClient countryClient(Jaxb2Marshaller marshaller) {
CountryClient client = new CountryClient();
client.setDefaultUri("http://localhost:8080/ws");
client.setMarshaller(marshaller);
client.setUnmarshaller(marshaller);
return client;
}
}
~~~
The `marshaller` is pointed at the collection of generated domain objects and will use them to both serialize and deserialize between XML and POJOs.
The `countryClient` is created and configured with the URI of the country service shown earlier. It is also configured to use the JAXB marshaller.
## Run the Application
This application is packaged up to run from the console and retrieve the data for a given country name, as the following listing (from `src/main/java/com/example/consumingwebservice/ConsumingWebServiceApplication.java`) shows:
~~~
package com.example.consumingwebservice;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import com.example.consumingwebservice.wsdl.GetCountryResponse;
@SpringBootApplication
public class ConsumingWebServiceApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumingWebServiceApplication.class, args);
}
@Bean
CommandLineRunner lookup(CountryClient quoteClient) {
return args -> {
String country = "Spain";
if (args.length > 0) {
country = args[0];
}
GetCountryResponse response = quoteClient.getCountry(country);
System.err.println(response.getCountry().getCurrency());
};
}
}
~~~
這 `main()` 該方法符合 [`SpringApplication`](https://docs.spring.io/spring-boot/docs/2.3.2.RELEASE/api/org/springframework/boot/SpringApplication.html) 幫手類,提供 `CountryConfiguration.class` 作為其論點 `run()`方法。 這告訴Spring從中讀取注釋元數據 `CountryConfiguration` 并將其作為Spring應用程序上下文中的組件進行管理。
此應用程序經過硬編碼以查找“西班牙”。 在本指南的后面,您將看到如何在不編輯代碼的情況下輸入其他符號。
### 建立可執行的JAR
您可以使用Gradle或Maven從命令行運行該應用程序。 您還可以構建一個包含所有必需的依賴項,類和資源的可執行JAR文件,然后運行該文件。 生成可執行jar使得在整個開發生命周期中,跨不同環境等等的情況下,都可以輕松地將服務作為應用程序進行發布,版本控制和部署。
如果您使用Gradle,則可以通過使用以下命令運行該應用程序 `./gradlew bootRun`。 或者,您可以通過使用以下命令構建JAR文件: `./gradlew build` 然后運行JAR文件,如下所示:
~~~
java -jar build/libs/gs-consuming-web-service-0.1.0.jar
~~~
如果您使用Maven,則可以通過使用以下命令運行該應用程序 `./mvnw spring-boot:run`。 或者,您可以使用以下命令構建JAR文件: `./mvnw clean package` 然后運行JAR文件,如下所示:
~~~
java -jar target/gs-consuming-web-service-0.1.0.jar
~~~
The steps described here create a runnable JAR. You can also build a classic WAR file.
Logging output is displayed. The service should be up and running within a few seconds.
The following listing shows the initial response:
~~~
Requesting country data for Spain
<getCountryRequest><name>Spain</name>...</getCountryRequest>
~~~
您可以通過運行以下命令來插入其他國家/地區:
~~~
java -jar build/libs/gs-consuming-web-service-0.1.0.jar Poland
~~~
然后,響應更改為以下內容:
~~~
Requesting location for Poland
<getCountryRequest><name>Poland</name>...</getCountryRequest>
~~~
## 概括
恭喜你! 您剛剛開發了一個客戶端,可以使用Spring使用基于SOAP的Web服務。
- springboot概述
- springboot構建restful服務
- spring構建一個RESTful Web服務
- spring定時任務
- 消費RESTful Web服務
- gradle構建項目
- maven構建項目
- springboot使用jdbc
- springboot應用上傳文件
- 使用LDNA驗證用戶
- 使用 spring data redis
- 使用 spring RabbitTemplate消息隊列
- 用no4j訪問nosql數據庫
- springboot驗證web表單
- Spring Boot Actuator構j建服務
- 使用jms傳遞消息
- springboot創建批處理服務
- spring security保護web 安全
- 在Pivotal GemFire中訪問數據
- 使用Spring Integration
- 使用springboot jpa進行數據庫操作
- 數據庫事務操作
- 操作mongodb
- springmvc+tymleaf創建web應用
- 將Spring Boot JAR應用程序轉換為WAR
- 創建異步服務
- spring提交表單
- 使用WebSocket構建交互式Web應用程序
- 使用REST訪問Neo4j數據
- jquery消費restful
- springboot跨域請求
- 消費SOAP Web服務
- springboot使用緩存
- 使用Vaadin創建CRUD UI
- 使用REST訪問JPA數據
- 使用REST訪問Pivotal GemFire中的數據
- 構建soap服務
- 使用rest訪問mongodb數據
- 構建springboot應用docker鏡像
- 從STS部署到Cloud Foundry
- springboot測試web應用
- springboot訪問mysql
- springboot編寫自定義模塊并使用
- 使用Google Cloud Pub / Sub進行消息傳遞
- 構建反應式RESTful Web服務
- 使用Redis主動訪問數據
- Spring Boot 部署到Kubernetes
- 使用反應式協議R2DBC訪問數據
- Spring Security架構
- spring構建Docker鏡像詳解
- Spring Boot和OAuth2
- springboot應用部署到k8s
- spring構建rest服務詳解