0%

SpringBoot 开发实践(4):使用 @Controller 实现 RESTful Web 接口

前言

在之前的章节,我们已经用到了 Controller 的部分功能——外界通过 HTTP 请求,访问 SpringBoot 中的方法。这就是我们熟知的 Web 接口,是客户端与后端应用交互的重要方式之一。

那么在本章,我们就来整理下如何使用 @Controller 实现 RESTful Web 接口。

@Controller 的使用

基本介绍

@Controller 注解用于标识一个类,被标识的类就是个 SpringMVC Controller 对象,即一个控制器。SpringBoot 在启动时,会自动扫描被 @Controller 标记的类,并扫描该类中的方法。使用 @RequestMapping 标记的方法即为一个处理器,不同的请求会由分发器分发到对应的方法上。

创建 Controller 类

新建一个 controller 包,在包内创建一个 MyController1.java

1
2
3
4
5
6
7
8
@Controller
public class MyController1 {
@ResponseBody
@RequestMapping(value = "/test")
private String test() {
return "Hello world!";
}
}
  • @Controller: 标记为一个控制器类。
  • @ResponseBody: 标志返回值是实体内容,而不是返回一个界面。因为我们要做的是 RESTful 接口,所以这里需要的是直接返回参数内容。如果不标记 @ResponseBody 的话,将返回名为”Hello world!”的界面文件。
  • @RequestMapping: 标记方法为控制器。后面会详细介绍该注解的用法。

启动项目,在浏览器中或 Web 调试工具(例如 PostMan)访问 http://127.0.0.1:8080/test,将得到”Hello world!”字符串。

用 @RestController 代替 @Controller 与 @ResponseBody

@RestController 的功能 = @Controller + @ResponseBody。 在类上标注 @RestController,就不需要在该类的每个方法上标注 @ResponseBody 了。

@RequestMapping 的使用

基本介绍

@RequestMapping 可以标识在类或者方法上,用于指明 Spring 用哪个类或者哪个方法来处理对应的请求。

@RequestMapping 标记在类上时,表示该类下的所有方法都被映射到其 value 属性所指示的路径下。

创建 MyController2.java

1
2
3
4
5
6
7
8
9
10
11
12
13
@RestController
@RequestMapping(value = "/controller2")
public class MyController2 {
@RequestMapping(value = "/test1")
private String test1() {
return "This is test1.";
}

@RequestMapping(value = "/test2")
private String test2() {
return "This is test2.";
}
}

这上面这两个方法的 URL 分别为:

  • http://127.0.0.1:8080/controller2/test1
  • http://127.0.0.1:8080/controller2/test2

@RequestMapping 相关属性

@RequestMapping 中,可以配置如下的属性:

  • value: 用于将请求映射到指定的方法上。
  • method: 规定请求的类型。支持的请求类型包括:GETPOSTPUTDELETEOPTIONSPATCHHEADTRACE。如果不填,则默认支持所有请求类型。
  • consumes: 规定请求的入参类型,即 Content-Type。例如:text/xmlapplication/jsonmultipart/form-data 等。
  • produces: 规定请求的出参类型,如果请求的 header 中设置了 Accept 类型,则需要在 produces 中配置同样的类型才能返回出参。
  • params: 规定请求中必须包含指定参数值时,方法才会处理该请求。
  • headers: 规定请求头必须包含指定 header 值时,方法才会处理该请求。
  • name: 给映射地址起个别名。

例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@RestController
@RequestMapping(value = "/controller3")
public class MyController3 {
@RequestMapping(value = "/test1", method = {RequestMethod.POST})
private String test1() {
return "This is test1.";
}

@RequestMapping(value = "/test2", consumes = "application/json")
private String test2() {
return "This is test2.";
}

@RequestMapping(value = "/test3", params = "id=1")
private String test3() {
return "This is test3.";
}
}
  • http://127.0.0.1:8080/controller3/test1: 该请求的类型必须为 POST。
  • http://127.0.0.1:8080/controller3/test2: 该请求 header 中必须指定 Content-type = application/json
  • http://127.0.0.1:8080/controller3/test3?id=1: 该请求,必须要传入 id = 1 参数,方法才会被执行。

如何获取入参

通常,我们需要在访问接口的同时向后台传入数据。关于入参的获取,有以下四种常见方式。

通过 HttpServletRequest 获取参数

HttpServletRequest 对象,包含了客户端一次 HTTP 请求中的请求消息头、请求消息体和请求消息行的所有内容。通过 API 可以获取请求中的信息。对于入参,我们可以使用 getParameter(String key) 方法获得参数值。

MyController4.java 中添加如下方法:

1
2
3
4
5
6
@RequestMapping(value = "/test1")
private String test1(HttpServletRequest httpServletRequest) {
int id = Integer.parseInt(httpServletRequest.getParameter("id"));
String name = httpServletRequest.getParameter("name");
return String.format("id:%d, name:%s", id, name);
}

访问 http://127.0.0.1:8080/controller4/test1?id=1&name=InterHorse,返回“id:1, name:InterHorse”。

