简介

Swagger 是最流行的 API 开发工具,它遵循 OpenAPI Specification(OpenAPI 规范,也简称 OAS)。 Swagger 可以贯穿于整个 API 生态,如 API 的设计、编写 API 文档、测试和部署。 Swagger 是一种通用的,和编程语言无关的 API 描述规范。

官网:https://swagger.io/

导入swagger依赖

1
2
3
4
5
6
7
8
9
10
11
12
 <!--swagger依赖-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<!--swagger ui-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>

编写swagger的配置类

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
@Configuration
@EnableSwagger2
public class Swagger2Config {
/**
* 创建API应用
* apiInfo() 增加API相关信息
* 通过select()函数返回一个ApiSelectorBuilder实例,用来控制哪些接口暴露给Swagger来展现,
* 指定扫描的包路径来定义指定要建立API的目录。
* @return
*/
@Bean
public Docket coreApiConfig(){
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(adminApiInfo())
.groupName("com.zzu_miao")
.select()
.paths(Predicates.and(PathSelectors.regex("/.*")))
.build();
}

private ApiInfo adminApiInfo(){
return new ApiInfoBuilder()
.title("zzu_miao--api文档")
.description("zzu_miao接口描述")
.version("1.0")
.contact(new Contact("dhx","https://www.dhx.icu/","2648466390@qq.com"))
.build();
}
}

添加文档内容

在完成了上述配置后,其实已经可以生产文档内容,但是这样的文档主要针对请求本身

描述的主要来源是函数的命名,通常需要自己增加一些说明来丰富文档内容。

比如下面是没有添加任何内容, 仅仅是配置swagger直接就显示的内容

启动springboot后, 访问 Swagger UI: http://localhost:8080/swagger-ui.html#/

Swagger使用的注解及其说明:

@Api:用在类上,说明该类的作用。
@ApiOperation:注解来给API增加方法说明。
@ApiParam:定义在参数上
@ApiResponses:用于表示一组响应
@ApiResponse:用在@ApiResponses中,一般用于表达一个错误的响应信息

  • code:数字,例如400
  • message:信息,例如"请求参数为空"
  • response:抛出异常的类

@ApiModel:描述一个Model的信息(一般用在请求参数无法使用@ApiImplicitParam注解进行描述的时候)

@ApiModelProperty:描述一个model的属性

@ApiImplicitParams: 用在方法上包含一组参数说明。

@ApiImplicitParam:用来注解来给方法入参增加说明。

@ApiImplicitParam的参数说明:

  • paramType:指定参数放在哪个地方
    • header:请求参数放置于Request Header,使用@RequestHeader获取
    • query:请求参数放置于请求地址,使用@RequestParam获取
    • path:(用于restful接口)–>请求参数的获取:@PathVariable body:(不常用) form(不常用)
  • name:参数名
  • dataType:参数类型
  • required:参数是否必须传 true | false
  • value:说明参数的意思
  • defaultValue:参数的默认值

通过上面的注解 , 我们可以轻松的添加内容

代码举例

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
/**
* @author Dhx_
* @className UserController
* @description TODO用户控制层
* @date 2022/10/22 16:20
*/
@Slf4j
@RestController
@RequestMapping("/user")
public class UserController {

@Resource
UserService userService;

@Resource
StringRedisTemplate stringRedisTemplate;
/**
* 发送验证码
* @param phone 手机号
*/
@PostMapping("/code")
@ApiOperation("发送验证码")
public BaseResponse<String> sendCode(@RequestParam("phone")String phone){
return userService.sendCode(phone);
}

/**
* 注册功能
* @param userRegisterDTO 封装信息到userRegisterDTO
* @return 返回用户的id
*/
@PostMapping("/register")
@ApiOperation("用户注册")
public BaseResponse<Long> register(UserRegisterDTO userRegisterDTO){
String userAccount=userRegisterDTO.getUserAccount();
String userPassword = userRegisterDTO.getUserPassword();
String checkPassword = userRegisterDTO.getCheckPassword();
return userService.register(userAccount,userPassword,checkPassword);
}

/**
* 普通登录 输入用户名以及密码登录
* @param userAccount 账户
* @param userPassword 密码
* @return 返回登录用户基本信息
*/
@PostMapping("/login")
@ApiOperation("用户登录")
public BaseResponse<UserDTO> login(@RequestParam("account")String userAccount, @RequestParam("password")String userPassword){
return userService.login(userAccount,userPassword);
}

/**
* 获取当前的用户并返回
* @return 返回当前用户基本信息
*/
@GetMapping("/current")
@ApiOperation("获取当前登录的用户的基本信息")
public BaseResponse<UserDTO> getCurrent(){
return ResultUtil.success(UserHolder.getUser());
}

/**
* 根据id 查询用户信息
* @param id 用户id
* @return UserDTO 返回用户基本信息
*/
@GetMapping("/{id}")
@ApiOperation("根据用户id获取用户基本信息")
public BaseResponse<UserDTO> queryUserById(@PathVariable("id")Long id){
return userService.queryUserById(id);
}

/**
* 查询用户详细信息 => 展示用户资料
* @param id
* @return
*/
@GetMapping("/info/{id}")
@ApiOperation("根据用户id获取用户详细信息")
public BaseResponse<User> queryUserInfoById(@PathVariable("id")Long id){
return userService.queryUserInfoById(id);
}

/**
* 根据关键词查询用户
* @param userName
* @return
*/
@GetMapping("/search")
@ApiOperation("根据关键词查询用户")
public BaseResponse<List<UserDTO>> searchUsers(@RequestParam("username")String userName){
return userService.searchUsers(userName);
}

/**
* 退出登录
* @param request
* @return
*/
@PostMapping("/logout")
@ApiOperation("退出登录")
public BaseResponse<Long> logout(HttpServletRequest request){
return userService.logout(request);
}


/**
* 编辑资料, 不允许编辑 account
* @param userUpdateDTO 包含了用户编辑信息的参数
* @return 返回用户的账户
*/
@PostMapping("/updateUserInfo")
@ApiOperation("修改用户信息")
public BaseResponse<String> updateUserInfo(UserUpdateDTO userUpdateDTO){
return userService.updateUserInfo(userUpdateDTO);
}
}

