您好,欢迎访问一九零五行业门户网

构建一个基于 Spring 的 RESTful Web Service

目标构建一个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.6或更高 gradle 1.8+或maven 3.0+ 你也可以使用sts(spring tool suite)直接import该工程 
如何完成如同所有的spring入门教程,你可以选择一步一步的自己实现,也可以跳过基本的设置步骤。最终,你都将得到一份可以正常运行的代码。
如果选择按步实现,继续下一节。
如果选择跳过基本的安装部分,则执行以下命令从github获取代码:
git clone https://github.com/spring-guides/gs-rest-service.git
切换当前目录到gs-rest-service/initial,跳到 create a resource representation class步骤 。
完成后,可以与gs-rest-service/complete中的代码对比一下,确保正确。
建立工程首先建立一个基本的构建脚本。基于spring构建应用时,可以用使用任何的构建系统。这里我们以gradle和maven为例。如果不熟悉它们,请参考building java projects with gradle或者building java projects with maven
建立目录结构在你选定的工程目录下,建立如下子目录结构;例如,在*nix系统中使用mkdir -p src/main/java/hello命令:
└── src └── main └── java └── hello
创建gradle构建文件下面是初始的gradle构建文件。你也可以使用maven,maven的配置文件pom.xml可以参考这里。如果你使用sts(spring tool suite),可以直接导入该工程。
build.gradle
buildscript { repositories { maven { url http://repo.spring.io/libs-snapshot } mavenlocal() }}apply plugin: 'java'apply plugin: 'eclipse'apply plugin: 'idea'jar { basename = 'gs-rest-service' version = '0.1.0'}repositories { mavencentral() maven { url http://repo.spring.io/libs-snapshot }}dependencies { compile(org.springframework.boot:spring-boot-starter-web:1.0.0.rc1) compile(com.fasterxml.jackson.core:jackson-databind) testcompile(junit:junit:4.11)}task wrapper(type: wrapper) { gradleversion = '1.8'}
注意:本文使用了spring boot。
创建资源描述类(create a resource representation class)现在已经建立了工程和构建系统,下面创建你的web service。
首先考虑服务间的交互(service interactions)。
这个服务要处理/greeting的get请求,其查询字符串包含一个可选的name参数。这个get请求应该一个200 ok的响应,以及json结构的描述问候语的内容。格式如下:
{ id: 1, content: hello, world!}
id域是问候语的唯一标识,content域是问候语的文本描述。
为了对问候语的描述进行建模,创建了一个资源描述类。提供了一个包含域(id和content)、构造方法和访问器(getter和setter)的pojo(pain 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类型的实例编码成json格式。
下面创建资源控制器(resource controller)来发送这些问候语。
创建资源控制器(create a resource controller)采用spring构建restful web services时,采用控制器处理http请求。控制器组件通过@controller注解来标识,下面的greetingcontroller类处理/greeting的get请求,并返回一个greeting类的新的实例:
src/main/java/hello/greetingcontroller.java
package hello;import java.util.concurrent.atomic.atomiclong;import org.springframework.stereotype.controller;import org.springframework.web.bind.annotation.requestmapping;import org.springframework.web.bind.annotation.requestparam;import org.springframework.web.bind.annotation.responsebody;@controllerpublic class greetingcontroller { private static final string template = hello, %s!; private final atomiclong counter = new atomiclong(); @requestmapping(/greeting) public @responsebody greeting greeting( @requestparam(value=name, required=false, defaultvalue=world) string name) { return new greeting(counter.incrementandget(), string.format(template, name)); }}
这个controller很简单,但是其内部做了大量工作,麻雀虽小,五脏俱全。我们一步一步的解释。
@requestmapping注解确保对/greeting的http请求映射到greeting()方法。
注意:上述例子中没有写明get、put、post等等。这是因为@requestmapping注解默认情况下映射所有的http操作。使用@requestmapping(method=get)指定只映射get请求。
@requestparam把查询字符串中name参数的值绑定到greeting()方法的name参数上。该查询参数不是必须的(required=false);如果请求时没有指定该参数,则使用其默认值“world”(defaultvalue)。
方法体的实现创建并返回了一个新的greeting对象,该对象的id属性每次自增1,content属性采用template和name组合而来。
传统的mvc控制器和上述restful web service控制器的一个关键区别在于:http响应体的创建方式。前者采用视图层技术(view technology)实现把服务器端的数据渲染为html,后者则返回一个greeting对象。对象数据将会直接以json格式写到http响应中。
通过以下方式实现上述功能,greeting()方法的@responsebody注解告诉spring mvc不需要使用服务器端视图层渲染问候语对象(the greeting object),取而代之的是,返回的问候语对象时一个response body,而且应该直接写出。
greeting对象必须转换成json格式。由于spring支持http报文转换,你不需要手工进行转换。由于jackson 2在classpath中,因而spring的mappingjackson2httpmessageconverter会自动将greeting实例转换为json格式。
make the application executable虽然可以将这个service打包成传统的war文件,并部署到一个外部的应用服务器上,但是我们采用了一个更简单的方式:创建一个独立的(standalone)应用程序。把所有文件打包到一个可执行的jar文件中,由古老的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@enableautoconfigurationpublic class application { public static void main(string[] args) { springapplication.run(application.class, args); }}
main()方法调用了springapplication帮助类,把application.class传递给它的run()方法作为参数。这样spring就会去从application读取注解,并作为spring application context的一个组件进行管理。
@componentscan注解告诉spring递归地搜索hello包和其子包中直接或间接标记为@component的类。这确保spring发现并注册greetingcontroller,由于它被标记为@controller,而@controller是一类@component注解。
@enableautoconfiguration注解基于你的classpath的内容打开合理的默认行为。例如,由于应用程序依赖于嵌入版的tomcat(tomcat-embed-core.jar),一个tomcat服务器会自动建立并进行合理的默认配置。应用程序也依赖于spring mvc(spring-webmvc.jar),一个spring mvc dispatcherservlet会为你配置和注册–不需要web.xml!自动配置(auto-configuration)是一种强大的灵活的机制。详请参考api文档。
构建可执行jar(build an executable jar)目前位置,application类已经写完,下面通过构建系统把所有文件打包为一个可执行jar文件。这将便于对这个service在多种不同环境中进行发布、版本控制和部署。
下面是采用gradle的步骤,如果采用maven,可以在这里找到pom.xml文件,执行mvn clean package构建工程。
更新build.gradle文件的buildscript部分,如下:
buildscript { repositories { maven { url http://repo.spring.io/libs-snapshot } mavenlocal() } dependencies { classpath(org.springframework.boot:spring-boot-gradle-plugin:1.0.0.rc1) }}
再在build.gradle中添加如下语句:
apply plugin: 'spring-boot'
可以在这里看到最终版本的build.gradle文件。
spring boot gradle plugin收集classpath中的所有jar包,并构建一个单独的uber-jar,这使得更加便于执行和传输你的service。它也搜索public static void main()方法标志为一个可执行类。
下面执行如下命令生成一个单独的可执行jar文件,该jar文件包含所有必需的依赖的类和资源:
./gradlew build
如果你使用gradle,可以使用如下语句执行生成的jar文件:
java -jar build/libs/gs-rest-service-0.1.0.jar
如果使用maven,使用如下语句:
java -jar target/gs-rest-service-0.1.0.jar
注意:上述过程将生成一个可执行jar。你也可以选择构建一个war文件。
执行(run the service)如果采用gradle,可以在命令行中执行如下命令来运行你的service:
./gradlew clean build && java -jar build/libs/gs-rest-service-0.1.0.jar
注意:如果采用maven,可以执行如下语句mvn clean package && java -jar target/gs-rest-service-0.1.0.jar
日志输出。service将会启动并在数秒钟内运行。
测试(test the service)现在service已经启动,访问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!}
这说明greetingcontroller类中的@requestparam注解起作用了。name参数给定的默认值为“world”,但是可以通过在查询字符串中设定值覆盖它。
注意id属性从1变为2。这表明你在多次请求中访问了同一个greetingcontroller实例,它的counter域每次访问时会自增1。
小结(summary)恭喜!你已经开发出了一个基于spring的restful web service。
其它类似信息

推荐信息