通过 @RequestParam 获取参数

1
2
3
4
5
@RequestMapping(value = "/test2")
private String test2(@RequestParam("id") int id,
@RequestParam("name") String name) {
return String.format("id:%d, name:%s", id, name);
}

访问 http://127.0.0.1:8080/controller4/test2?id=1&name=InterHorse,返回“id:1, name:InterHorse”。

其中,@RequestParam 也有属性可以进行配置:

  • name: 指定属性绑定的名称。
  • value: name 的别名。所以 name 和 value 是等价的。
  • required: 参数是否必须传。默认为 true。
  • defaultValue: 如果某个属性的 required 设置为 false,则可以通过该属性配置某个参数的默认值。

例如

1
2
3
4
5
@RequestMapping(value = "/test5")
private String test5(@RequestParam(value = "id", required = false, defaultValue = "10") int id,
@RequestParam(value = "name", required = false, defaultValue = "Bill") String name) {
return String.format("id:%d, name:%s", id, name);
}

如果入参为空,则默认返回“id:10, name:Bill”。

通过 @PathVariable 获得入参

使用 @PathVariable ,可以直接将 URL 中的参数动态绑定到入参中。

1
2
3
4
5
@RequestMapping(value = "/test3/{id}/{name}")
private String test3(@PathVariable("id") int id,
@PathVariable("name") String name) {
return String.format("id:%d, name:%s", id, name);
}

请求 http://127.0.0.1:8080/controller4/test3/1/InterHorse,返回值为“id:1, name:InterHorse”。

通过实体获得入参

创建一个实体 InputAO.java,包含 id 和 name 两个属性。SpringBoot 会自动根据入参的属性名称与实体中同名属性进行映射,将参数 set 到实体中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class InputAO {
private int id;
private String name;

public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}
}
1
2
3
4
5
6
@RequestMapping(value = "/test4")
private String test4(InputAO inputAO) {
int id = inputAO.getId();
String name = inputAO.getName();
return String.format("id:%d, name:%s", id, name);
}

请求 http://127.0.0.1:8080/controller4/test4?id=1&name=InterHorse,返回值为“id:1, name:InterHorse”。

如何返回参数

返回一个对象

在之前所有的演示中,我们已经在返回 String 类型的数据了,其他几种基本类型例如 intlongboolean 也是一样,只需要修改方法的返回类型就可以返回不同类型的数据了。那么如何返回对象类型呢?非常简单,只需要将返回类型修改为需要返回的对象类型,那么 SpringBoot 就自动将实体序列化成 JSON 格式进行返回了。

创建实体 ResponseBO.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class ResponseBO {
private String code;
private String message;
private Object data;

public String getCode() {
return code;
}

public void setCode(String code) {
this.code = code;
}

public String getMessage() {
return message;
}

public void setMessage(String message) {
this.message = message;
}

public Object getData() {
return data;
}

public void setData(Object data) {
this.data = data;
}
}

MyController5.java 中添加如下方法

1
2
3
4
5
6
7
8
9
10
11
12
@RequestMapping(value = "/test1")
private ResponseBO test1(@RequestParam("id") int id,
@RequestParam("name") String name) {
ResponseBO res = new ResponseBO();
res.setCode("200");
res.setMessage("调用成功");
Map<String, Object> map = new HashMap<>(2);
map.put("id", id);
map.put("name", name);
res.setData(map);
return res;
}

访问 http://127.0.0.1:8080/controller5/test1?id=1&name=InterHorse ,返回

1
2
3
4
5
6
7
8
{
"code": "200",
"message": "调用成功",
"data": {
"name": "InterHorse",
"id": 1
}
}

设置 HTTP 参数

有时候,我们除了要返回数据内容之外,可能还要根据需要,设置 HTTP 的相关属性。例如,默认的 HTTP code 为 200,如果想修改成别的数值,需要怎么做呢?同样也非常简单。与 HttpServletRequest 类似,HttpServletResponse 对象为一次请求的响应对象,在方法的入参中添加 HttpServletResponse httpServletResponse,通过其 API 即可对响应内容进行设置。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@RequestMapping(value = "/test2")
private ResponseBO test2(@RequestParam("id") int id,
@RequestParam("name") String name,
HttpServletResponse httpServletResponse) {
ResponseBO res = new ResponseBO();
res.setCode("200");
res.setMessage("调用成功");
Map<String, Object> map = new HashMap<>(2);
map.put("id", id);
map.put("name", name);
res.setData(map);
// 设置 HTTP code
httpServletResponse.setStatus(600);
return res;
}

访问 http://127.0.0.1:8080/controller5/test2?id=1&name=InterHorse,请求的 HTTP code 已设置为 600。

以上就是有关 SpringBoot 中 RESTful Web API 的常用实现方法。方法之多,适用为重。要根据实际的生产需要,选择适合自己的方法。

本章代码地址:GitHub


我是因特马,一个爱分享的斜杠程序员~

欢迎关注我的公众号:一只因特马

  • 本文作者: 因特马
  • 本文链接: https://www.interhorse.cn/a/463891276/
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!