RESTful 风格编程
RESTful(Representational State Transfer)架构风格是一种网络应用程序的设计风格和开发方式,基于HTTP协议,可以利用URI(Uniform Resource Identifier)来访问和操作资源。在RESTful设计中,资源的组织和访问遵循一定的原则,以提高系统的可读性和可维护性。
资源请求方式
GET
操作: 用于读取(Read)资源。不改变服务器状态,只是获取信息。springboot后端通常用@RequestParam,@PathVariable或者对象接收。
例子: GET /users/123 用来获取ID为123的用户信息。
POST
操作: 用于创建(Create)新资源。通常向服务器发送数据,服务器会创建一个新的资源并返回其位置或标识。springboot后端通常用@RequestBody 对象接收。
例子: POST /users 可能伴随着用户信息的JSON数据,用于创建一个新的用户账户。
PUT
操作: 用于更新(Update)已有资源的全部信息。要求客户端提供完整的资源表示。springboot后端通常用@RequestBody 对象接收。
例子: PUT /users/123 可能包含用户的完整更新信息,更新ID为123的用户记录。
PATCH
操作: 用于更新(Update)已有资源的部分信息。与PUT不同,它只更新资源的部分属性。springboot后端通常用@RequestBody 对象接收。
例子: PATCH /users/123 可能只包含需要修改的用户属性,如邮箱或密码。
DELETE
操作: 用于删除(Delete)指定资源。springboot后端通常用@RequestParam或者@PathVariable接收。
例子: DELETE /users/123 用来删除ID为123的用户记录。
6. OPTIONS:
操作: 用于获取服务器支持的HTTP方法,常用于 CORS(跨源资源共享)预检请求。
例子: OPTIONS /users/123 可以用来询问关于特定资源的可用HTTP方法。
通过Body传递参数的常见方式
application/x-www-form-urlencoded
- 用于发送URL编码的键值对,适合发送简单的表单(一般指只含有文本)数据。编码后的数据量更小。许多RESTful API在不需要上传文件时,可以使用此格式来传递参数,因为它简洁且易于解析,且网络传输较小。
- Spring Boot接收: 使用@RequestParam注解来接收这些键值对。
- 示例: 简单的登录表单,用户名和密码。参数编码为username=admin&password=123456
- Content-Type: application/x-www-form-urlencoded。这种格式下,数据会被编码为键值对,并按照URL编码规则进行编码。
multipart/form-data
- 用于上传文件或者发送键值对形式的非文件数据,常用于多部分表单(数据类型不同,除了文本,一般还含有文件)数据提交。
- Spring Boot接收: 对于文件上传,可以使用@RequestParam(“file”) MultipartFile file来接收。对于非文件字段,也可以使用@RequestParam来接收各个表单项。
- Content-Type: multipart/form-data; boundary=<boundary>。这里的<boundary>是一个由客户端生成的唯一字符串,用来分隔请求中的不同部分。
raw
- 发送原始数据,可以是JSON、XML、HTML、纯文本等。这中方式在post方式中,如果不涉及文件,是较为常用的。
- Spring Boot接收: 如果是JSON数据,应该使用@RequestBody YourModelClass object来接收,其中YourModelClass对应数据结构的Java类。对于其他格式,可以根据实际内容选择合适的处理方式。
- Content-Type: 根据实际选择的原始数据类型决定。例如,如果选择发送JSON数据,则为application/json; 如果是XML,则为application/xml; 纯文本为text/plain等。
binary
- 直接上传二进制文件到服务器,没有额外的表单字段,用于发送二进制数据,如图片、音频、视频等,不包含任何额外的键值对信息。
- Spring Boot接收: 可以直接读取InputStream,或者根据具体情况定义处理器。如果是特定类型的数据,可以考虑自定义处理器来直接操作输入流。
- Content-Type: 根据实际上传的二进制文件类型设定。例如,图片可能是image/jpeg、image/png等;PDF文件则是application/pdf。
参数传递方式
在RESTful架构中,HTTP请求支持多种传参方式,这些方式主要应用于与资源交互的不同场景。以下是几种常见的传参方式:
查询参数(Query Parameters)
主要用于GET, DELETE, 通过URL中的?后面附加键值对来传递参数。适用于过滤、排序、分页等非核心资源标识的信息。SpringBoot通过@RequestParam接收。
例子: GET /users?name=John&age=30 请求年龄为30,名为John的用户列表。
路径参数(Path Variables)
主要用于GET, DELETE,直接将参数值嵌入到URL路径中,用以标识资源的一部分。 SpringBoot通过@PathVariable接收。
例子: DELETE /users/123 中的123是路径参数,用来指定删除ID为123的用户信息。
请求体(Request Body)
主要用于POST、PUT、PATCH等请求
-
将复杂的数据结构(如JSON、XML)放在请求体中传递。 SpringBoot通过@RequesetBody接收
例子:在创建用户时,POST /users 可能携带包含用户名、邮箱、密码等信息的JSON对象。 -
表单参数(Form Parameters)
通常与POST请求一起使用,特别是上传文件或简单表单数据时。可以是application/x-www-form-urlencoded或multipart/form-data格式。 SpringBoot通过@RequestParam接收。
例子: 用户注册时,提交用户名和密码等信息。 -
二进制
直接上传二进制流,如图片,音频,视频等
Header参数
在HTTP头部中携带元数据或认证信息,如Authorization头用于携带认证令牌。
例子: GET /protected-resource 请求头中包含Authorization: Bearer {token}。
Cookie参数
虽不常用于RESTful服务,但也可以通过Cookie传递会话信息或用户偏好设置。
例子: 维持用户登录状态。
注意事项
- 安全性: 敏感信息不应通过查询参数传递,因为它们可能会被记录在浏览器历史、服务器日志中。
- 幂等性: GET、PUT、DELETE和PATCH(如果实现得当)是幂等的,意味着多次请求具有相同的效果;而POST不是幂等的,每次请求都会创建新的资源。
- 内容协商: 通过请求头(如Accept和Content-Type)来决定响应和请求体的内容类型,是RESTful服务中常见的实践。
- OPTIONS通常不涉及参数传递。此方法用于获取服务器支持的HTTP方法,响应中包含Allow头部列出了允许的方法。
@RequestParam @PathVariable @RequestBody 三者的使用场景
在Spring框架中,@RequestParam
, @PathVariable
, 和 @RequestBody
是用于处理HTTP查询参数的注解,它们各有不同的使用场景:
@RequestParam
- 当需要从请求的查询字符串(query string,即URL中
?
后面的部分)中获取参数值时,使用@RequestParam
。 - 表单数据处理,包含简单表单和多部份表单
@PathVariable
- 如果URL中包含变量部分(通过大括号
{}
标识),并将这些部分映射到方法参数上,就应使用@PathVariable
。 - 动态路由:在构建具有高度动态性的路由时,@PathVariable可以用来捕获URL中变化的部分,实现灵活的路由映射。例如,博客系统的文章页面可能使用/articles/{year}/{month}/{day}/{slug}来支持日期和文章别名的动态路由。
- 路径模式匹配:Spring框架允许在@PathVariable中使用正则表达式来限制路径变量的值,从而实现更精细的控制。例如,@PathVariable(“id”) @Pattern(regexp=“[0-9]+”) String id确保了ID只能是数字序列。
@RequestBody
- 当请求体(body)包含了一些结构化的数据,比如JSON或XML,并将这些数据绑定到Java对象时,使用
@RequestBody
。这在处理POST、PUT等请求,特别是包含复杂数据结构的请求时非常有用。 - 复杂数据绑定:除了处理JSON或XML,@RequestBody还可以与其他数据格式一起工作,比如处理表单数据(当Content-Type为application/x-www-form-urlencoded或multipart/form-data,结合MultiValueMap或自定义对象)。
- 分块上传或流式处理:当处理大型文件上传或需要高效利用内存时,可以将@RequestBody与StreamingResponseBody或Flux<DataBuffer>配合,实现数据的流式处理,特别是在WebFlux等反应式编程模型中。
- 内容协商:@RequestBody与@Consumes注解结合使用,可以实现内容协商机制,根据请求头中的Accept字段选择合适的数据处理逻辑,支持多种数据格式的请求体处理。
- 自定义反序列化:在某些情况下,可能需要对请求体进行自定义的反序列化处理,可以通过实现HttpMessageConverter接口来自定义转换逻辑,@RequestBody可以利用这些自定义转换器来处理特殊格式的请求体。
特殊情况下的参数传递
- 有多个id需要传递
- 将多个id拼接为字符串,通过查询参数或者路径参数传递, 然后后端解析:xx/user?ids=1,2,3; xx/user/1,2,3
- 前端传递数组
- 通过查询参数传递:GET /knowledge/testObj/list?pageNum=1&pageSize=10&type[0]=3&type[1]=6
- 通过请求体传递:{“type”: [1,2] }
以上两种情况,后端可以通过对象接收
class A {
···
int[] type;
}
也可以解析HttpServletRequest 对象,或者自定义HandlerMethodArgumentResolver解析器。
愿你我都能在各自的领域里不断成长,勇敢追求梦想,同时也保持对世界的好奇与善意。