原文:http://spring.io/guides/gs/rest-service/
这个指南讨论如何使用Spring的RESTful web service来创建一个“hello world”程序。
示例功能简介
使用以下方式的HTTP GET请求来访问这个Service:
http://localhost:8080/greeting
使用下面greeting的JSON描述来响应这个请求:
{"id":1,"content":"Hello, World!"}
在下面的查询字符串中有一个可选的name参数,可以实现greeting的定制化响应:
http://localhost:8080/greeting?name=User
name参数值会替换默认的“World”,并反映到对应的响应中:
{"id":1,"content":"Hello, User!"}
开发环境
一个文本编辑器或IDE;
JDK1.6或更新的版本;
Gradle1.11+或Maven3.0+;
也可以把本实例的代码直接导入到Spring Tool Suite(STS)中,然后在那儿开始工作。
如何完成这个指南
跟大多数Spring的入门指南一样,可以按照步骤从头开始,也可以跳过那些你已经熟悉的基本的步骤,不管使用哪种方法,最终都要编写工作代码。
要从头开始,请转到下面的“使用Gradle构建”标题。
要跳过基本步骤,请做以下事情:
1. 下载并解压本指南的资源库,或使用以下Git命令来克隆它:
git clone https://github.com/spring-guides/gs-rest-service.git
2. 在命令行进入gs-rest-service/initial目录
3. 跳转到下面的“创建资源描述类”标题。
使用Gradle构建
首先要建立一个基本的编译脚本。在编译使用Spring的应用程序时,你可以使用任意你喜欢的编译系统,但是本示例程序需要使用这里介绍的Gradle和Maven来工作。如果你不熟悉这两个工具,请参照“使用Gradle构建Java工程”或“使用Mave构建Java工程”
创建目录结构
在你选择的工程目录中,创建下列子目录结构;例如,在操作系统中使用mkdir/-p src/main/java/hello命令:
└── src
└── main
└── java
└── hello
创建Gradle的编译文件
下面是初始的Gradle的编译文件。
build.gradle
buildscript {
repositories {
maven { url"https://repo.spring.io/libs-release" }
mavenLocal()
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:1.1.10.RELEASE")
}
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'spring-boot'
jar {
baseName ='gs-rest-service'
version = '0.1.0'
}
repositories {
mavenLocal()
mavenCentral()
maven { url"https://repo.spring.io/libs-release" }
}
dependencies {
compile("org.springframework.boot:spring-boot-starter-web")
testCompile("junit:junit")
}
task wrapper(type: Wrapper) {
gradleVersion = '1.11'
}
Spring启动 gradle插件提供了很多方便的功能:
1. 它收集了所有的classpath上的jars,并把它们打包成一个单独的、可运行的“über-jar”,这让执行和传输服务更加方便。
2. 它会搜索Public static void main()方法,把它标记为可运行的类。
3. 它提供了一个内置的依赖解析器,把对应的版本号设置给匹配的Spring启动依赖,你可以用你所希望的版本来重写,但它会默认启动选择的版本设置。
使用Mave构建
首先建立基本的编译脚本,在使用Spring构建应用程序时,你可以使用任意你喜欢的构建系统,但是本示例的代码需要使用这里介绍的Maven。如果你还不熟悉Maven,可以参照“使用Maven来构建Java工程”。
创建目录结构
在你选择的工程目录中,创建下列子目录,例如,在操作系统命令行下使用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.1.10.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<properties>
<start-class>hello.Application</start-class>
</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>
SpringBoot Maven插件提供了很多方便的功能:
1. 它收集了所有的classpath上的jars,并把它们打包成一个单独的、可运行的“über-jar”,这让执行和传输服务更加方便。
2. 它会搜索Public static void main()方法,把它标记为可运行的类。
3. 它提供了一个内置的依赖解析器,把对应的版本号设置给匹配的Spring启动依赖,你可以用你所希望的版本来重写,但它会默认启动选择的版本设置。
使用Spring工具集来创建
如果使用Spring工具集,那么你可以简单的直接导入这个指南。
创建一个资源描述类
现在可以创建该工程并编译系统,就可以创建自己的Web Service了。
以下是Service的交互过程:
该Service会处理/greeting的GET请求,在这个请求的查询字符串中会带有一个可选的name参数。这个GET请求应该返回200 OK的响应,并用JSON的格式在消息体中描述一个问候。它看上去格式如下:
{
"id": 1,
"content": "Hello, World!"
}
其中id字段这个问候的唯一标识,content字段问候的文本描述。
我们需要创建一个资源描述类来作为问候表述的模型。
这个类提供了一个带有字段、构造器以及id和content字段的访问器的普通Java对象:
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类型的示例封装到JSON中。
创建资源控制器
在Spring创建RESTful的web service的方法中,HTTP请求是由控制器来处理的。通过@RestController注释可以很容易的识别这些组件,并且下面的处理/greeting的GET请求的GreetingController会返回一个新的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参数中。这个查询字符串参数不是必须的,如果在请求中没有这个参数,那么会使用默认值“World”。
这个方法的实现部分创建并返回了一个新的Greeting对象,这个对象的id属性值是来自counter对象的下一个值,content属性值是template变量使用name值格式化后的值。
RESTful web service控制器跟传统的MVC控制器的关键差异是是创建HTTP响应的方式不同,它不依赖于在服务端把相关数据展开到HTML中的视图技术,而是简单包装并返回一个Greeting对象,这个对象会用JSON的形式直接写个HTTP响应。
上述代码中使用Spring 4中新的@RestController注释,它把这个类标记为控制器,其中的每个方法会返回一个域对象而不是一个视图。它是@Controller和@ResponseBody注释合到一起的快捷方式。
Greeting对象必须被转换成JSON格式,我们要感谢Spring的HTTP消息转换支持,你不需要手动的来做这种转换。因为类路径中有Jackson 2类库,Spring的MappingJackson2HttpMessageConverter类会自动的把Greeting示例转换到JSON样式。
编写可执行的应用程序
尽管可以把这个服务打包成传统的WAR文件,并把他部署到一个外部的应用服务器中,但为了便于演示,本示例创建了一个独立的应用程序。你要把以上创建的代码和资源打包到一个单独的、可执行的JAR文件中,然后使用Java的main()方法来启动应用。在这个过程中,你会使用Spring支持的内置的Tomcat的servlet容器来作为HTTP的运行时,而不是把它部署到外部的应用服务器中。
src/main/java/hello/Application.java
package hello;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.SpringApplication;
import org.springframework.context.annotation.ComponentScan;
@ComponentScan
@EnableAutoConfiguration
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
main()方法中调用的SpringApplication帮助器,并给它的run()方法提供了Application.class作为参数,这是告诉Spring要从Application对象中读取注释的元素数据,并且会把该Application对象作为Spring应用程序的上下文环境中的一个组件来管理。
@ComponentScan注释会告诉Spring采用递归的方法来搜索hell包和其子包中直接或间接带有Spring的@Component注释标记的类。这个只是确保Spring会找到并注册GreetingController类,因为它使用了@RestController注释,这注释是@Component注释的一种类型。
@EnableAutoConfiguration注释会基于你的类路径上内容来切换合理的默认行为,例如,因为本应用程序会依赖内置的Tomcat的版本(tomcat-embed-core.jar),所以建立和配置一个Tomcat服务就被认为是合理的默认行为。并且因为该应用程序还依赖Spring的MVC框架(spring-webmvc.jar),所以默认会给你配置和注册Spring MVC的DispatcherServlet类---无需web.xml!自动配置时一种强大、灵活的机制。更多的细节可参考API文档。
创建一个可执行的JAR
如果你正在使用Gradle,可以使用./gradlew bootRun命令来运行本应用程序。
你可以使用./gradlew build命令把所有的必要的依赖、类和资源都编译到一个可执行的JAR文件中。这样会让它在其整个生命周期内,很容易的进行传递、版本管理以及部署等等。
运行该JAR文件的命令如下:
java -jar build/libs/gs-rest-service-0.1.0.jar
如果你正在使用Maven,可以使用mvn spring-boot:run命令来运行本应用程序。或者适应mvn clean package命令来创建一个JAR文件,然后使用下面的命令来运行这个JAR文件:
java -jar target/gs-rest-service-0.1.0.jar
注意:上述创建可运行的JAR的过程,也可以用创建类的WAR文件来代替。
运行该JAR文件时,会有日志显示。
测试该Web Service
服务被启动后,在浏览器中访问http://localhost:8080/greeting,你会看到:
{"id":1,"content":"Hello, World!"}
给http://localhost:8080/greeting?name=User的查询字符串name提供一个值,你会看到content属性的值从“Hello,World!”改变到“Hello,User!”:
{"id":2,"content":"Hello, User!"}
这种改变演示了GreetingController中@RequestParam注释所期望的工作结果。name参数已经给设置了默认值“World”,但是它可以通过查询字符串来显示的重写。
还要注意id属性值已经从1改变成2,这证明了多个请求都使用同一个GreetingController示例来工作,并且counter每次调用都像期望的那样被加1。