前后端分离CRUD开发与跨域问题解决方案

发布时间:2026/7/20 23:32:58
前后端分离CRUD开发与跨域问题解决方案 1. 前后端分离CRUD开发中的跨域问题解析前后端分离架构已成为现代Web开发的主流模式但在实际开发中跨域问题就像一道无形的墙经常让开发者碰壁。我刚接手一个企业级项目时就曾因为跨域问题导致前端整整两天无法获取后端数据。本文将结合实战经验系统讲解如何在前端分离架构下实现CRUD功能并彻底解决跨域问题。2. 前后端分离架构基础2.1 技术栈选型建议后端推荐使用Spring Boot MyBatis Plus组合这套组合拳能快速搭建RESTful API。我在最近三个项目中都采用了这个方案开发效率提升40%以上。前端则建议Vue.js Element UI配合axios进行HTTP通信。注意技术栈版本要特别注意兼容性Spring Boot 2.3与Vue CLI 4.x是最稳定的组合2.2 项目结构设计合理的项目结构能避免后期大量重构project/ ├── backend/ # Spring Boot项目 │ ├── src/ │ └── pom.xml └── frontend/ # Vue项目 ├── public/ └── src/3. 后端CRUD实现详解3.1 MyBatis Plus配置使用MyBatis Plus可以省去90%的SQL编写Mapper public interface UserMapper extends BaseMapperUser { // 继承BaseMapper即获得CRUD能力 }3.2 控制器层实现RESTful风格的控制器示例RestController RequestMapping(/api/users) public class UserController { Autowired private UserMapper userMapper; GetMapping public ListUser list() { return userMapper.selectList(null); } PostMapping public boolean save(RequestBody User user) { return userMapper.insert(user) 0; } // 其他CRUD方法... }4. 前端CRUD实现4.1 Axios封装建议对axios进行二次封装// http.js const service axios.create({ baseURL: process.env.VUE_APP_BASE_API, timeout: 5000 }) // 请求拦截器 service.interceptors.request.use( config { // 可添加token等 return config }, error { return Promise.reject(error) } )4.2 Vue组件实现用户列表组件示例template el-table :datalist el-table-column propname label姓名/el-table-column !-- 其他列 -- el-table-column label操作 template #defaultscope el-button clickhandleEdit(scope.row)编辑/el-button el-button clickhandleDelete(scope.row)删除/el-button /template /el-table-column /el-table /template script export default { data() { return { list: [] } }, mounted() { this.fetchData() }, methods: { async fetchData() { const res await this.$http.get(/api/users) this.list res.data }, // 其他CRUD方法... } } /script5. 跨域问题全面解决方案5.1 跨域的本质原因浏览器同源策略限制以下情况协议不同http vs https域名不同a.com vs b.com端口不同8080 vs 30005.2 解决方案对比方案实现难度适用场景缺点JSONP简单老项目兼容仅支持GETNginx反向代理中等生产环境需要部署CORS简单开发/生产需后端配合5.3 Spring Boot CORS配置全局配置方案推荐Configuration public class CorsConfig implements WebMvcConfigurer { Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping(/**) .allowedOrigins(*) .allowedMethods(GET, POST, PUT, DELETE) .allowCredentials(false) .maxAge(3600); } }控制器局部配置RestController CrossOrigin(origins http://localhost:8080) RequestMapping(/api) public class UserController { // ... }5.4 Nginx反向代理配置生产环境推荐方案server { listen 80; server_name api.yourdomain.com; location / { proxy_pass http://backend:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }6. 实战中的坑与解决方案6.1 预检请求(OPTIONS)问题复杂请求会先发OPTIONS请求后端需要正确处理RestController public class OptionsController { RequestMapping(value /**, method RequestMethod.OPTIONS) public ResponseEntity? handleOptions() { return ResponseEntity.ok() .header(Access-Control-Allow-Methods, GET,POST,PUT,DELETE) .header(Access-Control-Allow-Headers, Content-Type) .build(); } }6.2 带凭证的请求如果需要传递cookie等凭证信息registry.addMapping(/**) .allowedOrigins(http://frontend-domain.com) .allowCredentials(true);前端axios配置axios.defaults.withCredentials true6.3 常见错误排查403 Forbidden检查CORS配置是否包含前端域名验证请求头是否被允许OPTIONS请求返回404确保Spring Security未拦截OPTIONS请求添加OPTIONS方法的路由处理Credentials不生效检查allowCredentials(true)是否设置确认allowedOrigins不能为*7. 安全增强建议生产环境不要使用allowedOrigins(*)应明确指定允许的域名对于敏感操作建议结合JWT等认证机制定期检查CORS配置避免过度开放权限8. 性能优化技巧设置合理的maxAge减少预检请求.maxAge(3600) // 1小时内不再发送OPTIONS请求Nginx层启用gzip压缩gzip on; gzip_types application/json;前端使用axios的拦截器统一处理错误service.interceptors.response.use( response response, error { if (error.response.status 403) { // 处理跨域错误 } return Promise.reject(error) } )经过多个项目的实战验证这套方案能稳定解决95%以上的跨域问题。最后提醒开发环境可以使用宽松的CORS配置但生产环境一定要严格限制来源域名。