【前言】这是我学习Spring框架的第一篇,之前看过几本介绍Spring框架的书,上面都是用context.xml文件完成bean配置。最近自己阅读spring官方网站,发现全部是用注解,没有一行xml配置。为了跟上时代,我决定把官网教程读一遍,在这里放上阅读笔记。
【原文链接】http://spring.io/guides/gs/rest-service/
【实现目标】创建一个web服务,能够响应形如:http://localhost:8080/greeting 这样的get请求。响应页面是一个Json,看起来应该是这样的,{"id":1,"content":"Hello, World!"}
。也可以给get请求带上参数http://localhost:8080/greeting?name=User 这样的话,响应页面看起来应该是这样的{"id":1,"content":"Hello,User!"}
。
【准备工作】
按照原文给的方法进行。
如果是用Eclipse的maven创建工程,需要在pom.xml中设置依赖关系,最好按照原文maven配置方法添加pom.xml中的属性。否则org.springframework.web.bind.annotation.*无法导入。
生成一个代表资源的类
一切准备好之后,现在可以创建自己的web server了。开始我们想想web服务是怎么交互的:server先处理对/greeting的GET请求,GET可以带个参数name。然后server返回200 OK,并用一个Json最为应答正文,这个Json看起来像这样:
{
"id": 1,
"content": "Hello, World!"
}
id域是每个greeting的唯一标识,content域代表问候语。
为了给问候语建模,现在需要一个类来表示问候语,这个类只需要简单的几个东西:id、content域,构造器,域访问器
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;
}
}
下一步建立处理greeting请求的资源控制器
创建资源控制器
用Spring框架实现的web server中,HTTP请求都由控制器来处理。控制器部分可以用@RestController
注解来标注。下面的GreetingController类就是用来处理greeting请求的控制器,它的greeting方法响应对/greeting页面的get请求,并返回一个Greeting对象。
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请求映射到了greetring()方法。这里并没有区分get post put方法,可以用@RequestMapping(method=GET)实现更精确的匹配绑定。
- @RequestParam 注解可以指定请求的参数,他把http请求中的参数name(即,value="name")绑定到greeting(Stringname)方法中的参数name。defaultValue="World"的含义是,如果http请求中不带参数name,那么greeting()中的name将被赋值为"World"。
- 在greeting()方法内部,用Greeting()构造器生成Greeting对象并返回。用AtomicLong的counter生成id,name按template格式化。
传统MVC和RESTfull web server的关键不同点在于,HTTP响应体的生成方式。传统MVC基于视图的方式会在server端渲染成HTML格式的问候语greeting,而后者只是简单计数(指id计数),控制器只需返回Greeting对象,而这个Greeting对象将由框架以Json的方式写入HTML。
这里使用了Spring4最新的注解@RestController
将一个类声明为控制器,该类中所有的处理请求的方法都返回对象而不是MVC中的View。这个注解是@Controller
和@ResponseBody
组合的简写。
Greeting对象必须转成Json。感谢Spring框架对Http消息的支持,你不需要自己完成这个转换。系统路径中有Jackson 2,Spring中的MappingJackson2HttpMessageConverter
功能会自动实现Bean到Json的转换。
让应用能跑起来
虽然可以把工程打包成war部署在一个web应用服务上,不过下面会告诉你一个实现独立应用的方法。先把所有东西都打包成一个可运行的jar文件,当然,要有一个main()方法。下一步是将jar包部署在tomcat servlet容器上面作为HTTP运行环境。
package hello;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
@SpringBootApplication
注解意味着以下工作:
-
@Configuration
标记的类作为applicationContext中bean的定义(不再需要写.xml文件了)。 -
@EnableAutoConfiguration
告诉Spring Boot 添加classpath 中指定的bean、其他bean、和各种属性设置。 -
一般你需要为Spring MVC 应用添加
@EnableWebMvc
注解,不过Spring Boot在发现classpath中含有spring-webmvc时会自动添加。这个注解标记应用为web应用,同时激活一些关键行为,例如启动一个servlet转发器。 -
@ComponentScan
告诉Spring在hello包中扫描其他部分、配置、服务来定位HelloController。
main()方法是用了Spring Boot的SpringApplication.run()
方法启动应用。你是否注意到这里没有一行XML,也没有web.xml。本工程是100%纯java工程,不需要做任何配置(用注解就是这样~)。
Build和执行JAR
- 如果你用的Gradle,你可以这样
运行./gradlew bootRun
。你可以创建一个单独的可执行JAR文件,包含了所有必须的依赖文件,类,资源。这样做能很容易的在开发周期中在不同环境之间完成移植,发布版本,部署服务。此时你可以这样:./gradlew build 然后就可以运行java -jar build/libs/gs-rest-service-0.1.0.jar
- 如果用的Maven,你可以这样运行应用:
mvn spring-boot:run
. 或者你可以buildmvn clean package
然后运行JAR:java -jar target/gs-rest-service-0.1.0.jar
- 也可以打包成war
测试
经过测试,发现一些有意思的东西。
- 我的运行环境是eclipse下的maven构建的Spring工程,在启动Spring应用的时候,他会自动装载到Tomcat里面,我的tomcat配置的8080端口,所以url变成了http://localhost:8080/greeting。
- Application类和Controller类必须在一个package里面,否则servlet转发机制虽然生效,却并不会转发http请求到controller。而Bean可以放在另一个package里面。
【小结】熟悉掌握控制器中的注解@RestController @RequestMapping @RequestParam,应用入口的注解@SpringBootApplication,以及Spring Boost入口SpringApplication.run()