本教程将手把手教你用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两个加一起才能实现这个功能。