本教程将手把手教你用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或更高版本
- 或
- 你也可以导入本教程的代码,在 中直接访问页面,然后以此为基础,继续学习。
怎么完成本教程
像大多数Spring的入门教程一样,你可以从头开始完成每一个步骤,或者选择跳过你已经熟悉的基础步骤。不管怎么样,最后你都会得到正常运行的代码。
要从头开始,请跳转到用Maven构建。
要路过基础步骤,按如下操作:
- 并解压本教程的代码库,或者用克隆一份:
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
4.0.0 org.springframework gs-rest-service 0.1.0 org.springframework.boot spring-boot-starter-parent 1.2.3.RELEASE org.springframework.boot spring-boot-starter-web 1.7 org.springframework.boot spring-boot-maven-plugin spring-releases https://repo.spring.io/libs-release spring-releases https://repo.spring.io/libs-release
提供了很多方便的特性:
- 收集所有classpath里包含的Jar包,构建成一个可执行的Jar包,这可以使运行或是迁移你的Web Serveice时变得很简便。
- 搜索public static void main() 方法,并将其标识为可执行的class。
- It provides a built-in dependency resolver that sets the version number to match . 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将用 库来自动将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;@RestControllerpublic 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响应体的方式。与其依靠)在服务器端将Greeting对象变成HTML,RESTful web service控制器只是简单的填充并返回Greeting对象,对象中的数据将直接以JSON格式写入到HTTP响应中。
这份代码使用了Sring4系列中的新注解:@RestController,它将一个类标识为一个控制器,这个控制器中所有的方法都返回一个领域对象(domain object),而不是一个视图(view)。之前,@Controller和@ResonseBody两个加一起才能实现这个功能。
Greeting 对象必需被转换成JSON。幸亏有Spring的HTTP消息转换器的支持,你不需要手动做转换。Spring框架自动选择将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;@SpringBootApplicationpublic 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包。
测试服务
现在服务已经起来了,访问,你将看到:
{"id":1,"content":"Hello, World!"}
加上name参数:.返回的content值将改变:
{"id":2,"content":"Hello, User!"}
这个改变表明GreetingController中的@RequestParam运行正常。
同时注意,id属性的值从1变成了2.这证明你对GreetingController发起了多个请求,每次请求对控制器中方法的调用都会使其中的counter递增。
总结
恭喜!你刚刚用Spring开发了一个RESTful web service.