Java 后端HTTP 请求(GET/POST)传输规范
作者:凯qwq
文章详细阐述了RESTful API设计的最佳实践,涵盖了GET和POST请求的规范、参数传递、响应体、版本控制、日志记录等,本文介绍实例代码介绍了Java后端HTTP请求(GET/POST)传输规范,感兴趣的朋友一起看看吧
一、核心原则
- 遵循 “RESTful 风格”,URI 仅表示资源,HTTP 方法表示操作;
- GET 仅用于查询,禁止通过 GET 传递敏感数据;POST 用于新增 / 修改 / 删除,或传递大量 / 敏感数据;
- 所有接口参数、响应数据统一使用 UTF-8 编码,避免乱码。
二、GET 请求规范
1. 用途限制
- 仅用于查询 / 获取资源,禁止用于新增、修改、删除操作;
- 后端注解:统一使用
@GetMapping,禁止用@RequestMapping(method = RequestMethod.GET)(冗余)。
2. 参数传递规则(Java 编码落地)
(1)路径参数(唯一标识)
- 后端用
@PathVariable接收,参数名与 URI 中的占位符一致; - ✅ 正确代码示例:
// URI:GET /api/v1/users/1001
@RestController
@RequestMapping("/api/v1/users")
public class UserController {
@GetMapping("/{userId}")
public ResultDTO<UserInfoRespDTO> getUserById(@PathVariable("userId") Long userId) {
UserInfoRespDTO user = userService.getUserById(userId);
return ResultDTO.success(user);
}
}- ❌ 错误:用
@RequestParam接收唯一标识(如@RequestParam("userId") Long userId)。
(2)查询参数(筛选 / 分页 / 排序)
- 后端用
@RequestParam接收,可设置默认值、是否必传; - 参数命名:小驼峰,与前端一致,禁止用下划线;
- ✅ 正确代码示例:
// URI:GET /api/v1/orders?status=PAID&pageNum=1&pageSize=10
@GetMapping("/orders")
public ResultDTO<PageInfo<OrderListRespDTO>> getOrderList(
@RequestParam(value = "status", required = false) String status,
@RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum,
@RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize
) {
PageInfo<OrderListRespDTO> page = orderService.getOrderList(status, pageNum, pageSize);
return ResultDTO.success(page);
}(3)复杂查询参数(多个筛选条件)
- 封装为
XXXQueryReqDTO,用@ModelAttribute接收(避免参数过多); - ✅ 正确代码示例:
// 封装查询DTO
@Data
public class OrderQueryReqDTO {
private String status;
private String orderNo;
private LocalDateTime startTime;
private LocalDateTime endTime;
private Integer pageNum = 1;
private Integer pageSize = 10;
}
// 接口接收
@GetMapping("/orders/query")
public ResultDTO<PageInfo<OrderListRespDTO>> queryOrder(@ModelAttribute OrderQueryReqDTO queryDTO) {
PageInfo<OrderListRespDTO> page = orderService.queryOrder(queryDTO);
return ResultDTO.success(page);
}3. 长度与编码
- 后端无需手动 URL 解码(SpringMVC 自动解码);
- 若参数含中文 / 特殊字符,确保
application.yml中配置:
server:
tomcat:
uri-encoding: UTF-8
spring:
http:
encoding:
charset: UTF-8
enabled: true
force: true4. 敏感数据禁止
- 后端通过拦截器 / 切面校验:若 GET 请求参数包含
password/token/phone等敏感字段,直接返回 400; - 示例(拦截器逻辑):
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
String method = request.getMethod();
if ("GET".equals(method)) {
Map<String, String[]> paramMap = request.getParameterMap();
if (paramMap.containsKey("password") || paramMap.containsKey("token")) {
response.setStatus(400);
response.getWriter().write(JSON.toJSONString(ResultDTO.fail("GET请求禁止传递敏感数据")));
return false;
}
}
return true;
}三、POST 请求规范
1. 用途限制
- 用于新增 / 修改 / 删除资源,或传递大量 / 敏感数据的查询;
- 后端注解:统一使用
@PostMapping,禁止用@RequestMapping(method = RequestMethod.POST)。
2. 参数传递规则(Java 编码落地)
(1)JSON 参数(主流)
- 后端用
@RequestBody接收,参数封装为XXXReqDTO,并添加 JSR380 参数校验注解; - ✅ 正确代码示例:
// 新增用户DTO(含参数校验)
@Data
@Schema(description = "用户新增请求参数")
public class UserAddReqDTO {
@NotBlank(message = "用户名不能为空")
@Size(min = 2, max = 20, message = "用户名长度需在2-20位")
private String username;
@NotBlank(message = "密码不能为空")
@Pattern(regexp = "^[a-zA-Z0-9@#$%^&*]{6,32}$", message = "密码仅支持字母、数字、特殊符号,长度6-32位")
private String password;
@Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式错误")
private String phoneNumber;
}
// 接口接收
@PostMapping("/users")
public ResultDTO<Long> addUser(@Valid @RequestBody UserAddReqDTO addDTO) {
Long userId = userService.addUser(addDTO);
return ResultDTO.success(userId, "新增用户成功");
}- 注意:必须加
@Valid触发参数校验,否则注解不生效;校验失败会抛出MethodArgumentNotValidException,需在全局异常处理器中捕获。
(2)文件上传(multipart/form-data)
- 后端用
@RequestPart接收文件,@RequestParam接收附加参数; - 配置文件上传大小限制:
spring:
servlet:
multipart:
max-file-size: 10MB # 单个文件大小
max-request-size: 50MB # 总文件大小- ✅ 正确代码示例:
@PostMapping("/files/upload")
public ResultDTO<FileUploadRespDTO> uploadFile(
@RequestPart("file") MultipartFile file,
@RequestParam("fileName") String fileName
) {
// 校验文件类型/大小
if (!file.getContentType().startsWith("image/")) {
return ResultDTO.fail(400, "仅支持图片上传");
}
FileUploadRespDTO resp = fileService.upload(file, fileName);
return ResultDTO.success(resp);
}(3)幂等性保障(新增接口)
- 后端通过 “唯一业务编号”+ 数据库唯一索引实现幂等;
- 示例:新增订单时,前端传递
orderNo(UUID),后端先查后插:
@Transactional(rollbackFor = Exception.class)
public Long addOrder(OrderCreateReqDTO createDTO) {
// 1. 校验订单号是否已存在(幂等核心)
if (orderMapper.existsByOrderNo(createDTO.getOrderNo())) {
throw new BusinessException("订单已存在,请勿重复提交");
}
// 2. 新增订单
Order order = new Order();
BeanUtils.copyProperties(createDTO, order);
orderMapper.insert(order);
return order.getId();
}3. 特殊场景:POST 查询(敏感 / 大量参数)
- 适用于参数过多(超过 URL 长度限制)、含敏感数据的查询;
- ✅ 正确代码示例:
// 复杂订单查询(参数多、含敏感条件)
@PostMapping("/orders/complex-query")
public ResultDTO<PageInfo<OrderListRespDTO>> complexQuery(@RequestBody OrderComplexQueryReqDTO queryDTO) {
PageInfo<OrderListRespDTO> page = orderService.complexQuery(queryDTO);
return ResultDTO.success(page);
}四、通用规范(GET/POST 均适用)
1. URI 命名规则(Java 编码落地)
- Controller 类上的
@RequestMapping统一以/api/v{版本号}/开头,资源用复数名词; - ✅ 正确:
@RequestMapping("/api/v1/users"),❌ 错误:@RequestMapping("/api/v1/user")/@RequestMapping("/api/v1/getUser")。
2. 响应规范(统一返回体)
- 后端封装通用响应类
ResultDTO,所有接口统一返回该类型,禁止直接返回业务对象 / 字符串; - ✅ 通用响应类代码:
@Data
public class ResultDTO<T> {
// 状态码:200成功,400参数错误,403权限不足,500服务异常
private Integer code;
// 提示信息
private String msg;
// 业务数据
private T data;
// 成功响应(带数据)
public static <T> ResultDTO<T> success(T data) {
ResultDTO<T> result = new ResultDTO<>();
result.setCode(200);
result.setMsg("操作成功");
result.setData(data);
return result;
}
// 成功响应(无数据)
public static ResultDTO<Void> success() {
return success(null);
}
// 失败响应
public static ResultDTO<Void> fail(Integer code, String msg) {
ResultDTO<Void> result = new ResultDTO<>();
result.setCode(code);
result.setMsg(msg);
return result;
}
}3. 异常处理(Java 编码落地)
- 全局异常处理器统一捕获所有异常,返回标准化
ResultDTO,禁止接口抛出未捕获异常; - ✅ 全局异常处理器代码:
@RestControllerAdvice
public class GlobalExceptionHandler {
// 捕获参数校验异常
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResultDTO<Void> handleValidException(MethodArgumentNotValidException e) {
String msg = e.getBindingResult().getFieldError().getDefaultMessage();
return ResultDTO.fail(400, msg);
}
// 捕获自定义业务异常
@ExceptionHandler(BusinessException.class)
public ResultDTO<Void> handleBusinessException(BusinessException e) {
return ResultDTO.fail(e.getCode(), e.getMessage());
}
// 捕获所有未处理的异常
@ExceptionHandler(Exception.class)
public ResultDTO<Void> handleException(Exception e) {
// 记录详细异常日志
log.error("服务端异常", e);
return ResultDTO.fail(500, "服务器内部错误,请稍后重试");
}
}4. 接口版本控制
- 后端通过 URI 携带版本号(推荐),禁止通过参数(如
?version=1)或请求头控制版本; - ✅ 正确:
@RequestMapping("/api/v1/users"),@RequestMapping("/api/v2/users")。
五、反例与正例对照表(Java 编码)
表格
| 场景 | 反例(禁止) | 正例(推荐) |
|---|---|---|
| GET 查询单个用户 | @GetMapping("/getUser") + @RequestParam("userId") Long userId | @GetMapping("/{userId}") + @PathVariable Long userId |
| POST 新增用户 | @PostMapping("/addUser") + URL 传参 | @PostMapping("/users") + @RequestBody UserAddReqDTO |
| 响应数据 | return user;(直接返回业务对象) | return ResultDTO.success(user); |
| 参数校验 | 手动 if 判断(if (username == null) { throw new Exception(); }) | JSR380 注解(@NotBlank)+ @Valid |
六、Java 后端编码额外规范
- 请求头规范:
- 跨域请求:后端配置
CorsConfig,允许前端的 Origin、Method、Header; - 认证请求:token 统一放在
Authorization请求头,后端用@RequestHeader("Authorization") String token接收。
- 跨域请求:后端配置
- 日志规范:
- 所有接口入参 / 出参必须打印日志(使用 SLF4J),禁止打印敏感数据(如密码);
- ✅ 示例:
@GetMapping("/{userId}")
public ResultDTO<UserInfoRespDTO> getUserById(@PathVariable("userId") Long userId) {
log.info("【查询用户】入参:userId={}", userId);
UserInfoRespDTO user = userService.getUserById(userId);
log.info("【查询用户】出参:{}", JSON.toJSONString(user));
return ResultDTO.success(user);
}- 性能规范:
- GET 请求建议添加缓存(如 Redis),避免频繁查库;
- POST 请求建议异步处理(如 MQ),耗时操作(如文件解析、数据同步)不阻塞接口响应。
总结
- 编码核心:GET 用
@PathVariable/@RequestParam,POST 用@RequestBody,参数校验用 JSR380+@Valid; - 响应核心:所有接口统一返回
ResultDTO,异常统一由GlobalExceptionHandler捕获; - 安全核心:GET 禁止传敏感数据,POST 新增接口保证幂等,日志屏蔽敏感信息;
- 规范核心:URI 用小写复数名词 + 版本号,参数命名小驼峰,编码统一 UTF-8。
| 请求类型 | 参数传递位置 | 前端核心写法(示例) | 后端核心写法(Java) | 适用场景 | 关键规范 / 注意事项 |
|---|---|---|---|---|---|
| GET | URL 路径参数 | axios.get('/api/v1/users/1001') | @GetMapping("/{userId}")@PathVariable("userId") Long userId | 查询单个资源(如查用户 / 订单) | 1. 路径参数为唯一标识(ID / 编号)2. URI 用复数名词,小写 |
| GET | URL 查询参数 | axios.get('/api/v1/orders', { params: { status: 'PAID', pageNum: 1 } }) | @GetMapping("/orders")@RequestParam String status@RequestParam Integer pageNum | 列表筛选 / 分页 / 排序 | 1. 参数名小驼峰2. 非必传参数加required = false3. 可封装为 DTO 用@ModelAttribute接收 |
| POST | Request Body(JSON) | axios.post('/api/v1/users', { username: '张三', password: '123456' }) | @PostMapping("/users")@Valid @RequestBody UserAddReqDTO addDTO | 新增 / 修改资源、复杂查询 | 1. 必加@Valid触发参数校验2. DTO 加 JSR380 注解(@NotBlank/@Pattern)3. Content-Type: application/json |
| POST | Form Data(表单) | let formData = new FormData();formData.append('username', '张三');axios.post('/api/v1/users/login', formData) | @PostMapping("/login")@RequestParam String username@RequestParam String password | 简单表单提交(如登录) | 1. Content-Type: application/x-www-form-urlencoded2. 敏感数据建议转 JSON 传递 |
| POST | Multipart Form Data(文件 + 参数) | let formData = new FormData();formData.append('file', file);formData.append('fileName', '头像.png');axios.post('/api/v1/files/upload', formData) | @PostMapping("/upload")@RequestPart("file") MultipartFile file@RequestParam("fileName") String fileName | 文件上传(单 / 多文件) | 1. 配置文件大小限制(spring.servlet.multipart)2. 文件参数名统一为file |
| GET/POST | 请求头参数 | axios.get('/api/v1/users', { headers: { Authorization: 'Bearer token123' } }) | @RequestHeader("Authorization") String token | 传递 token / 语言 / 版本等 | 1. 认证 token 统一放Authorization头2. 非敏感、固定参数用请求头 |
| POST | 混合参数(路径 + JSON) | axios.post('/api/v1/users/1001/update', { phone: '13800138000' }) | @PostMapping("/{userId}/update")@PathVariable Long userId@RequestBody UserUpdateReqDTO updateDTO | 修改单个资源(带 ID + 参数) | 1. 路径传唯一标识,Body 传修改参数2. 禁止路径传大量参数 |
补充:说明(前后端协作关键)
1. 通用数据格式
- 字符编码:前后端统一用 UTF-8;
- 日期格式:统一用
yyyy-MM-dd HH:mm:ss(前端传字符串,后端用@DateTimeFormat接收):
// 后端接收日期示例
@GetMapping("/orders")
public ResultDTO<?> getOrders(@RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime startTime) {
// 业务逻辑
}- 数值类型:前端传递数字(如
pageNum: 1),禁止传字符串(如pageNum: "1"),后端用Integer/Long接收。
2. 错误码 / 响应格式统一
表格
| 响应场景 | 前端接收格式 | 后端返回写法 |
|---|---|---|
| 成功 | { code: 200, msg: "成功", data: {} } | ResultDTO.success(data) |
| 参数校验失败 | { code: 400, msg: "用户名不能为空" } | ResultDTO.fail(400, "用户名不能为空") |
| 权限不足 | { code: 403, msg: "无权限" } | ResultDTO.fail(403, "无权限") |
| 服务端异常 | { code: 500, msg: "服务器错误" } | ResultDTO.fail(500, "服务器错误") |
3. 反例对照(禁止写法)
表格
| 场景 | 前端反例 | 后端反例 | 问题说明 |
|---|---|---|---|
| GET 传敏感数据 | axios.get('/login?pwd=123456') | @RequestParam String pwd | 密码暴露在 URL / 日志中 |
| POST 用 URL 传大量参数 | axios.post('/users?name=张三&age=20&phone=138...') | @RequestParam接收 10 + 个参数 | URL 长度有限制,可读性差 |
| 路径参数用动词 | axios.get('/api/v1/getUser/1001') | @GetMapping("/getUser/{userId}") | 违反 RESTful 规范,URI 仅表示资源 |
| 文件上传用 JSON | axios.post('/upload', { file: fileObj }) | 用@RequestBody接收文件 | JSON 无法传输二进制文件 |
总结
- 核心匹配:路径参数→
@PathVariable、查询参数→@RequestParam、JSON→@RequestBody、文件→@RequestPart; - 场景优先:查询用 GET(路径 / 查询参数),新增 / 修改 / 文件用 POST(JSON/FormData);
- 规范统一:参数名小驼峰、日期格式统一、响应体结构一致,前后端按表对齐即可避免 90% 的参数传递问题。
到此这篇关于Java 后端HTTP 请求(GET/POST)传输规范的文章就介绍到这了,更多相关java http请求内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
