注解详解:@GET、@POST、@PUT、@DELETE、@HTTP 的使用场景

说实话,刚用 Retrofit 那会儿,我也老搞混这些注解。不就是 HTTP 方法嘛,但实际项目中踩了几次坑才明白——选对注解,写出来的接口才干净、好维护。今天我把它们掰开揉碎了讲,你跟着走一遍就清楚了。

Retrofit HTTP 方法注解 · 场景映射 HTTP 请求注解 @GET 查询资源 @POST 创建资源 @PUT 全量更新 @DELETE 删除资源 @HTTP 自定义方法 选型口诀 取用GET 创建用POST 全量覆盖用PUT 删资源用DELETE 特例走 @HTTP

1. @GET —— 取数据,不折腾

@GET 最常用,对应 HTTP GET 请求。说白了就是“向服务器要东西”,参数通常拼在 URL 里或通过 @Query 传。

典型使用:获取用户列表、查询订单详情、搜索商品。

public interface ApiService {
    @GET("users")
    Call<List<User>> getUsers();

    // 带查询参数
    @GET("users/search")
    Call<List<User>> searchUsers(@Query("name") String name,
                                  @Query("page") int page);
}

我的习惯:我喜欢把查询参数单独用 @QueryMap 封装起来,接口签名更清爽,尤其参数多的时候。

之前在做一个新闻客户端,首页接口用 @GET 拉栏目列表。结果 QA 反馈偶尔刷不出数据,查了半天才发现是参数名拼写错误——URL 上的参数名必须和后端约定的一模一样,大小写都敏感。嗯,从那以后我都用 @QueryMap 统一管理,再也不手写逐个参数了。

2. @POST —— 新增一条记录

@POST 用于创建资源。请求体里传数据,服务器返回创建成功的标识(通常是 ID 或完整对象)。

@POST("users")
Call<User> createUser(@Body User user);

避坑:我曾经以为 @Body 会自动忽略 null 字段,结果发现它序列化时会带上。如果后端对 null 敏感,建议配合 @JsonInclude(Include.NON_NULL) 使用。

还有,别在 @POST 里拼 URL 参数。有些新人会把查询参数也塞进 URL,看起来像 @POST("users?source=app")。这样虽然能跑,但语义不对——创建操作应该把非体量参数用 @Query 或 @Header 传,别混着用。

3. @PUT —— 全量替换

@PUT 是全量更新。你传什么,服务器就把整个资源替换成什么。如果只传了部分字段,没传的会被清空(取决于后端实现)。

@PUT("users/{id}")
Call<User> updateUser(@Path("id") int userId, @Body User user);

重点:@PUT 不是“修改个别字段”,而是“用新对象整体覆盖旧对象”。很多人搞混这个,项目里出过好几次数据丢失事故。

我记得有次做后台管理系统,同事把 @PUT 当补丁用,只传了几个字段。结果用户头像全部变成默认——因为没传头像字段,服务器直接覆盖成 null。那以后我们规定:部分更新必须用 @PATCH(虽然 Retrofit 不内置,但 @HTTP 可以搞定)。

4. @DELETE —— 删了就别想找回来

@DELETE 语义最明确,删除指定资源。通常只需要传个 ID。

@DELETE("users/{id}")
Call<ResponseBody> deleteUser(@Path("id") int userId);

小技巧:返回类型我习惯用 Call<ResponseBody>,因为删除成功一般只关心状态码,不需要解析 body。

有个细节:某些服务端删除接口要求传请求体(比如软删除时带备注)。这时候 @DELETE 可以搭配 @Body 吗?理论上 OK,但 Retrofit 默认的 DELETE 会忽略 body。我遇到过这种情况,最终用 @HTTP 自定义解决了——往下看。

5. @HTTP —— 万能自定义工具

@HTTP 是 Retrofit 最后一张牌。当标准注解搞不定时,就用它。

// 自定义 DELETE 带 Body
@HTTP(method = "DELETE", path = "users/{id}", hasBody = true)
Call<ResponseBody> deleteUserWithBody(@Path("id") int userId,
                                       @Body DeleteRequest body);

// 自定义 PATCH(部分更新)
@HTTP(method = "PATCH", path = "users/{id}", hasBody = true)
Call<User> patchUser(@Path("id") int userId, @Body Map<String, Object> fields);

// 自定义 HEAD
@HTTP(method = "HEAD", path = "version", hasBody = false)
Call<Void> checkVersion();

适用场景:

  • 需要 PATCH 方法时
  • 标准注解不允许添加请求体时(比如 @DELETE 加 body)
  • 非标准 HTTP 方法(如 MOVE、COPY)

曾经踩过的坑:我之前在对接第三方支付 API 时,对方要求用 PURGE 方法清缓存。Retrofit 没有这个注解,当时差点用 @POST 冒充。后来用 @HTTP(method = "PURGE", ...) 完美解决。所以遇到奇葩方法,别硬套,直接用 @HTTP 自定义。

6. 快速指南:如何挑选注解

下面这个表是我自己总结的,你可以直接收藏当参考。

注解HTTP 方法核心用途请求体幂等
@GETGET查询/读取资源否是
@POSTPOST创建资源是否
@PUTPUT全量更新/替换是是
@DELETEDELETE删除资源通常无是
@HTTP自定义非标准方法/PATCH/带体DELETE可配看实现

一句话口诀:取用GET,建用POST,全改PUT,删用DELETE,特殊走 @HTTP。

这五个注解覆盖了 99% 的日常需求。你写接口时多想想:我这次操作是“查”还是“改”?是全量还是部分?想清楚了,注解选起来就很简单。嗯,今天就到这,下回见。