Spring REST Controller,在GET方式下,有多个参数时的处理

现在越来越多的服务都转向使用RESTful了,我们的项目也不例外,使用spring来做了REST。在采用RESTful的时候,我们会严格按照约定来使用 HTTP METHOD:

  • GET: 查询
  • POST: 创建
  • PUT: 修改
  • DELETE: 删除

本来,按照这种方式来做的时候,开发都很方便。不过,最近遇到一个问题:

在一个查询接口中,需要的参数比较多,如果还是使用GET方式进行请求的话,那么,Controller 中的方法的参数列表将会非常多,如:

public List<String> getName(@RequestParam String query1,
                            @RequestParam String query2,
                            @RequestParam String query3,
                            ......) {
        return new ArrayList<>();
}

很明显,这样的话,将会导致这个方法太难看 : ( 。

那么,该如何解决这个问题呢?下面说说我的思路:

方法一
换成POST请求,将所有参数封装成一个类,然后使用 @RequestBody注解将参数自动解析成该类的一个实例,如:

public List<String> getName(@RequestBody QueryDto queryDto) {
        return new ArrayList<>();
}

public class QueryDto {
    private String query1;
    private String query2;
    private String query3;

    // getter, setter ...
}

不过,有些人可能会纠结于上面的 RESTful“规范”,认为POST不应该用来进行查询。
对,这么想的确是合理的,不过,这个“规范”只是建议大家这么来遵守,并不是强制要求。有兴趣的,可以看看京东的请求,它的部分查询请求也是用的POST

方法二
还是使用GET请求,但是将所有请求参数通过JSON格式来传递,controller拿到参数后,使用 JSON 相关的库(如 gson),将该JSON转化为相应的对象,如:

public List<String> getName(@RequestParam String queryDtoStr) {
        QueryDto queryDto = new Gson().fromJson(queryDtoStr, QueryDto .class);
        // ....
        return new ArrayList<>();
}

public class QueryDto {
    private String query1;
    private String query2;
    private String query3;

    // getter, setter ...
}

这种情况下,请求的URL应该是类似于下面这样的:

http://localhost:8080/app/names?queryDtoStr={"query1":12,"query2":2,"query3":2}

当然,为了避免参数中出现 #&等特殊字符,最好是采用 encodeURIComponent对参数进行转义,
具体的请参见我的另一份blog:Ajax 以GET方式请求时,参数中包含 “#” 特殊字符的处理

方法三
在网法搜索时,发现有一种说法,说“GET请求也可以带body”,如果这个可以的话,就不用像上面方法一二那样麻烦了。直接使用GET + @RequestBody即可。

不过,我没试过,也不知道怎么试,我还是想用正常的方式,即:

  • get 的参数放在 URL 后面
  • post 的参数放在body中
<think>Swagger和SpringRESTDocs在生成文档的本质区别在于文档生成的方式和目的:1.**Swagger(OpenAPI)**:-**方式**:通过代码注解(如`@Api`、`@Operation`等)在源代码中直接描述API,运行由库(如springdoc-openapi)解析注解并生成交互式文档(通常为HTML页面)。-**目的**:提供实的、可交互的API文档,允许开发者在文档页面上直接测试API。2.**SpringRESTDocs**:-**方式**:通过编写测试用例(如MockMvc测试)来验证API,并在测试过程中生成文档片段(如Asciidoc或Markdown片段)。文档内容来自测试用例中的描述,然后通过工具(如Asciidoctor)将片段整合成完整的文档。-**目的**:确保文档与代码实现一致(因为文档由测试生成,测试通过才生成文档),并且生成的文档更注重准确性和可维护性,适合作为正式文档发布。**本质区别总结**:-**Swagger**:文档与代码强耦合,注解写在代码中,运行动态生成文档,适合快速开发和调试。-**SpringRESTDocs**:文档与代码分离,文档内容由测试驱动生成,保证文档的准确性,适合需要高质量文档的项目。**代码示例对比**:1.**Swagger注解方式(在Controller中添加注解)**:```java@RestController@Tag(name="UserAPI",description="Operationspertainingtousermanagement")publicclassUserController{@Operation(summary="GetauserbyID",description="ReturnsasingleuserbytheirID")@ApiResponse(responseCode="200",description="Userfound")@ApiResponse(responseCode="404",description="Usernotfound")@GetMapping("/users/{id}")publicUsergetUser(@PathVariableLongid){//...}}```2.**SpringRESTDocs方式(通过测试生成文档)**:```java@SpringBootTest@AutoConfigureRestDocs//启用RESTDocspublicclassUserDocumentation{@AutowiredprivateMockMvcmockMvc;@TestpublicvoidgetUserById()throwsException{mockMvc.perform(get("/users/{id}",1)).andExpect(status().isOk()).andDo(document("get-user-by-id",pathParameters(parameterWithName("id").description("TheuserID")),responseFields(fieldWithPath("id").description("TheuserID"),fieldWithPath("name").description("Theusername"))));}}```**结论**:选择工具取决于项目需求:-需要快速生成可交互的文档并支持在线测试->Swagger-需要高准确性、可维护的离线文档(如PDF)->SpringRESTDocs§§相关问题§§:1.如何在SpringBoot项目中同使用Swagger和SpringRESTDocs?2.SpringRESTDocs生成的文档片段如何整合成完整的API文档?3.Swagger注解和SpringRESTDocs测试用例是否可以共享API描述信息以避免重复?4.在使用SpringRESTDocs,如何处理API版本变化导致的文档更新?</think>### Swagger 和 Spring REST Docs 的本质区别 #### 1. **核心设计理念** **Swagger (OpenAPI)**: - **运行文档生成**:通过注解直接嵌入业务代码 - **文档即代码**:API描述与实现代码强耦合 - **交互式文档**:自动生成可执行的Web UI(Swagger UI) - **示例**: ```java @Operation(summary = "创建用户", description = "通过JSON创建新用户") @PostMapping("/users") public User createUser(@RequestBody User user) { return userService.save(user); } ``` **Spring REST Docs**: - **测试驱动文档**:文档通过单元测试生成 - **文档与代码分离**:API描述独立于业务代码 - **静态文档输出**:生成Asciidoc/Markdown等静态文件 - **示例**: ```java mockMvc.perform(post("/users") .content(jsonUser) .contentType(MediaType.APPLICATION_JSON)) .andExpect(status().isCreated()) .andDo(document("create-user", requestFields( fieldWithPath("name").description("用户名"), fieldWithPath("email").description("邮箱") ))); ``` #### 2. **文档生成机制** | 维度 | Swagger | Spring REST Docs | |--------------------|----------------------------------|----------------------------------| | **触发机** | 应用运行动态生成 | 构建通过测试生成 | | **准确性保证** | 可能滞后于实际实现 | 测试通过才生成文档(强制同步) | | **更新机制** | 修改注解后重启生效 | 修改测试后重新执行测试生成 | | **输出格式** | HTML/JSON (OpenAPI规范) | Asciidoc/Markdown (可转HTML/PDF) | #### 3. **工作流程对比** **Swagger 流程**: ``` 业务代码 → 添加注解 → 启动应用 → 访问 /swagger-ui → 动态渲染文档 ``` **Spring REST Docs 流程**: ``` 编写测试用例 → 执行测试 → 生成文档片段 → 整合片段 → 构建最终文档 ``` #### 4. **核心差异总结** | 特性 | Swagger | Spring REST Docs | |--------------------|----------------------------------|----------------------------------| | **耦合性** | 与代码强耦合 | 与实现解耦 | | **可靠性** | 文档可能过 | 文档=测试验证后的真实行为 | | **维护成本** | 需同步维护代码和注解 | 修改API必须更新测试用例 | | **定制能力** | UI定制受限 | 完全控制文档结构和样式 | | **适用场景** | 快速原型/调试 | 正式发布文档/API规范 | #### 5. **本质区别可视化** ```mermaid graph LR A[API实现] --> B[Swagger] A --> C[Spring REST Docs] B --> D[注解描述] --> E[运行生成HTML] C --> F[测试验证] --> G[构建生成Asciidoc] ``` **关键结论**: - **Swagger** 本质是 *描述性文档*,通过注解声明API行为 - **Spring REST Docs** 本质是 *验证性文档*,通过测试证明API行为 - 前者适合**开发阶段快速迭代**,后者适合**交付高质量正式文档** ---
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值