1 概述
Web服务层的构建可以说是开发Spring Boot应用程序最主要的工作,现实中几乎所有互联网应用程序都需要对外提供各种形式的Web服务。本篇讨论的对象是轻量级Web服务,其表现形式就是通过HTTP暴露的一组端点。Spring Boot为开发轻量级Web服务提供了一系列解决方案。
Spring Boot 框架提供的第一套解决方法那就是WebMVC,这是基于MVC(Model View Controller)架构设计并实现的经典技术组件。开发人员使用一组基础注解就可以开发Controller,并暴露RESTFUL风格的HTTP端点。对服务消费,可以使用RestTemplate模版工具类。
Spring Boot框架提供的第二套解决方案是HATEOAS,这是在整个REST成熟度模型中位于最高层次的技术组件。通过Spring HATEOAS,能够开发超媒体组件,并实现自解释的Web API。
最后,在前后端分离的开发模式下,开发人员面临的一大挑战是如何设计合理且高效的前后端交互Web API。这时候就可以引入Spring Boot框架提供的第三套解决方案,即Spring GraphQL。GraphQL是一种图驱动的查询语言,可以用来设计并实现满足前后端交互所需的数据格式、返回结果、请求次数以及请求地址。
2 Spring WebMVC
Spring WebMVC框架具有一套遵循模型-视图-控制器架构设计理念的体系结构,可以开发灵活、松耦合的HTTP端点。Spring基础框架就包含WebMVC组件,而基于Spring Boot开发的Web服务同样使用到该组件。Web服务的实现涉及服务创建和服务消费两个方面。下面将对这两个方面所涉及的技术组件进行介绍。
2.1 创建Web服务
在Spring Boot中,创建Web服务的主要工作是实现Controller。而在创建Controller之后,需要对HTTP请求进行处理并返回正确的响应结果。
1、创建Controller
@RestController
@RequestMapping(value = "users")
public class UserController {
@GetMapping(value = "/{id}")
public User getUserById(@PathVariable String id){
User user = new User();
user.setId("001");
user.setName("张三");
return user;
}
}
@Document("users")
public class User {
@Id
private String id;
@Field("name")
private String name;
@Field("age")
private Integer age;
@Field("createAt")
private Date createdAt;
@Field("nationality")
private String nationality;
@Field("friendsIds")
private List<String> friendsIds;
@Field("articlesIds")
private List<String> articlesIds;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Date getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Date createdAt) {
this.createdAt = createdAt;
}
public String getNationality() {
return nationality;
}
public void setNationality(String nationality) {
this.nationality = nationality;
}
public List<String> getFriendsIds() {
return friendsIds;
}
public void setFriendsIds(List<String> friendsIds) {
this.friendsIds = friendsIds;
}
public List<String> getArticlesIds() {
return articlesIds;
}
public void setArticlesIds(List<String> articlesIds) {
this.articlesIds = articlesIds;
}
}
这个一个典型的Controller,可以看到上述代码包含了@RestController、@RequestMapping、@GetMapping等注解。其中, @RestController注解集成自Spring MVC中的@Controller,就是一个RESTFul风格的HTTP端点,并且会自动使用JSON实现HTTP请求和响应的序列化/反序列化。根据这一特性,在构建Web服务时可以使用@RestController注解来取代@Controller注解以简化开发。
@GetMapping 注解和 @RequestMapping注解的功能类似,只是默认使用了Restquest-Method.GET来指定HTTP方法。Spring Boot2 引入了一批新注解,除了@GetMapping外还有@PutMapping、@PostMapping、@DeleteMapping等,方便开发人员显示指定HTTP请求方法。也可以继续使用原来的@RequestMapping注解来实现同样的效果。
在上述UserController中,通过静态代码完成根据用户ID获取用户信息的业务流程。这里用到了两层Mapping,第一层的@RequestMapping注解在服务层定义了服务的根据经users,而第二层GetMapping注解则在操作级别又定义了HTTP请求方法的具体路径及参数信息。
2.2 处理Web请求
处理Web请求的过程涉及获取输入参数以及返回响应结果。Spring Boot提供了一系列便捷有用的注解来简化对请求输入的控制过程,常用的包括上述UserController中所展示的@PathVariable和@RequestBody。
@PathVariable注解用于获取路径参数,即从类似url/{id}这种形式的路径中获取{id}参数的值。通常,使用@PathVariable注解时只需要指定参数的名称即可。下面一段代码使用@PathVariable注解的典型代码示例,在请求路径中同时传入了两个参数。
@PostMapping(value = "/{username}/{password}")
public User generateUser(@PathVariable("username") String username,@PathVariable("password") String password){
User user = new User(username,password);
return user;
}
在HTTP中,content-type属性用来指定所传输的内容类型。可以通过@Request-Mapping注解中的produces属性来对其进行设置,通常会将其设置为application/json。
@RestController
@RequestMapping(value = "users",produces = "application/json")
public class UserController {
@GetMapping(value = "/{id}")
public User getUserById(@PathVariable String id){
User user = new User();
user.setId("001");
user.setName("张三");
return user;
}
@PostMapping(value = "/{username}/{password}")
public User generateUser(@PathVariable("username") String username,@PathVariable("password") String password){
User user = new User(username,password);
return user;
}
}
而@ReuqestBody主机是用来处理content-type为application/json类型时的请求内容。通过@RequestBody注解可以将请求体中的JSON字符串绑定到相应的实体对象上。可以对上面的generateUser()方法进行重构,通过@RequestBody注解来传入参数。
@PostMapping(value = "/")
public User generateUser(@RequestBody User user_){
}
2.3 消费Web服务
当创建好Controller之后,接下来要做的就是对它暴露的HTTP端点进行消费。将引入Spring Boot提供的RestTemplate模版工具类。
1、创建RestTemplate
想要创建一个RestTemplate对象,最简单也最常见的方法就是直接new一个该类的实例。
@SpringBootApplication
public class TestRestTemplate {
@Bean
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
这里创建了一个RestTemplate实例,通过@Bean注解将其注入到Spring容器中。在Spring Boot应用程序中,通常会把上述代码放在Bootstrap类中,这样在代码工程的其他地方都可以应用这个实例。
2、使用RestTemplate
通过RestTemplate发送的请求和获取的响应都是以JSON作为序列化方式。当创建完RestTemplate之后,就可以使用它内置的工具方法来向远程Web服务发起请求。RestTemplate为开发人员提供了一大批发送HTTP请求的工具方法,如下表: