React集成Axios访问SpringBoot REST接口遇CORS跨域及编译问题咨询
问题解决方案
一、前端编译报错修复
三个未定义变量的报错核心原因是用到了状态变量但没有通过React Hook声明,同时存在部分无效导入、axios导入语法错误的问题,修正点如下:
- 补充导入
useStateHook,修正axios的默认导入写法(axios是默认导出,不需要用花括号解构导入) - 在组件内部声明用到的
rowData、isLoaded状态,以及对应的更新方法 - 删掉代码中没有实际使用的
admin-on-rest相关导入,避免不必要的依赖报错
修正后的完整可运行App.js代码:
import React, { useEffect, useState } from "react"; import axios from 'axios'; import { DataGrid } from '@material-ui/data-grid'; export default function App() { // 声明所需的状态 const [rowData, setRowData] = useState([]); const [isLoaded, setIsLoaded] = useState(false); useEffect(() => { const apiurl = "http://localhost:8080/user/all"; axios .get(apiurl) .then((response) => response.data) .then((data) => { setIsLoaded(true); setRowData(data); }) .catch(err => console.log("请求报错", err)); }, []); const columns = [ { field: "id", headerName: "ID", width: 10 }, { field: "userName", headerName: "Name", width: 170 }, { field: "userTelNo", headerName: "Tel No", width: 70 }, { field: "userEmail", headerName: "EMail", width: 100 }, { field: "userRole", headerName: "Role", width: 100 }, ]; return( <DataGrid rows={rowData} columns={columns} id="id" pageSize={15} checkboxSelection /> ); }
二、SpringBoot后端CORS跨域配置
浏览器报错No 'Access-Control-Allow-Origin' header的核心原因是后端没有返回允许跨域的响应头,可以根据项目实际场景选择下面任意一种方法配置:
方法1:局部接口配置(改动最小)
直接在对应的Controller类上添加@CrossOrigin注解,指定允许的前端来源:
import org.springframework.web.bind.annotation.CrossOrigin; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/user") // 允许http://localhost:3000的跨域请求 @CrossOrigin(origins = "http://localhost:3000") public class UserController { // 原有/user/all接口逻辑保持不变 @GetMapping("/all") public List<User> getAllUsers() { // 查询用户列表的原有逻辑 } }
方法2:全局跨域配置(全项目生效)
如果项目多个接口都需要被前端访问,写一个全局配置类统一配置跨域规则,不需要在每个Controller加注解:
import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class GlobalCorsConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") // 匹配项目所有接口路径 .allowedOrigins("http://localhost:3000") // 匹配前端实际访问地址 .allowedMethods("GET", "POST", "PUT", "DELETE") // 允许的HTTP请求方法 .allowedHeaders("*") // 允许所有请求头 .allowCredentials(true) // 如需携带Cookie/认证信息需开启,不需要可设为false .maxAge(3600); // 预检请求缓存时长,减少重复OPTIONS请求 } }
特殊场景:项目集成了Spring Security
如果上述配置写了还是跨域报错,是因为Spring Security的过滤链优先级更高,会拦截跨域预检请求,需要在Security配置类中补充跨域支持:
// 在Security的配置方法中添加.cors()配置 @Override protected void configure(HttpSecurity http) throws Exception { http // 保留其他原有Security配置 .cors() // 启用跨域支持,自动关联上面的全局CORS配置 .and() // 保留其他原有Security配置... }
常见踩坑提醒
- 配置的允许来源地址必须和浏览器地址栏的前端地址完全一致,要写全协议、域名、端口,不能省略
http://前缀 - 不要只在前端折腾开发代理配置就以为不用改后端,生产环境跨域问题最终都需要后端返回正确的CORS响应头
- 不要将
*作为允许来源同时开启allowCredentials(true),两者无法同时生效,必须指定明确的来源地址
内容的提问来源于stack exchange,提问作者Ezani
相关产品推荐
相关产品推荐

