SpringBoot系列06:RESTful接口开发,请求参数接收、全局跨域CORS完整配置

SpringBoot系列06:RESTful接口开发,请求参数接收、全局跨域CORS完整配置

✅ 系列专栏:SpringBoot零基础进阶实战系列

✅ 适配版本:SpringBoot 3.x / Java 17+

✅ 核心亮点:零基础上手、全覆盖参数接收、三种全局CORS配置、生产级避坑、可直接复用

✅ 阅读收益:彻底掌握RESTful接口规范、所有请求参数接收场景、解决前后端99%跨域问题


一、前言:为什么必须学RESTful与CORS配置?

在前后端分离开发模式中,RESTful API 是目前行业统一的接口设计规范,替代了传统杂乱的接口请求方式,让接口语义清晰、统一规范、易于维护。而CORS跨域问题是前后端联调的高频痛点,90%的接口联调报错都源于跨域配置不当。

本文将从零开始,手把手带大家实现 标准RESTful接口开发 + 全场景请求参数接收 + 生产级全局CORS配置,摒弃零散代码,提供可直接用于项目的完整方案,同时解析底层原理和常见踩坑点。

本文核心知识点清单

  • RESTful API设计规范(四大HTTP方法对应增删改查)

  • SpringBoot五种核心请求参数接收方式(全覆盖业务场景)

  • 三种生产级全局CORS跨域配置方案(优先级对比、场景适配)

  • 跨域核心原理、常见报错原因与终极解决方案

  • 生产环境CORS安全配置避坑指南


二、RESTful API核心设计规范

RESTful(Representational State Transfer)即表述性状态转移,核心思想是用HTTP请求方法定义操作,用URL定义资源,URL只命名资源,不包含操作行为。

2.1 传统接口 vs RESTful接口对比

传统接口风格(不规范):

  • /user/add 新增用户

  • /user/delete 删除用户

  • /user/update 修改用户

  • /user/get 查询用户

RESTful规范风格(标准统一):

HTTP方法 业务操作 接口地址 说明
GET 查询资源 /api/user 查询用户列表
GET 查询单资源 /api/user/{id} 根据ID查询单个用户
POST 新增资源 /api/user 新增用户
PUT 全量修改资源 /api/user/{id} 根据ID完整更新用户信息
PATCH 局部修改资源 /api/user/{id} 局部更新用户字段
DELETE 删除资源 /api/user/{id} 根据ID删除用户

2.2 RESTful核心约束

  1. 资源唯一:URL定位唯一资源,名词复数命名(user、order、goods)

  2. 方法语义化:严格遵循HTTP方法对应增删改查

  3. 无状态:服务器不存储客户端状态,每次请求独立

  4. 返回统一格式:统一JSON响应体,包含状态码、信息、数据


三、SpringBoot全场景请求参数接收实战

SpringBoot RESTful接口中,参数接收分为5种核心场景,覆盖所有业务开发需求,下面结合RESTful接口逐一实战演示,所有代码基于SpringBoot3可直接运行。

前置基础:RESTful接口统一控制器注解

java 复制代码
// 组合注解 = @Controller + @ResponseBody,直接返回JSON数据
@RestController
@RequestMapping("/api/user")
public class UserRestController {
}

3.1 @PathVariable 路径参数(URL路径传参)

适用场景:查询单个资源、删除、修改(RESTful标准传参),参数拼接在URL路径中

请求示例:GET /api/user/1001

java 复制代码
/**
 * 根据ID查询单个用户
 * @param id 用户ID(路径参数)
 * @return 用户信息
 */
@GetMapping("/{id}")
public Result getUserById(@PathVariable Long id){
    return Result.success("查询成功", "用户ID:" + id);
}

进阶用法:多路径参数、参数别名、必填控制

java 复制代码
// 多路径参数 + 别名映射 + 非必填
@GetMapping("/{userId}/role/{roleId}")
public Result getUserRole(
        @PathVariable("userId") Long uid,
        @PathVariable(required = false) Long roleId
){
    return Result.success("多参数查询成功", "用户ID:"+uid+",角色ID:"+roleId);
}

3.2 @RequestParam 查询参数(URL问号传参)

适用场景:列表查询、条件筛选、分页参数,参数拼接在URL?后

请求示例:GET /api/user/list?name=张三&page=1&size=10

java 复制代码
/**
 * 用户条件分页查询
 * @param name 用户名(非必填)
 * @param page 页码(默认1)
 * @param size 每页条数(默认10)
 * @return 分页数据
 */
@GetMapping("/list")
public Result getUserList(
        @RequestParam(value = "name", required = false, defaultValue = "") String name,
        @RequestParam(defaultValue = "1") Integer page,
        @RequestParam(defaultValue = "10") Integer size
){
    String res = String.format("筛选用户:%s,页码:%d,条数:%d", name, page, size);
    return Result.success("分页查询成功", res);
}

