
本指南將引導您完成使用 Spring 創建“Hello, World”RESTful Web 服務的過程,該服務在響應中包含跨域資源共享 (CORS) 的標頭。您可以在此中找到有關Spring CORS支持的更多信息博客文章.
【資料圖】
您將構建一個服務,該服務接受 HTTP GET 請求并使用問候語的 JSON 表示形式進行響應,如以下列表所示:??http://localhost:8080/greeting?
?
{"id":1,"content":"Hello, World!"}
可以使用查詢字符串中的可選參數自定義問候語,如以下清單所示:??name?
?
http://localhost:8080/greeting?name=User
參數值將覆蓋 的默認值,并反映在響應中,如以下清單所示:??name?
???World?
?
{"id":1,"content":"Hello, User!"}
此服務與 中所述的服務略有不同構建一個 RESTful Web 服務,因為它使用 Spring 框架 CORS 支持來添加相關的 CORS 響應標頭。
像大多數春天一樣入門指南,您可以從頭開始并完成每個步驟,也可以繞過您已經熟悉的基本設置步驟。無論哪種方式,您最終都會得到工作代碼。
要從頭開始,請繼續從 Spring 初始化開始.
要跳過基礎知識,請執行以下操作:
下載?并解壓縮本指南的源存儲庫,或使用吉特:git clonehttps://github.com/spring-guides/gs-rest-service-cors.git
光盤成gs-rest-service-cors/initial
跳轉到創建資源表示類.完成后,您可以根據 中的代碼檢查結果。??gs-rest-service-cors/complete?
?
你可以使用這個預初始化項目,然后單擊生成以下載 ZIP 文件。此項目配置為適合本教程中的示例。
手動初始化項目:
導航到https://start.spring.io.此服務拉入應用程序所需的所有依賴項,并為您完成大部分設置。選擇 Gradle 或 Maven 以及您要使用的語言。本指南假定您選擇了 Java。單擊“依賴關系”,然后選擇“Spring Web”。單擊生成。下載生成的 ZIP 文件,該文件是配置了您選擇的 Web 應用程序的存檔。如果您的 IDE 集成了 Spring Initializr,則可以從 IDE 完成此過程。 |
您也可以從 Github 分叉項目,然后在 IDE 或其他編輯器中打開它。 |
?httpclient?
?測試(在)需要Apache庫。??complete/src/test/java/com/example/restservicecors/GreetingIntegrationTests.java?
???httpclient?
?
要將 Apache 庫添加到 Maven,請添加以下依賴項:??httpclient?
?
org.apache.httpcomponents httpclient test
以下清單顯示了完成的文件:??pom.xml?
?
4.0.0 org.springframework.boot spring-boot-starter-parent 3.0.0 com.example rest-service-cors-complete 0.0.1-SNAPSHOT rest-service-cors-complete Demo project for Spring Boot 17 org.springframework.boot spring-boot-starter-web org.apache.httpcomponents.client5 httpclient5 test org.springframework.boot spring-boot-starter-test test org.springframework.boot spring-boot-maven-plugin
要將 Apache 庫添加到 Gradle,請添加以下依賴項:??httpclient?
?
testImplementation "org.apache.httpcomponents:httpclient"
以下清單顯示了完成的文件:??build.gradle?
?
plugins { id "org.springframework.boot" version "3.0.0" id "io.spring.dependency-management" version "1.1.0" id "java"}group = "com.example"version = "0.0.1-SNAPSHOT"sourceCompatibility = "17"repositories { mavenCentral()}dependencies { implementation "org.springframework.boot:spring-boot-starter-web" testImplementation "org.apache.httpcomponents.client5:httpclient5" testImplementation "org.springframework.boot:spring-boot-starter-test"}test { useJUnitPlatform()}
設置項目和生成系統后,可以創建 Web 服務了。
從考慮服務交互開始該過程。
該服務將使用查詢字符串中的參數(可選)處理對 的請求。請求應返回正文中包含 JSON 的響應,以表示問候語。它應類似于以下列表:??GET?
???/greeting?
???name?
???GET?
???200 OK?
?
{ "id": 1, "content": "Hello, World!"}
該字段是問候語的唯一標識符,是問候語的文本表示形式。??id?
???content?
?
若要對問候語表示形式進行建模,請創建資源表示形式類。提供一個普通的舊 Java 對象,其中包含 和 數據的字段、構造函數和訪問器,如以下清單(來自 )所示:??id?
???content?
???src/main/java/com/example/restservicecors/Greeting.java?
?
package com.example.restservicecors;public class Greeting { private final long id; private final String content; public Greeting() { this.id = -1; this.content = ""; } public Greeting(long id, String content) { this.id = id; this.content = content; } public long getId() { return id; } public String getContent() { return content; }}
彈簧使用杰克遜·?庫,用于自動將類型的實例封送到 JSON 中。? |
在Spring構建RESTful Web服務的方法中,HTTP請求由控制器處理。這些組件很容易通過@Controller注釋,以及以下清單 (from ) 中顯示的 通過返回類的新實例來處理請求:??GreetingController?
???src/main/java/com/example/restservicecors/GreetingController.java?
???GET?
???/greeting?
???Greeting?
?
package com.example.restservicecors;import java.util.concurrent.atomic.AtomicLong;import org.springframework.web.bind.annotation.CrossOrigin;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.bind.annotation.RestController;@RestControllerpublic class GreetingController { private static final String template = "Hello, %s!"; private final AtomicLong counter = new AtomicLong(); @CrossOrigin(origins = "http://localhost:8080") @GetMapping("/greeting") public Greeting greeting(@RequestParam(required = false, defaultValue = "World") String name) { System.out.println("==== get greeting ===="); return new Greeting(counter.incrementAndGet(), String.format(template, name)); }}
這個控制器簡潔明了,但引擎蓋下有很多事情要做。我們一步一步地分解它。
注釋可確保將 HTTP 請求映射到該方法。??@RequestMapping?
???/greeting?
???greeting()?
?
前面的示例使用批注,該批注充當 的快捷方式。我們在這種情況下使用是因為它便于測試。Spring 仍將拒絕源與 CORS 配置不匹配的 GET 請求。瀏覽器不需要發送 CORS 預檢請求,但如果我們想觸發預檢,我們可以在正文中使用并接受一些 JSON。? |
??@RequestParam?
?將查詢字符串參數的值綁定到方法的參數中。此查詢字符串參數不是 。如果請求中不存在,則使用 of。??name?
???name?
???greeting()?
???required?
???defaultValue?
???World?
?
方法主體的實現創建并返回一個新對象,屬性的值基于 中的下一個值,屬性的值基于查詢參數或默認值。它還通過使用問候語來格式化給定的格式。??Greeting?
???id?
???counter?
???content?
???name?
???template?
?
傳統 MVC 控制器和前面顯示的 RESTful Web 服務控制器之間的主要區別在于創建 HTTP 響應正文的方式。這個 RESTful Web 服務控制器不是依靠視圖技術來執行問候數據到 HTML 的服務器端呈現,而是填充并返回一個對象。對象數據以 JSON 形式直接寫入 HTTP 響應。??Greeting?
?
為此,{RestController}[] 注解假定每個方法都繼承??@RestController?
?@ResponseBody默認情況下的語義。因此,返回的對象數據將直接插入到響應正文中。
由于Spring的HTTP消息轉換器支持,該對象自然而然地轉換為JSON。因為??Greeting?
?杰克遜在類路徑上,春天的MappingJackson2HttpMessageConverter自動選擇將實例轉換為 JSON。??Greeting?
?
您可以從單個控制器或全局啟用跨源資源共享 (CORS)。以下主題介紹了如何執行此操作:
控制器方法 CORS 配置全局 CORS 配置為了使 RESTful Web 服務在其響應中包含 CORS 訪問控制標頭,您必須向處理程序方法添加注釋,如以下清單 (from ) 所示:??@CrossOrigin?
???src/main/java/com/example/restservicecors/GreetingController.java?
?
@CrossOrigin(origins = "http://localhost:8080") @GetMapping("/greeting") public Greeting greeting(@RequestParam(required = false, defaultValue = "World") String name) { System.out.println("==== get greeting ===="); return new Greeting(counter.incrementAndGet(), String.format(template, name));
此注釋僅為此特定方法啟用跨源資源共享。默認情況下,它允許所有源、所有標頭和注釋中指定的 HTTP 方法。此外,還使用了 30 分鐘。您可以通過指定以下批注屬性之一的值來自定義此行為:??@CrossOrigin?
???@RequestMapping?
???maxAge?
?
?origins?
???methods?
???allowedHeaders?
???exposedHeaders?
???allowCredentials?
???maxAge?
?.在此示例中,我們只允許發送跨源請求。??http://localhost:8080?
?
您還可以在控制器類級別添加注釋,以在此類的所有處理程序方法上啟用 CORS。? |
除了(或作為基于注釋的細粒度配置的替代方法)之外,您還可以定義一些全局 CORS 配置。這類似于使用 但可以在 Spring MVC 中聲明并與細粒度配置相結合。默認情況下,允許使用所有源和、 和方法。??Filter?
???@CrossOrigin?
???GET?
???HEAD?
???POST?
?
下面的清單(來自)顯示了類中的方法:??src/main/java/com/example/restservicecors/GreetingController.java?
???greetingWithJavaconfig?
???GreetingController?
?
@GetMapping("/greeting-javaconfig") public Greeting greetingWithJavaconfig(@RequestParam(required = false, defaultValue = "World") String name) { System.out.println("==== in greeting ===="); return new Greeting(counter.incrementAndGet(), String.format(template, name));
方法和方法之間的區別(用于? |
下面的清單(來自)顯示了如何在應用程序類中添加 CORS 映射:??src/main/java/com/example/restservicecors/RestServiceCorsApplication.java?
?
public WebMvcConfigurer corsConfigurer() { return new WebMvcConfigurer() { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/greeting-javaconfig").allowedOrigins("http://localhost:8080"); } }; }
您可以輕松更改任何屬性(如示例中所示),以及將此 CORS 配置應用于特定路徑模式。??allowedOrigins?
?
您可以組合全局級和控制器級 CORS 配置。 |
Spring Initializr 為您創建了一個基本的應用程序類。以下清單(來自 )顯示了初始類:??initial/src/main/java/com/example/restservicecors/RestServiceCorsApplication.java?
?
package com.example.restservicecors;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplicationpublic class RestServiceCorsApplication { public static void main(String[] args) { SpringApplication.run(RestServiceCorsApplication.class, args); }}
您需要添加一個方法來配置如何處理跨源資源共享。以下清單(來自 )顯示了如何執行此操作:??complete/src/main/java/com/example/restservicecors/RestServiceCorsApplication.java?
?
@Bean public WebMvcConfigurer corsConfigurer() { return new WebMvcConfigurer() { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/greeting-javaconfig").allowedOrigins("http://localhost:8080"); } }; }
下面的清單顯示了已完成的應用程序類:
package com.example.restservicecors;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.context.annotation.Bean;import org.springframework.web.servlet.config.annotation.CorsRegistry;import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@SpringBootApplicationpublic class RestServiceCorsApplication { public static void main(String[] args) { SpringApplication.run(RestServiceCorsApplication.class, args); } @Bean public WebMvcConfigurer corsConfigurer() { return new WebMvcConfigurer() { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/greeting-javaconfig").allowedOrigins("http://localhost:8080"); } }; }}
??@SpringBootApplication?
?是一個方便的注釋,它添加了以下所有內容:
?@Configuration?
?:將類標記為應用程序上下文的 Bean 定義源。??@EnableAutoConfiguration?
?:告訴 Spring 引導根據類路徑設置、其他 bean 和各種屬性設置開始添加 bean。例如,如果 在類路徑上,則此注釋會將應用程序標記為 Web 應用程序并激活關鍵行為,例如設置 .spring-webmvc
DispatcherServlet
??@ComponentScan?
?:告訴 Spring 在包中查找其他組件、配置和服務,讓它找到控制器。com/example
該方法使用 Spring Boot 的方法啟動應用程序。您是否注意到沒有一行 XML?也沒有文件。此 Web 應用程序是 100% 純 Java,您無需處理配置任何管道或基礎結構。??main()?
???SpringApplication.run()?
???web.xml?
?
您可以使用 Gradle 或 Maven 從命令行運行應用程序。您還可以構建一個包含所有必需依賴項、類和資源的可執行 JAR 文件并運行該文件。通過構建可執行 jar,可以輕松地在整個開發生命周期中跨不同環境等將服務作為應用程序進行交付、版本控制和部署。
如果使用 Gradle,則可以使用 .或者,您可以使用 JAR 文件生成 JAR 文件,然后運行該文件,如下所示:??./gradlew bootRun?
???./gradlew build?
?
java -jar build/libs/gs-rest-service-cors-0.1.0.jar
如果使用 Maven,則可以使用 運行應用程序。或者,您可以使用 JAR 文件生成 JAR 文件,然后運行該文件,如下所示:??./mvnw spring-boot:run?
???./mvnw clean package?
?
java -jar target/gs-rest-service-cors-0.1.0.jar
此處描述的步驟將創建一個可運行的 JAR。你也可以構建經典 WAR 文件. |
將顯示日志記錄輸出。該服務應在幾秒鐘內啟動并運行。
現在服務已啟動,請在瀏覽器中訪問,您應該看到:??http://localhost:8080/greeting?
?
{"id":1,"content":"Hello, World!"}
通過訪問提供查詢字符串參數。屬性的值從 更改為 ,如下面的清單所示:??name?
???http://localhost:8080/greeting?name=User?
???content?
???Hello, World!?
???Hello User!?
?
{"id":2,"content":"Hello, User!"}
此更改表明 中的排列按預期工作。參數的默認值為 ,但始終可以通過查詢字符串顯式重寫。??@RequestParam?
???GreetingController?
???name?
???World?
?
此外,該屬性已從 更改為 。這證明您正在跨多個請求處理同一實例,并且其字段在每次調用時都會按預期遞增。??id?
???1?
???2?
???GreetingController?
???counter?
?
現在,您可以測試 CORS 標頭是否已到位,并允許來自其他源的 Javascript 客戶端訪問該服務。為此,您需要創建一個 Javascript 客戶端來使用該服務。以下清單顯示了此類客戶端:
首先,創建一個名為 (from ) 的簡單 Javascript 文件,其中包含以下內容:??hello.js?
???complete/public/hello.js?
?
$(document).ready(function() { $.ajax({ url: "http://localhost:8080/greeting" }).then(function(data, status, jqxhr) { $(".greeting-id").append(data.id); $(".greeting-content").append(data.content); console.log(jqxhr); });});
此腳本使用 jQuery 在 使用 REST 服務。它由 加載,如以下清單 (from ) 所示:??http://localhost:8080/greeting?
???index.html?
???complete/public/index.html?
?
Hello CORS <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script> <script src="hello.js"></script>The ID is
The content is
這本質上是創建于使用 jQuery 使用 RESTful Web 服務,稍作修改,以便在 localhost 端口 8080 上運行時使用服務。有關如何開發此客戶端的更多詳細信息,請參閱該指南。 |
要啟動在本地主機上的端口 8080 上運行的客戶端,請運行以下 Maven 命令:
./mvnw spring-boot:run
如果您使用 Gradle,則可以使用以下命令:
./gradlew bootRun
應用啟動后,打開??http://localhost:8080??在瀏覽器中,您應該看到以下內容:
若要測試 CORS 行為,需要從另一個服務器或端口啟動客戶端。這樣做不僅可以避免兩個應用程序之間的沖突,還可以確保客戶端代碼從與服務不同的源提供。若要啟動在端口 9000 的本地主機上運行的應用(以及已在端口 8080 上運行的應用),請運行以下 Maven 命令:
./mvnw spring-boot:run -Dserver.port=9000
如果您使用 Gradle,則可以使用以下命令:
./gradlew bootRun --args="--server.port=9000"
應用啟動后,打開??http://localhost:9000??在瀏覽器中,您應該看到以下內容:
如果服務響應包含 CORS 標頭,則 ID 和內容將呈現到頁面中。但是,如果 CORS 標頭丟失(或對于客戶端來說不足),則瀏覽器會使請求失敗,并且值不會呈現到 DOM 中。
祝賀!您剛剛開發了一個 RESTful Web 服務,其中包括與 Spring 的跨域資源共享。