本教程將手把手教你用Spring構建一個"hello world" RESTful Web Service。
你將構建什么
你將構建一個Web Service,用於接收HTTP GET請求,請求地址:
http://localhost:8080/greeting
請求響應返回一段JSON格式的問候語:
{"id":1,"content":"Hello, World!"}
你可以在請求中添加一個可選參數:name,定制問候語:
http://localhost:8080/greeting?name=User
name 參數的值會替換默認的“World”,相應的響應返回變成:
{"id":1,"content":"Hello, User!"}
你需要什么
- 大約15分鍾
- 你最喜歡的文本編輯器或IDE
- JDK1.7或更高版本
- Gradle 2.3+ 或 Maven 3.0+
- 你也可以導入本教程的代碼,在Spring Tool Suite (STS) 中直接訪問頁面,然后以此為基礎,繼續學習。
怎么完成本教程
像大多數Spring的入門教程一樣,你可以從頭開始完成每一個步驟,或者選擇跳過你已經熟悉的基礎步驟。不管怎么樣,最后你都會得到正常運行的代碼。
要從頭開始,請跳轉到用Maven構建。
要路過基礎步驟,按如下操作:
- 下載並解壓本教程的代碼庫,或者用Git克隆一份:
git clone https://github.com/spring-guides/gs-rest-service.git
- 進入如下目錄:
gs-rest-service/initial
- 跳轉到創建資源表示類
當你完成后,你可以拿你的結果跟如下目錄下的代碼做對比,看是否正確:
gs-rest-service/complete
用Maven構建
首先你要寫一個基本的構建腳本。你可以使用任意一款你喜歡的構建系統來構建Spring應用程序,但是下面會給出你需要的Maven代碼。如果你對Maven不熟悉,請參考用Maven構建Java工程。
創建目錄結構
在你選擇的工程目錄下,創建如下的子目錄結構;例如,在*nix系列系統中,使用如下命令:
mkdir -p src/main/java/hello
└── src
└── main
└── java
└── hello
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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.springframework</groupId> <artifactId>gs-rest-service</artifactId> <version>0.1.0</version> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.2.3.RELEASE</version> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies> <properties> <java.version>1.7</java.version> </properties> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> <repositories> <repository> <id>spring-releases</id> <url>https://repo.spring.io/libs-release</url> </repository> </repositories> <pluginRepositories> <pluginRepository> <id>spring-releases</id> <url>https://repo.spring.io/libs-release</url> </pluginRepository> </pluginRepositories> </project>
Spring Boot Maven plugin 提供了很多方便的特性:
- 收集所有classpath里包含的Jar包,構建成一個可執行的Jar包,這可以使運行或是遷移你的Web Serveice時變得很簡便。
- 搜索public static void main() 方法,並將其標識為可執行的class。
- It provides a built-in dependency resolver that sets the version number to match Spring Boot dependencies. You can override any version you wish, but it will default to Boot’s chosen set of versions.(這一段沒看懂,不敢亂翻譯)
創建資源表示類
現在你已經搭建好工程和構建系統,可以開始創建你的Web Service了。
先想想Web Service是如何交互的。
你的Web Service將處理對/greeting路徑的GET請求,請求中可以選擇攜帶name參數。處理請求后應該返回一個200 OK的響應,在響應的body中包含JSON格式的問候語句。看起來像這樣:
{
"id": 1,
"content": "Hello, World!"
}
id 字段是一個問候的唯一標識,content 是問候的文本內容。
為問候這一概念建模,你創建一個資源表示類,這是一個POJO(plain old JAVA object):
src/main/java/hello/Greeting.java
package hello; public class Greeting { private final long id; private final String content; public Greeting(long id, String content) { this.id = id; this.content = content; } public long getId() { return id; } public String getContent() { return content; } }
注意:下面你會看到,Spring將用Jackson JSON 庫來自動將Greeting類的JAVA對象實例轉換成JSON格式。
創建一個控制器(controller)
Spring構建的RESTful web services用控制器來處理HTTP請求。這些組件都是用@RestController注解來標識,下面的GreetingController將處理對/greeting路徑發起的GET請求,然后返回一個Greeting類的實例對象:
src/main/java/hello/GreetingController.java
package hello; import java.util.concurrent.atomic.AtomicLong; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @RestController public class GreetingController { private static final String template = "Hello, %s!"; private final AtomicLong counter = new AtomicLong(); @RequestMapping("/greeting") public Greeting greeting(@RequestParam(value="name", defaultValue="World") String name) { return new Greeting(counter.incrementAndGet(), String.format(template, name)); } }
這個控制器簡單且精練,但是其中包含的東西卻不少。讓我們來一一解析。
@RequestMapping 注解確保對/greeting路徑的HTTP請求都會映射到greeting()方法。
注意:上面的例子沒有指出請求類型是GET還是PUT或是POST,亦或是其他類型,因為@RequestMapping默認會映射所有類型的HTTP請求。可以使用@RequestMapping(method=Get)來限制映射的請求類型。
@RequestParam會將請求參數name的值賦予greeting()方法的入參,如果請求中未攜帶name參數,則name參數的默認值為"World"。
方法里創建並返回一個新建的Greeting對象,其id屬性來源於counter的下一個值,content屬性則是用String的format方法,利用greeting模板對指定的name進行格式化得到的。
傳統的MVC控制器和RESTful web service控制器之間最關鍵的一個不同是生成HTTP響應體的方式。與其依靠視圖技術(view technology)在服務器端將Greeting對象變成HTML,RESTful web service控制器只是簡單的填充並返回Greeting對象,對象中的數據將直接以JSON格式寫入到HTTP響應中。
這份代碼使用了Sring4系列中的新注解:@RestController,它將一個類標識為一個控制器,這個控制器中所有的方法都返回一個領域對象(domain object),而不是一個視圖(view)。之前,@Controller和@ResonseBody兩個加一起才能實現這個功能。
Greeting 對象必需被轉換成JSON。幸虧有Spring的HTTP消息轉換器的支持,你不需要手動做轉換。Spring框架自動選擇MappingJackson2HttpMessageConverter
將Greeting對象實例轉換成JSON。
讓程序變得可執行
雖然將這個WEB Service打包成一個傳統的WAR包然后部署到一個外部應用服務器是可行的,但下面會展示一個更簡單的方法:創建一個獨立的應用程序。你將所有的東西打包到一個可執行的JAR包中,用一個JAVA中古老但好用的main()方法來引導啟動。同時你利用Spring內嵌的Tomcat servlet容器做HTTP運行環境,而不是部署到外部的Tomcat。
src/main/java/hello/Application.java
package hello; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
@SpringBootApplication是一個便捷的注解,這個注解把以下所有的增加進來:
- @Configuration 將這個類標記成應用程序上下文中bean定義的源頭。
- @EnableAutoConfiguration告訴Spring可以開始加載beans了,從classpath配置中,還有各種屬性配置文件中加載beans,或是加載別的beans。
- 一般你將為一個Spring MVC框架的應用程序加上 @EnableWebMvc注解,但Spring Boot只要在classpath中看到spring-webmvc就會自動加上該注解。這個注解將應用程序標記為一個WEB應用程序,並且激活一些關鍵行為,比如建起一個DispatcherServlet.
- @ComponentScan告訴Spring去尋找hello包中的其他組件,配置文件,服務,使其可以找到HelloController。
main()方法中調用Spring Boot的SpringApplication.run()方法來啟動應用程序。你有沒有注意到我們沒用到一丁點的XML?連web.xml文件都沒有。這個Web應用程序是100%純JAVA的,你不用做任何配置任何管道或基礎配置項。
構建一個可執行的JAR
如果你使用Maven,你可以用如下命令來執行程序:mvn spring-boot:run.你也可以用mvn clean package來打Jar包,用java –jar target/gs-rest-service-0.1.0.jar來運行Jar包,你將看到正在打印日志信息,服務將在幾秒鍾之后運行起來。
注意:上面的過程將會生成一個可執行的Jar包,你也可以選擇構建一個經典的WAR包。
測試服務
現在服務已經起來了,訪問http://localhost:8080/greeting,你將看到:
{"id":1,"content":"Hello, World!"}
加上name參數:http://localhost:8080/greeting?name=User.返回的content值將改變:
{"id":2,"content":"Hello, User!"}
這個改變表明GreetingController中的@RequestParam運行正常。
同時注意,id屬性的值從1變成了2.這證明你對GreetingController發起了多個請求,每次請求對控制器中方法的調用都會使其中的counter遞增。
總結
恭喜!你剛剛用Spring開發了一個RESTful web service.