核心参数说明

  • value:前端参数名与后端形参名不一致时做映射

  • required:是否必填,默认true

  • defaultValue:参数为空时默认值

3.3 @RequestBody JSON实体参数(POST/PUT核心)

适用场景 :新增、修改接口,前端传递JSON格式请求体,最常用的传参方式

注意GET请求不支持@RequestBody,仅POST/PUT/PATCH可用

第一步:创建实体接收类

java 复制代码
import lombok.Data;

@Data
public class UserDTO {
    // 用户名
    private String username;
    // 手机号
    private String phone;
    // 年龄
    private Integer age;
}

第二步:编写新增接口

java 复制代码
/**
 * 新增用户(JSON请求体传参)
 * @param userDTO 用户信息
 * @return 新增结果
 */
@PostMapping
public Result addUser(@RequestBody UserDTO userDTO){
    return Result.success("新增用户成功", userDTO);
}

常见报错:415 Unsupported Media Type,原因:前端未设置Content-Type: application/json

3.4 @RequestHeader 请求头参数

适用场景:获取Token、请求设备信息、自定义请求头等

java 复制代码
/**
 * 获取请求头中的Token
 * @param token 登录令牌
 * @return 校验结果
 */
@GetMapping("/token")
public Result getToken(@RequestHeader("Authorization") String token){
    return Result.success("获取Token成功", "令牌:" + token);
}

3.5 普通表单参数(无注解接收)

适用场景:form表单提交,Content-Type: application/x-www-form-urlencoded

无需任何注解,直接通过形参接收,参数名与前端一致即可

java 复制代码
@PostMapping("/form")
public Result formSubmit(String username, String password){
    return Result.success("表单提交成功", "账号:"+username+",密码:"+password);
}

3.6 统一响应结果封装(规范REST返回值)

为满足RESTful接口统一返回规范,封装通用Result工具类,所有接口统一返回格式:

java 复制代码
import lombok.Data;

@Data
public class Result<T> {
    // 响应码:200成功 500失败
    private Integer code;
    // 响应信息
    private String msg;
    // 响应数据
    private T data;

    // 成功响应
    public static <T> Result<T> success(String msg, T data){
        Result<T> result = new Result<>();
        result.setCode(200);
        result.setMsg(msg);
        result.setData(data);
        return result;
    }

    // 失败响应
    public static <T> Result<T> error(String msg){
        Result<T> result = new Result<>();
        result.setCode(500);
        result.setMsg(msg);
        return result;
    }
}

四、CORS跨域原理与报错原因

4.1 什么是跨域?

浏览器同源策略限制:协议、域名、端口三者任意一个不同,即为跨域,浏览器会拦截响应,抛出跨域报错。

同源判定规则http://localhost:8080(后端)与 http://localhost:3000(前端)端口不同 = 跨域

4.2 常见跨域报错

Access to fetch at 'xxx' from origin 'xxx' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

核心原因:后端接口未配置跨域许可,未返回对应的跨域响应头。


五、三种生产级全局CORS配置方案(推荐收藏)

SpringBoot中跨域配置分为局部注解配置全局配置 ,局部配置仅对单个接口生效,企业项目统一使用全局配置,下面提供三种主流全局配置方案,适配不同场景。

5.1 方案一:实现WebMvcConfigurer(最推荐、轻量化)

适用场景:绝大多数SpringBoot项目,不影响SpringSecurity、拦截器等配置,优先级适中

核心优势:代码简洁、侵入性低、适配SpringBoot3

java 复制代码
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * 全局跨域配置(方案一:WebMvc配置)
 * 生产推荐:精准配置域名,禁止直接使用*
 */
@Configuration
public class CorsConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        // 匹配所有接口路径
        registry.addMapping("/**")
                // 允许跨域的前端域名(生产环境替换为真实前端地址,多个域名用逗号分隔)
                .allowedOrigins("http://localhost:3000", "http://127.0.0.1:3000")
                // 允许所有请求方法
                .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
                // 允许所有请求头
                .allowedHeaders("*")
                // 允许携带Cookie、Token凭证
                .allowCredentials(true)
                // 预检请求有效期1小时,减少OPTIONS请求次数
                .maxAge(3600);
    }
}

5.2 方案二:注册CorsFilter过滤器(优先级最高、全局拦截)

适用场景:需要优先执行跨域配置、整合SpringSecurity、高并发项目

核心优势:过滤器层级最高,可解决拦截器、权限框架导致的跨域失效问题

java 复制代码
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

import java.util.Arrays;

/**
 * 全局跨域配置(方案二:CorsFilter过滤器)
 * 优先级高于WebMvc配置,适合整合权限框架的项目
 */
@Configuration
public class CorsFilterConfig {

