753 lines
19 KiB
Markdown
753 lines
19 KiB
Markdown
# HTTP Restful工具文档
|
||
|
||
## 概述
|
||
|
||
HTTP Restful工具提供了标准化的HTTP请求和响应处理功能,提供公共方法供外部调用,保持低耦合。
|
||
|
||
## 功能特性
|
||
|
||
- **低耦合设计**:提供公共方法,不封装Handler结构
|
||
- **标准化的响应结构**:`{code, message, timestamp, data}`
|
||
- **分离HTTP状态码和业务状态码**
|
||
- **支持分页响应**
|
||
- **提供便捷的请求参数解析方法**
|
||
- **支持JSON请求体解析**
|
||
- **Factory黑盒模式**:推荐使用 `factory.Success()` 等方法
|
||
|
||
## 响应结构
|
||
|
||
### 标准响应结构
|
||
|
||
```json
|
||
{
|
||
"code": 0,
|
||
"message": "success",
|
||
"timestamp": 1704067200,
|
||
"data": {}
|
||
}
|
||
```
|
||
|
||
**结构体类型(暴露在 factory 中):**
|
||
|
||
```go
|
||
// 在 factory 包中可以直接使用
|
||
type Response struct {
|
||
Code int `json:"code"` // 业务状态码,0表示成功
|
||
Message string `json:"message"` // 响应消息
|
||
Timestamp int64 `json:"timestamp"` // 时间戳
|
||
Data interface{} `json:"data"` // 响应数据
|
||
}
|
||
```
|
||
|
||
### 分页响应结构
|
||
|
||
```json
|
||
{
|
||
"code": 0,
|
||
"message": "success",
|
||
"timestamp": 1704067200,
|
||
"data": {
|
||
"list": [],
|
||
"total": 100,
|
||
"page": 1,
|
||
"pageSize": 10
|
||
}
|
||
}
|
||
```
|
||
|
||
**结构体类型(暴露在 factory 中):**
|
||
|
||
```go
|
||
// 在 factory 包中可以直接使用
|
||
type PageData struct {
|
||
List interface{} `json:"list"` // 数据列表
|
||
Total int64 `json:"total"` // 总记录数
|
||
Page int `json:"page"` // 当前页码
|
||
PageSize int `json:"pageSize"` // 每页大小
|
||
}
|
||
|
||
type PageResponse struct {
|
||
Code int `json:"code"`
|
||
Message string `json:"message"`
|
||
Timestamp int64 `json:"timestamp"`
|
||
Data *PageData `json:"data"`
|
||
}
|
||
```
|
||
|
||
### 使用暴露的结构体
|
||
|
||
外部项目可以直接使用 `factory.Response`、`factory.PageData` 等类型:
|
||
|
||
```go
|
||
import "git.toowon.com/jimmy/go-common/factory"
|
||
|
||
// 创建标准响应对象
|
||
response := factory.Response{
|
||
Code: 0,
|
||
Message: "success",
|
||
Data: userData,
|
||
}
|
||
|
||
// 创建分页数据对象
|
||
pageData := &factory.PageData{
|
||
List: users,
|
||
Total: 100,
|
||
Page: 1,
|
||
PageSize: 20,
|
||
}
|
||
|
||
// 传递给 Success 方法
|
||
fac.Success(w, pageData)
|
||
```
|
||
|
||
## 使用方法
|
||
|
||
### 方式一:使用Factory黑盒方法(推荐)⭐
|
||
|
||
这是最简单的方式,直接使用 `factory.Success()` 等方法:
|
||
|
||
```go
|
||
import (
|
||
"net/http"
|
||
"git.toowon.com/jimmy/go-common/factory"
|
||
commonhttp "git.toowon.com/jimmy/go-common/http"
|
||
)
|
||
|
||
func GetUser(w http.ResponseWriter, r *http.Request) {
|
||
fac, _ := factory.NewFactoryFromFile("config.json")
|
||
|
||
// 获取查询参数(使用公共方法)
|
||
id := commonhttp.GetQueryInt64(r, "id", 0)
|
||
|
||
// 返回成功响应(使用factory方法)
|
||
fac.Success(w, data)
|
||
}
|
||
|
||
func CreateUser(w http.ResponseWriter, r *http.Request) {
|
||
fac, _ := factory.NewFactoryFromFile("config.json")
|
||
|
||
// 解析JSON(使用公共方法)
|
||
var req struct {
|
||
Name string `json:"name"`
|
||
}
|
||
if err := commonhttp.ParseJSON(r, &req); err != nil {
|
||
commonhttp.WriteJSON(w, http.StatusBadRequest, 400, "请求参数解析失败", nil)
|
||
return
|
||
}
|
||
|
||
// 返回成功响应(使用factory方法)
|
||
fac.Success(w, data, "创建成功")
|
||
}
|
||
|
||
func GetUserList(w http.ResponseWriter, r *http.Request) {
|
||
fac, _ := factory.NewFactoryFromFile("config.json")
|
||
|
||
// 获取分页参数(使用factory方法,推荐)
|
||
pagination := fac.ParsePaginationRequest(r)
|
||
page := pagination.GetPage()
|
||
pageSize := pagination.GetSize()
|
||
|
||
// 获取查询参数(使用factory方法,推荐)
|
||
keyword := fac.GetQuery(r, "keyword", "")
|
||
|
||
// 查询数据
|
||
list, total := getDataList(keyword, page, pageSize)
|
||
|
||
// 返回分页响应(使用factory方法)
|
||
fac.SuccessPage(w, list, total, page, pageSize)
|
||
}
|
||
|
||
// 注册路由
|
||
http.HandleFunc("/user", GetUser)
|
||
http.HandleFunc("/users", GetUserList)
|
||
```
|
||
|
||
### 方式二:直接使用公共方法
|
||
|
||
如果不想使用Factory,可以直接使用 `http` 包的公共方法:
|
||
|
||
```go
|
||
import (
|
||
"net/http"
|
||
commonhttp "git.toowon.com/jimmy/go-common/http"
|
||
)
|
||
|
||
func GetUser(w http.ResponseWriter, r *http.Request) {
|
||
// 获取查询参数
|
||
id := commonhttp.GetQueryInt64(r, "id", 0)
|
||
|
||
// 返回成功响应
|
||
commonhttp.Success(w, data)
|
||
}
|
||
|
||
func CreateUser(w http.ResponseWriter, r *http.Request) {
|
||
// 解析JSON
|
||
var req struct {
|
||
Name string `json:"name"`
|
||
}
|
||
if err := commonhttp.ParseJSON(r, &req); err != nil {
|
||
commonhttp.WriteJSON(w, http.StatusBadRequest, 400, "请求参数解析失败", nil)
|
||
return
|
||
}
|
||
|
||
// 返回成功响应
|
||
commonhttp.Success(w, data, "创建成功")
|
||
}
|
||
```
|
||
|
||
### 成功响应
|
||
|
||
```go
|
||
// 使用Factory(推荐)
|
||
fac.Success(w, data) // 只有数据,使用默认消息 "success"
|
||
fac.Success(w, data, "操作成功") // 数据+消息
|
||
|
||
// 或直接使用公共方法
|
||
commonhttp.Success(w, data) // 只有数据
|
||
commonhttp.Success(w, data, "操作成功") // 数据+消息
|
||
```
|
||
|
||
### 错误响应
|
||
|
||
```go
|
||
// 使用Factory(推荐)
|
||
fac.Error(w, 1001, "用户不存在") // 业务错误(HTTP 200,业务code非0)
|
||
fac.SystemError(w, "服务器内部错误") // 系统错误(HTTP 500)
|
||
|
||
// 或直接使用公共方法
|
||
commonhttp.Error(w, 1001, "用户不存在")
|
||
commonhttp.SystemError(w, "服务器内部错误")
|
||
commonhttp.WriteJSON(w, http.StatusBadRequest, 400, "请求参数错误", nil) // 自定义HTTP状态码(仅公共方法)
|
||
```
|
||
|
||
### 分页响应
|
||
|
||
```go
|
||
// 使用Factory(推荐)
|
||
fac.SuccessPage(w, list, total, page, pageSize)
|
||
fac.SuccessPage(w, list, total, page, pageSize, "查询成功")
|
||
|
||
// 或直接使用公共方法
|
||
commonhttp.SuccessPage(w, list, total, page, pageSize)
|
||
commonhttp.SuccessPage(w, list, total, page, pageSize, "查询成功")
|
||
```
|
||
|
||
### 解析请求
|
||
|
||
#### 解析JSON请求体
|
||
|
||
```go
|
||
// 使用公共方法
|
||
var req struct {
|
||
Name string `json:"name"`
|
||
Email string `json:"email"`
|
||
}
|
||
|
||
if err := commonhttp.ParseJSON(r, &req); err != nil {
|
||
commonhttp.WriteJSON(w, http.StatusBadRequest, 400, "请求参数解析失败", nil)
|
||
return
|
||
}
|
||
```
|
||
|
||
#### 获取查询参数
|
||
|
||
```go
|
||
// 使用公共方法
|
||
name := commonhttp.GetQuery(r, "name", "")
|
||
id := commonhttp.GetQueryInt(r, "id", 0)
|
||
userId := commonhttp.GetQueryInt64(r, "userId", 0)
|
||
isActive := commonhttp.GetQueryBool(r, "isActive", false)
|
||
price := commonhttp.GetQueryFloat64(r, "price", 0.0)
|
||
```
|
||
|
||
#### 获取表单参数
|
||
|
||
```go
|
||
// 使用公共方法
|
||
name := commonhttp.GetFormValue(r, "name", "")
|
||
age := commonhttp.GetFormInt(r, "age", 0)
|
||
userId := commonhttp.GetFormInt64(r, "userId", 0)
|
||
isActive := commonhttp.GetFormBool(r, "isActive", false)
|
||
```
|
||
|
||
#### 获取请求头
|
||
|
||
```go
|
||
// 使用公共方法
|
||
token := commonhttp.GetHeader(r, "Authorization", "")
|
||
contentType := commonhttp.GetHeader(r, "Content-Type", "application/json")
|
||
```
|
||
|
||
#### 获取分页参数
|
||
|
||
**方式1:使用 PaginationRequest 结构(推荐)**
|
||
|
||
```go
|
||
// 定义请求结构(包含分页字段)
|
||
type ListUserRequest struct {
|
||
Keyword string `json:"keyword"`
|
||
commonhttp.PaginationRequest // 嵌入分页请求结构
|
||
}
|
||
|
||
// 从JSON请求体解析(分页字段会自动解析)
|
||
var req ListUserRequest
|
||
if err := commonhttp.ParseJSON(r, &req); err != nil {
|
||
commonhttp.WriteJSON(w, http.StatusBadRequest, 400, "请求参数解析失败", nil)
|
||
return
|
||
}
|
||
|
||
// 使用分页方法
|
||
page := req.GetPage() // 获取页码(默认1)
|
||
size := req.GetSize() // 获取每页数量(默认20,最大100,优先使用page_size)
|
||
offset := req.GetOffset() // 计算偏移量
|
||
```
|
||
|
||
**方式2:从查询参数/form解析分页**
|
||
|
||
```go
|
||
// 使用公共方法
|
||
pagination := commonhttp.ParsePaginationRequest(r)
|
||
page := pagination.GetPage()
|
||
size := pagination.GetSize()
|
||
offset := pagination.GetOffset()
|
||
```
|
||
|
||
#### 获取时区
|
||
|
||
```go
|
||
// 使用公共方法
|
||
// 如果使用了middleware.Timezone中间件,可以从context中获取时区信息
|
||
// 如果未设置,返回默认时区 AsiaShanghai
|
||
timezone := commonhttp.GetTimezone(r)
|
||
```
|
||
|
||
## 完整示例
|
||
|
||
### 使用Factory(推荐)
|
||
|
||
```go
|
||
package main
|
||
|
||
import (
|
||
"log"
|
||
"net/http"
|
||
"git.toowon.com/jimmy/go-common/factory"
|
||
commonhttp "git.toowon.com/jimmy/go-common/http"
|
||
)
|
||
|
||
// 用户结构
|
||
type User struct {
|
||
ID int64 `json:"id"`
|
||
Name string `json:"name"`
|
||
Email string `json:"email"`
|
||
}
|
||
|
||
// 用户列表接口
|
||
func GetUserList(w http.ResponseWriter, r *http.Request) {
|
||
fac, _ := factory.NewFactoryFromFile("config.json")
|
||
|
||
// 获取分页参数(使用公共方法)
|
||
pagination := commonhttp.ParsePaginationRequest(r)
|
||
page := pagination.GetPage()
|
||
pageSize := pagination.GetSize()
|
||
|
||
// 获取查询参数(使用公共方法)
|
||
keyword := commonhttp.GetQuery(r, "keyword", "")
|
||
|
||
// 查询数据
|
||
users, total := queryUsers(keyword, page, pageSize)
|
||
|
||
// 返回分页响应(使用factory方法)
|
||
fac.SuccessPage(w, users, total, page, pageSize)
|
||
}
|
||
|
||
// 创建用户接口
|
||
func CreateUser(w http.ResponseWriter, r *http.Request) {
|
||
fac, _ := factory.NewFactoryFromFile("config.json")
|
||
|
||
// 解析请求体(使用公共方法)
|
||
var req struct {
|
||
Name string `json:"name"`
|
||
Email string `json:"email"`
|
||
}
|
||
|
||
if err := commonhttp.ParseJSON(r, &req); err != nil {
|
||
fac.WriteJSON(w, http.StatusBadRequest, 400, "请求参数解析失败", nil)
|
||
return
|
||
}
|
||
|
||
// 参数验证
|
||
if req.Name == "" {
|
||
fac.Error(w, 1001, "用户名不能为空")
|
||
return
|
||
}
|
||
|
||
// 创建用户
|
||
user, err := createUser(req.Name, req.Email)
|
||
if err != nil {
|
||
fac.SystemError(w, "创建用户失败")
|
||
return
|
||
}
|
||
|
||
// 返回成功响应(使用factory方法)
|
||
fac.Success(w, user, "创建成功")
|
||
}
|
||
|
||
// 获取用户详情接口
|
||
func GetUser(w http.ResponseWriter, r *http.Request) {
|
||
fac, _ := factory.NewFactoryFromFile("config.json")
|
||
|
||
// 获取查询参数(使用factory方法,推荐)
|
||
id := fac.GetQueryInt64(r, "id", 0)
|
||
|
||
if id == 0 {
|
||
commonhttp.WriteJSON(w, http.StatusBadRequest, 400, "用户ID不能为空", nil)
|
||
return
|
||
}
|
||
|
||
// 查询用户
|
||
user, err := getUserByID(id)
|
||
if err != nil {
|
||
fac.SystemError(w, "查询用户失败")
|
||
return
|
||
}
|
||
|
||
if user == nil {
|
||
fac.Error(w, 1002, "用户不存在")
|
||
return
|
||
}
|
||
|
||
// 返回成功响应(使用factory方法)
|
||
fac.Success(w, user)
|
||
}
|
||
|
||
func main() {
|
||
http.HandleFunc("/users", func(w http.ResponseWriter, r *http.Request) {
|
||
switch r.Method {
|
||
case http.MethodGet:
|
||
GetUserList(w, r)
|
||
case http.MethodPost:
|
||
CreateUser(w, r)
|
||
default:
|
||
commonhttp.WriteJSON(w, http.StatusMethodNotAllowed, 405, "方法不支持", nil)
|
||
}
|
||
})
|
||
|
||
http.HandleFunc("/user", GetUser)
|
||
|
||
log.Println("Server started on :8080")
|
||
log.Fatal(http.ListenAndServe(":8080", nil))
|
||
}
|
||
```
|
||
|
||
## API 参考
|
||
|
||
### Factory HTTP响应结构体(暴露给外部项目使用)
|
||
|
||
#### Response
|
||
|
||
标准响应结构体,外部项目可以直接使用 `factory.Response`。
|
||
|
||
**字段:**
|
||
- `Code`: 业务状态码,0表示成功
|
||
- `Message`: 响应消息
|
||
- `Timestamp`: 时间戳(Unix时间戳,秒)
|
||
- `Data`: 响应数据
|
||
|
||
**示例:**
|
||
```go
|
||
response := factory.Response{
|
||
Code: 0,
|
||
Message: "success",
|
||
Data: userData,
|
||
}
|
||
```
|
||
|
||
#### PageData
|
||
|
||
分页数据结构体,外部项目可以直接使用 `factory.PageData`。
|
||
|
||
**字段:**
|
||
- `List`: 数据列表
|
||
- `Total`: 总记录数
|
||
- `Page`: 当前页码
|
||
- `PageSize`: 每页大小
|
||
|
||
**示例:**
|
||
```go
|
||
pageData := &factory.PageData{
|
||
List: users,
|
||
Total: 100,
|
||
Page: 1,
|
||
PageSize: 20,
|
||
}
|
||
fac.Success(w, pageData)
|
||
```
|
||
|
||
#### PageResponse
|
||
|
||
分页响应结构体,外部项目可以直接使用 `factory.PageResponse`。
|
||
|
||
**字段:**
|
||
- `Code`: 业务状态码
|
||
- `Message`: 响应消息
|
||
- `Timestamp`: 时间戳
|
||
- `Data`: 分页数据(*PageData)
|
||
|
||
### Factory HTTP响应方法(推荐使用)
|
||
|
||
#### (f *Factory) Success(w http.ResponseWriter, data interface{}, message ...string)
|
||
|
||
成功响应,HTTP 200,业务code 0。
|
||
|
||
**参数:**
|
||
- `data`: 响应数据,可以为nil
|
||
- `message`: 响应消息(可选),如果为空则使用默认消息 "success"
|
||
|
||
**示例:**
|
||
```go
|
||
fac.Success(w, data) // 只有数据,使用默认消息 "success"
|
||
fac.Success(w, data, "操作成功") // 数据+消息
|
||
```
|
||
|
||
#### (f *Factory) Error(w http.ResponseWriter, code int, message string)
|
||
|
||
业务错误响应,HTTP 200,业务code非0。
|
||
|
||
**示例:**
|
||
```go
|
||
fac.Error(w, 1001, "用户不存在")
|
||
```
|
||
|
||
#### (f *Factory) SystemError(w http.ResponseWriter, message string)
|
||
|
||
系统错误响应,HTTP 500,业务code 500。
|
||
|
||
**示例:**
|
||
```go
|
||
fac.SystemError(w, "服务器内部错误")
|
||
```
|
||
|
||
#### (f *Factory) WriteJSON(w http.ResponseWriter, httpCode, code int, message string, data interface{})
|
||
|
||
写入JSON响应(自定义)。
|
||
|
||
**参数:**
|
||
- `httpCode`: HTTP状态码
|
||
- `code`: 业务状态码
|
||
- `message`: 响应消息
|
||
- `data`: 响应数据
|
||
|
||
**说明:**
|
||
- 此方法不在 Factory 中,直接使用 `commonhttp.WriteJSON()`
|
||
- 用于需要自定义HTTP状态码的场景(如 400, 401, 403, 404 等)
|
||
|
||
**示例:**
|
||
```go
|
||
commonhttp.WriteJSON(w, http.StatusBadRequest, 400, "请求参数错误", nil)
|
||
commonhttp.WriteJSON(w, http.StatusUnauthorized, 401, "未登录", nil)
|
||
```
|
||
|
||
#### (f *Factory) SuccessPage(w http.ResponseWriter, list interface{}, total int64, page, pageSize int, message ...string)
|
||
|
||
分页成功响应。
|
||
|
||
**参数:**
|
||
- `list`: 数据列表
|
||
- `total`: 总记录数
|
||
- `page`: 当前页码
|
||
- `pageSize`: 每页大小
|
||
- `message`: 响应消息(可选,如果为空则使用默认消息 "success")
|
||
|
||
**示例:**
|
||
```go
|
||
fac.SuccessPage(w, users, total, page, pageSize)
|
||
fac.SuccessPage(w, users, total, page, pageSize, "查询成功")
|
||
```
|
||
|
||
### HTTP公共方法(直接使用)
|
||
|
||
#### WriteJSON(w http.ResponseWriter, httpCode, code int, message string, data interface{})
|
||
|
||
写入JSON响应(自定义HTTP状态码和业务状态码)。
|
||
|
||
**说明:**
|
||
- 此方法不在 Factory 中,直接使用 `commonhttp.WriteJSON()`
|
||
- 用于需要自定义HTTP状态码的场景(如 400, 401, 403, 404 等)
|
||
|
||
**示例:**
|
||
```go
|
||
commonhttp.WriteJSON(w, http.StatusBadRequest, 400, "请求参数错误", nil)
|
||
commonhttp.WriteJSON(w, http.StatusUnauthorized, 401, "未登录", nil)
|
||
```
|
||
|
||
#### ParseJSON(r *http.Request, v interface{}) error
|
||
|
||
解析JSON请求体。
|
||
|
||
**示例:**
|
||
```go
|
||
var req CreateUserRequest
|
||
if err := commonhttp.ParseJSON(r, &req); err != nil {
|
||
// 处理错误
|
||
}
|
||
```
|
||
|
||
#### GetQuery(r *http.Request, key, defaultValue string) string
|
||
|
||
获取查询参数(字符串)。
|
||
|
||
#### GetQueryInt(r *http.Request, key string, defaultValue int) int
|
||
|
||
获取查询参数(整数)。
|
||
|
||
#### GetQueryInt64(r *http.Request, key string, defaultValue int64) int64
|
||
|
||
获取查询参数(int64)。
|
||
|
||
#### GetQueryBool(r *http.Request, key string, defaultValue bool) bool
|
||
|
||
获取查询参数(布尔值)。
|
||
|
||
#### GetQueryFloat64(r *http.Request, key string, defaultValue float64) float64
|
||
|
||
获取查询参数(浮点数)。
|
||
|
||
#### GetFormValue(r *http.Request, key, defaultValue string) string
|
||
|
||
获取表单值(字符串)。
|
||
|
||
#### GetFormInt(r *http.Request, key string, defaultValue int) int
|
||
|
||
获取表单值(整数)。
|
||
|
||
#### GetFormInt64(r *http.Request, key string, defaultValue int64) int64
|
||
|
||
获取表单值(int64)。
|
||
|
||
#### GetFormBool(r *http.Request, key string, defaultValue bool) bool
|
||
|
||
获取表单值(布尔值)。
|
||
|
||
#### GetHeader(r *http.Request, key, defaultValue string) string
|
||
|
||
获取请求头。
|
||
|
||
#### ParsePaginationRequest(r *http.Request) *PaginationRequest
|
||
|
||
从请求中解析分页参数。
|
||
|
||
**说明:**
|
||
- 支持从查询参数和form表单中解析
|
||
- 优先级:查询参数 > form表单
|
||
- 如果请求体是JSON格式且包含分页字段,建议先使用`ParseJSON`解析完整请求体到包含`PaginationRequest`的结构体中
|
||
|
||
#### GetTimezone(r *http.Request) string
|
||
|
||
从请求的context中获取时区。
|
||
|
||
**说明:**
|
||
- 如果使用了middleware.Timezone中间件,可以从context中获取时区信息
|
||
- 如果未设置,返回默认时区 AsiaShanghai
|
||
|
||
#### Success(w http.ResponseWriter, data interface{}, message ...string)
|
||
|
||
成功响应(公共方法)。
|
||
|
||
**参数:**
|
||
- `data`: 响应数据,可以为nil
|
||
- `message`: 响应消息(可选),如果为空则使用默认消息 "success"
|
||
|
||
**示例:**
|
||
```go
|
||
commonhttp.Success(w, data) // 只有数据
|
||
commonhttp.Success(w, data, "操作成功") // 数据+消息
|
||
```
|
||
|
||
#### Error(w http.ResponseWriter, code int, message string)
|
||
|
||
错误响应(公共方法)。
|
||
|
||
#### SystemError(w http.ResponseWriter, message string)
|
||
|
||
系统错误响应(公共方法)。
|
||
|
||
#### WriteJSON(w http.ResponseWriter, httpCode, code int, message string, data interface{})
|
||
|
||
写入JSON响应(公共方法,不在Factory中)。
|
||
|
||
**说明:**
|
||
- 用于需要自定义HTTP状态码的场景
|
||
- 直接使用 `commonhttp.WriteJSON()`,不在 Factory 中
|
||
|
||
#### SuccessPage(w http.ResponseWriter, list interface{}, total int64, page, pageSize int, message ...string)
|
||
|
||
分页成功响应(公共方法)。
|
||
|
||
### 分页请求结构
|
||
|
||
#### PaginationRequest
|
||
|
||
分页请求结构,支持从JSON和form中解析分页参数。
|
||
|
||
**字段:**
|
||
- `Page`: 页码(默认1)
|
||
- `Size`: 每页数量(兼容旧版本)
|
||
- `PageSize`: 每页数量(推荐使用,优先于Size)
|
||
|
||
**方法:**
|
||
- `GetPage() int`: 获取页码,如果未设置则返回默认值1
|
||
- `GetSize() int`: 获取每页数量,优先使用PageSize,如果未设置则使用Size,默认20,最大100
|
||
- `GetOffset() int`: 计算数据库查询的偏移量
|
||
|
||
#### ParsePaginationRequest(r *http.Request) *PaginationRequest
|
||
|
||
从请求中解析分页参数(内部函数,Handler内部使用)。
|
||
|
||
## 状态码说明
|
||
|
||
### HTTP状态码
|
||
|
||
- `200`: 正常响应(包括业务错误)
|
||
- `400`: 请求参数错误
|
||
- `401`: 未授权
|
||
- `403`: 禁止访问
|
||
- `404`: 资源不存在
|
||
- `500`: 系统内部错误
|
||
|
||
### 业务状态码
|
||
|
||
- `0`: 成功
|
||
- `非0`: 业务错误(具体错误码由业务定义)
|
||
|
||
## 注意事项
|
||
|
||
1. **HTTP状态码与业务状态码分离**:
|
||
- 业务错误(如用户不存在、参数验证失败等)返回HTTP 200,业务code非0
|
||
- 只有系统异常(如数据库连接失败、程序panic等)才返回HTTP 500
|
||
|
||
2. **分页参数限制**:
|
||
- page最小值为1
|
||
- pageSize最小值为1,最大值为100
|
||
|
||
3. **响应格式统一**:
|
||
- 所有响应都遵循标准结构
|
||
- timestamp为Unix时间戳(秒)
|
||
|
||
4. **错误处理**:
|
||
- 使用`Error`方法返回业务错误(HTTP 200,业务code非0)
|
||
- 使用`SystemError`返回系统错误(HTTP 500)
|
||
- 其他HTTP错误状态码(400, 401, 403, 404等)使用`WriteJSON`方法直接指定
|
||
|
||
5. **推荐使用Factory**:
|
||
- 使用 `factory.Success()` 等方法,代码更简洁
|
||
- 直接使用 `http` 包的公共方法,保持低耦合
|
||
- 不需要Handler结构,减少不必要的封装
|
||
|
||
## 示例
|
||
|
||
完整示例请参考:
|
||
- `examples/http_handler_example.go` - 使用Factory和公共方法
|
||
- `examples/http_pagination_example.go` - 分页示例
|
||
- `examples/factory_blackbox_example.go` - Factory黑盒模式示例
|