@ApiModel

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Data
@ApiModel("基本用户信息")
public class UserDTO implements Serializable {
private static final long serialVersionUID = -7089653452966045615L;

@ApiModelProperty(value = "用户id",required = false)
private Long userId;


@ApiModelProperty(value = "用户昵称",required = false)
private String userName;


@ApiModelProperty(value = "用户头像url",required = false)
private String avatarUrl;

@ApiModelProperty(value = "权限 1为管理员",required = false)
private int isAdmin;
}

使用swagger对代码进行测试

举例

swagger报错 java.lang.NumberFormatException: For input string: “”

具体报错

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
java.lang.NumberFormatException: For input string: ""
at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:65) ~[na:na]
at java.base/java.lang.Long.parseLong(Long.java:702) ~[na:na]
at java.base/java.lang.Long.valueOf(Long.java:1144) ~[na:na]
at io.swagger.models.parameters.AbstractSerializableParameter.getExample(AbstractSerializableParameter.java:412) ~[swagger-models-1.5.20.jar:1.5.20]
at jdk.internal.reflect.GeneratedMethodAccessor95.invoke(Unknown Source) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:689) ~[jackson-databind-2.11.3.jar:2.11.3]
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:755) ~[jackson-databind-2.11.3.jar:2.11.3]
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:178) ~[jackson-databind-2.11.3.jar:2.11.3]
at com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serializeContents(IndexedListSerializer.java:119) ~[jackson-databind-2.11.3.jar:2.11.3]
at com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serialize(IndexedListSerializer.java:79) ~[jackson-databind-2.11.3.jar:2.11.3]
at com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serialize(IndexedListSerializer.java:18) ~[jackson-databind-2.11.3.jar:2.11.3]
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:728) ~[jackson-databind-2.11.3.jar:2.11.3]
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:755) ~[jackson-databind-2.11.3.jar:2.11.3]
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:178) ~[jackson-databind-2.11.3.jar:2.11.3]
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:728) ~[jackson-databind-2.11.3.jar:2.11.3]
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:755) ~[jackson-databind-2.11.3.jar:2.11.3]
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:178) ~[jackson-databind-2.11.3.jar:2.11.3]
at com.fasterxml.jackson.databind.ser.std.MapSerializer.serializeFields(MapSerializer.java:726) ~[jackson-databind-2.11.3.jar:2.11.3]
at com.fasterxml.jackson.databind.ser.std.MapSerializer.serializeWithoutTypeInfo(MapSerializer.java:681) ~[jackson-databind-2.11.3.jar:2.11.3]
at com.fasterxml.jackson.databind.ser.std.MapSerializer.serialize(MapSerializer.java:637) ~[jackson-databind-2.11.3.jar:2.11.3]
at com.fasterxml.jackson.databind.ser.std.MapSerializer.serialize(MapSerializer.java:33) ~[jackson-databind-2.11.3.jar:2.11.3]
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:728) ~[jackson-databind-2.11.3.jar:2.11.3]
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:755) ~[jackson-databind-2.11.3.jar:2.11.3]
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:178) ~[jackson-databind-2.11.3.jar:2.11.3]
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider._serialize(DefaultSerializerProvider.java:480) ~[jackson-databind-2.11.3.jar:2.11.3]
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:319) ~[jackson-databind-2.11.3.jar:2.11.3]
at com.fasterxml.jackson.databind.ObjectMapper._writeValueAndClose(ObjectMapper.java:4409) ~[jackson-databind-2.11.3.jar:2.11.3]
at com.fasterxml.jackson.databind.ObjectMapper.writeValueAsString(ObjectMapper.java:3663) ~[jackson-databind-2.11.3.jar:2.11.3]
at springfox.documentation.spring.web.json.JsonSerializer.toJson(JsonSerializer.java:38) ~[springfox-spring-web-2.9.2.jar:null]
at springfox.documentation.swagger2.web.Swagger2Controller.getDocumentation(Swagger2Controller.java:105) ~[springfox-swagger2-2.9.2.jar:null]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190) ~[spring-web-5.2.12.RELEASE.jar:5.2.12.RELEASE]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138) ~[spring-web-5.2.12.RELEASE.jar:5.2.12.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105) ~[spring-webmvc-5.2.12.RELEASE.jar:5.2.12.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:878) ~[spring-webmvc-5.2.12.RELEASE.jar:5.2.12.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:792) ~[spring-webmvc-5.2.12.RELEASE.jar:5.2.12.RELEASE]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.2.12.RELEASE.jar:5.2.12.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040) ~[spring-webmvc-5.2.12.RELEASE.jar:5.2.12.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943) ~[spring-webmvc-5.2.12.RELEASE.jar:5.2.12.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.2.12.RELEASE.jar:5.2.12.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) ~[spring-webmvc-5.2.12.RELEASE.jar:5.2.12.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:626) ~[tomcat-embed-core-9.0.41.jar:4.0.FR]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.2.12.RELEASE.jar:5.2.12.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:733) ~[tomcat-embed-core-9.0.41.jar:4.0.FR]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.41.jar:9.0.41]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.2.12.RELEASE.jar:5.2.12.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.12.RELEASE.jar:5.2.12.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.2.12.RELEASE.jar:5.2.12.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.12.RELEASE.jar:5.2.12.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.2.12.RELEASE.jar:5.2.12.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.12.RELEASE.jar:5.2.12.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:888) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1597) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) ~[na:na]
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) ~[na:na]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
at java.base/java.lang.Thread.run(Thread.java:829) ~[na:na]