    @Bean
    public CorsFilter corsFilter() {
        CorsConfiguration config = new CorsConfiguration();
        // 允许的前端域名
        config.setAllowedOrigins(Arrays.asList("http://localhost:3000", "http://127.0.0.1:3000"));
        // 允许请求方法
        config.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS"));
        // 允许请求头
        config.setAllowedHeaders(Arrays.asList("*"));
        // 允许携带凭证
        config.setAllowCredentials(true);
        // 预检请求缓存时间
        config.setMaxAge(3600L);

        // 匹配所有接口
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", config);
        return new CorsFilter(source);
    }
}

5.3 方案三:yml配置文件极简配置(快速开发)

适用场景 :本地开发、快速测试,不推荐生产使用(灵活性差)

在application.yml中直接添加配置:

yaml 复制代码
# 全局跨域配置
spring:
  web:
    cors:
      allowed-origins: http://localhost:3000
      allowed-methods: GET,POST,PUT,DELETE,OPTIONS
      allowed-headers: *
      allow-credentials: true
      max-age: 3600

5.4 局部跨域配置(了解即可)

通过@CrossOrigin注解,作用于类或方法,仅对当前接口生效:

java 复制代码
@RestController
@RequestMapping("/api/user")
@CrossOrigin(origins = "http://localhost:3000")
public class UserRestController {
    // 所有接口自动跨域
}

六、生产环境CORS核心避坑指南(必看)

6.1 禁止使用 allowedOrigins("*")

致命错误:开启allowCredentials(true)时,不能配置*通配符,会直接报错!

原因:浏览器安全机制,允许携带Cookie时,必须指定具体域名,不允许全局开放

生产方案:枚举所有前端合法域名,或通过配置文件动态读取

6.2 OPTIONS预检请求403报错

复杂请求(带Token、自定义请求头)会先发OPTIONS预检请求,必须手动放行OPTIONS方法,否则权限框架会拦截

6.3 配置优先级规则

CorsFilter过滤器 > @CrossOrigin注解 > WebMvc全局配置 > yml配置

项目中只保留一种全局配置,多配置共存会导致跨域失效、冲突报错

6.4 跨域失效常见原因

  • SpringSecurity未放行OPTIONS请求

  • 自定义拦截器在跨域过滤器之前执行

  • 配置类未加@Configuration注解,未生效

  • 前后端端口、域名匹配错误

  • URL拼写格式错误:配置前端跨域域名时,禁止出现多余引号、空格、非法字符(如 `http://127.0.0.1:3000"` 错误格式),URL末尾不能带双引号、逗号等冗余字符,会直接导致跨域配置解析失败、前端请求跨域报错

  • 域名协议不匹配:后端配置http协议,前端使用https协议,或反之,引发跨域拦截

  • SpringSecurity未放行OPTIONS请求

  • 自定义拦截器在跨域过滤器之前执行

  • 配置类未加@Configuration注解,未生效

  • 前后端端口、域名匹配错误


七、完整项目测试流程

  1. 启动SpringBoot项目,端口8080

  2. 使用Postman/Apifox测试所有RESTful接口

  3. 启动前端项目(3000端口),调用后端接口,跨域问题彻底解决

  4. 所有参数接收场景均可正常解析,返回统一JSON格式


八、总结与下期预告

本文总结

  1. 掌握RESTful标准化接口设计,告别杂乱接口风格

  2. 吃透5种请求参数接收方式,覆盖100%业务传参场景

  3. 掌握3种生产级全局CORS配置,解决所有跨域问题

  4. 熟悉生产环境跨域避坑要点,规避线上故障

下期预告

SpringBoot系列07:全局异常处理+统一返回结果封装,彻底消灭接口杂乱报错


💡 博主寄语

RESTful接口开发和跨域配置是SpringBoot前后端分离的基础必修课,看似简单但极易踩坑。建议大家收藏本文,项目中直接复用配置,规范代码风格,提升开发效率。

码字不易,点赞关注持续更新SpringBoot干货!有问题评论区交流,秒回!

相关推荐
IVVi0jToe1 小时前
高效C++线程池设计与实现
java·c++·安全
CRMEB定制开发1 小时前
企业级Java电商系统选型路线图:从零到上线全流程拆解
java·开发语言·商城系统·小程序商城
Zhou1411361 小时前
Java常见面试题3
java·开发语言
Solis1 小时前
百万并发的点赞计数,我们为什么要把“事实“和“计数“拆开?
java·架构
tachibana22 小时前
hot100 排序链表(148)
java·数据结构·算法·leetcode·链表
wear工程师2 小时前
synchronized 锁升级:多数人还在背 JDK8 的答案,偏向锁早在 JDK18 就没了
java·面试
荣码2 小时前
LangGraph多步工作流:Agent不够用的时候,我踩了4个坑
java·python
是小李呀2 小时前
Java集合扩容机制解析:ArrayList与HashMap底层原理及性能差异
java