使用Spring创建满足RESTful规范的Web Service

原文: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。

你可能感兴趣的:(使用Spring创建满足RESTful规范的Web Service)