观察发现 , 最后一个与swagger有关的报错的地方是

第五行

io.swagger.models.parameters.AbstractSerializableParameter.getExample(AbstractSerializableParameter.java:412) ~[swagger-models-1.5.20.jar:1.5.20]

我们点进去这个io.swagger.models.parameters.AbstractSerializableParameter.getExample

源码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@JsonProperty("x-example")
public Object getExample() {
if (this.example == null) {
return null;
} else {
try {
if ("integer".equals(this.type)) {
return Long.valueOf(this.example);
}

if ("number".equals(this.type)) {
return Double.valueOf(this.example);
}

if ("boolean".equals(this.type) && ("true".equalsIgnoreCase(this.example) || "false".equalsIgnoreCase(this.defaultValue))) {
return Boolean.valueOf(this.example);
}
} catch (NumberFormatException var2) {
LOGGER.warn(String.format("Illegal DefaultValue %s for parameter type %s", this.defaultValue, this.type), var2);
}

return this.example;
}
}

这段代码的意思就是如果我们使用@ApiModelProperty注解的属性的类型是

integer double boolean

swagger就会对属性的值做出转换, 如果我们使用的是包装类 , 并且没有赋值初值, 此时就会报错

这就非常的扯淡了, swagger只对类型做出了判断, 但是却没有判断是否是空串

然后查找资料发现是swagger版本的问题,我使用的是 ==swagger2.9.2==的版本,而该版本依赖了swagger-models的1.5.20版本

(会导致报此错),但是后面的1.5.21版本对两者都进行了判断。

解决方法

==添加依赖==

1
2
3
4
5
6
7
8
9
10
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
<version>1.5.21</version>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-models</artifactId>
<version>1.5.21</version>
</dependency>

加载依赖, 重新启动 , 报错消失

@ApiModel注解 不显示问题

使用swagger的 @ApiModel注解的时候有个坑 就是必须在controller 使用 @RequestBody 注解 否则无法显示models

而且不报错,此时swagger就和 spring 耦合了,而且问题难以排查,

  1. @requestBody注解常用来处理content-type不是默认的application/x-www-form-urlcoded编码的内容,

    • 比如说:application/json或者是application/xml等。一般情况下来说常用其来处理application/json类型。
  2. 通过@requestBody可以将请求体中的JSON字符串绑定到相应的bean上,当然,也可以将其分别绑定到对应的字符串上。

  3. springBoot 中 使用@requestBody注解的话, 前端传递参数时需要JSON格式的参数,

    而且Content-Type为:application/json;charset=UTF-8 格式

@RequestBody的使用需要加载MappingJackson2HttpMessageConverter,

但是SpringBoot的官方文档提到,这个是默认已经加载的了