前后端跨域处理全指南:Java后端+Vue前端完整解决方案

摘要:本文详细介绍跨域问题的产生原因、浏览器同源策略机制,以及基于Java后端和Vue前端技术栈的多种跨域处理方案。涵盖@CrossOrigin注解、全局CORS配置、过滤器、Spring Security集成、Vue代理配置、Nginx反向代理等多种方案,并提供完整可运行的代码示例,适用于初中级开发者学习参考。

一、跨域基础概念

1.1 什么是跨域?

跨域(Cross-Origin)是指浏览器出于安全考虑,限制从一个域(协议+域名+端口)加载的网页去请求另一个域的资源。当协议、域名或端口三者中有任意一项不同时,就会触发跨域限制。

示例

  • http://localhost:3000http://localhost:8080(端口不同)❌ 跨域
  • http://example.comhttps://example.com(协议不同)❌ 跨域
  • http://api.example.comhttp://www.example.com(子域名不同)❌ 跨域
  • http://localhost:3000http://localhost:3000/api(同源)✅ 不跨域

1.2 为什么会有跨域限制?

浏览器的同源策略(Same-Origin Policy,SOP) 是Web安全的核心机制,用于:

  • 防止恶意网站读取另一个网站的敏感数据(如Cookie、localStorage)
  • 防止CSRF(跨站请求伪造)攻击
  • 保护用户隐私和数据安全
注意:跨域限制仅存在于浏览器,服务器之间的HTTP请求(如Java HttpClient、Postman)不受此限制。

1.3 CORS(跨域资源共享)工作原理

CORS是W3C标准,通过服务器设置HTTP响应头告知浏览器允许哪些源访问资源。

简单请求流程

浏览器请求 → 服务器返回Access-Control-Allow-Origin → 浏览器验证放行 

复杂请求(预检请求)流程

浏览器OPTIONS预检 → 服务器返回允许方法/头 → 浏览器发送真实请求 → 返回数据 

二、完整的跨域处理方案列表

以下是适用于Java后端+Vue前端的6种核心方案:

方案适用场景实现复杂度安全性需要后端配合
1. @CrossOrigin注解少量接口快速测试⭐ 低✅ 是
2. 全局CORS配置企业级标准方案⭐⭐ 中✅ 是
3. 过滤器Filter动态权限控制⭐⭐ 中✅ 是
4. Spring Security集成带权限系统的项目⭐⭐⭐ 高✅ 是
5. Vue DevServer代理开发环境专用⭐ 低❌ 否
6. Nginx反向代理生产环境部署⭐⭐ 中❌ 否

三、方案详解

方案1:@CrossOrigin注解(最简单)

3.1.1 实现原理

通过在Controller或方法上添加@CrossOrigin注解,Spring MVC会自动添加CORS响应头。

3.1.2 后端实现

单个接口跨域

importorg.springframework.web.bind.annotation.CrossOrigin;importorg.springframework.web.bind.annotation.GetMapping;importorg.springframework.web.bind.annotation.RestController;@RestControllerpublicclassDemoController{// 允许指定域名的跨域请求@CrossOrigin(origins ="http://localhost:8080")@GetMapping("/api/demo")publicStringdemo(){return"Hello from CORS!";}}

多个接口跨域

@RestController@RequestMapping("/api")// 类级别注解:该类下所有方法都支持跨域@CrossOrigin( origins ={"http://localhost:8080","http://localhost:3000"}, methods ={RequestMethod.GET,RequestMethod.POST}, maxAge =3600)publicclassApiController{@GetMapping("/users")publicStringgetUsers(){return"Users data";}@PostMapping("/login")publicStringlogin(){return"Login success";}}

3.1.3 前端配置(Vue + Axios)

// src/api/request.jsimport axios from'axios';const request = axios.create({baseURL:'http://localhost:8080',// 后端地址timeout:5000});exportdefault request;
<!-- src/components/Demo.vue --> <template> <div>{{ message }}</div> </template> <script> import request from '@/api/request'; export default { data() { return { message: '' } }, async mounted() { try { const res = await request.get('/api/demo'); this.message = res.data; } catch (error) { console.error('跨域请求失败:', error); } } } </script> 

3.1.4 优缺点分析

优点

  • 配置简单,一行注解搞定
  • 适合少量接口或快速原型开发

缺点

  • 每个接口都需要单独配置,维护成本高
  • 不适合大规模企业项目
  • 无法统一管理跨域规则

方案2:全局CORS配置(推荐)

3.2.1 实现原理

实现WebMvcConfigurer接口,重写addCorsMappings方法,统一配置全局跨域规则。

3.2.2 后端实现

packagecom.example.config;importorg.springframework.context.annotation.Configuration;importorg.springframework.web.servlet.config.annotation.CorsRegistry;importorg.springframework.web.servlet.config.annotation.WebMvcConfigurer;/** * 全局CORS配置类 * 推荐用于企业级项目,统一管理跨域规则 */@ConfigurationpublicclassCorsConfigimplementsWebMvcConfigurer{@OverridepublicvoidaddCorsMappings(CorsRegistry registry){ registry.addMapping("/**")// 对所有路径生效.allowedOrigins(// 允许的前端域名(生产环境需指定具体域名)"http://localhost:8080","http://localhost:3000","https://www.example.com").allowedMethods(// 允许的HTTP方法"GET","POST","PUT","DELETE","OPTIONS").allowedHeaders("*")// 允许的请求头.exposedHeaders("X-Total-Count","X-Page-Count")// 暴露的响应头.allowCredentials(true)// 允许携带Cookie(需与allowedOrigins配合).maxAge(3600);// 预检请求缓存时间(秒)}}

3.2.3 前端配置

Axios实例配置

// src/utils/request.jsimport axios from'axios';const service = axios.create({baseURL:'http://localhost:8080/api',// 后端API地址timeout:10000,withCredentials:true// 携带Cookie(需后端allowCredentials=true)});// 请求拦截器:添加Token等 service.interceptors.request.use(config=>{const token = localStorage.getItem('token');if(token){ config.headers['Authorization']='Bearer '+ token;}return config;},error=>{return Promise.reject(error);});// 响应拦截器:统一处理错误 service.interceptors.response.use(response=> response,error=>{if(error.response){switch(error.response.status){case401: console.error('未授权,请登录');break;case403: console.error('拒绝访问');break;case500: console.error('服务器错误');break;}}return Promise.reject(error);});exportdefault service;

API封装

// src/api/user.jsimport request from'@/utils/request';exportconstgetUserList=(params)=>{returnrequest({url:'/users',method:'get', params });};exportconstcreateUser=(data)=>{returnrequest({url:'/users',method:'post', data });};

3.2.4 优缺点分析

优点

  • 统一管理,便于维护
  • 一次配置,全局生效
  • 支持精细化的权限控制

缺点

  • 配置相对复杂
  • 需要理解CORS相关配置项

方案3:过滤器Filter(灵活控制)

3.3.1 实现原理

通过自定义Filter,在请求链中手动设置CORS响应头,可实现动态的跨域逻辑。

3.3.2 后端实现

packagecom.example.filter;importorg.springframework.stereotype.Component;importorg.springframework.web.filter.OncePerRequestFilter;importjavax.servlet.FilterChain;importjavax.servlet.ServletException;importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.HttpServletResponse;importjava.io.IOException;/** * CORS过滤器 * 适用于需要动态判断跨域权限的场景 */@ComponentpublicclassCorsFilterextendsOncePerRequestFilter{@OverrideprotectedvoiddoFilterInternal(HttpServletRequest request,HttpServletResponse response,FilterChain filterChain)throwsServletException,IOException{String origin = request.getHeader("Origin");// 动态判断是否允许该源跨域(可根据数据库、Redis等动态配置)if(isAllowedOrigin(origin)){ response.setHeader("Access-Control-Allow-Origin", origin); response.setHeader("Access-Control-Allow-Methods","GET, POST, PUT, DELETE, OPTIONS"); response.setHeader("Access-Control-Allow-Headers","Content-Type, Authorization, X-Requested-With"); response.setHeader("Access-Control-Allow-Credentials","true"); response.setHeader("Access-Control-Max-Age","3600");}// 处理OPTIONS预检请求if("OPTIONS".equals(request.getMethod())){ response.setStatus(HttpServletResponse.SC_OK);return;} filterChain.doFilter(request, response);}/** * 判断源是否在白名单中(可改为从数据库查询) */privatebooleanisAllowedOrigin(String origin){if(origin ==null){returnfalse;}// 允许的源列表(实际项目中可从配置文件或数据库读取)String[] allowedOrigins ={"http://localhost:8080","http://localhost:3000","https://www.example.com"};for(String allowed : allowedOrigins){if(allowed.equals(origin)){returntrue;}}returnfalse;}}

3.3.3 前端配置

同方案2,使用Axios配置即可。

3.3.4 优缺点分析

优点

  • 灵活性最高,可实现动态跨域控制
  • 可根据请求参数、用户角色等动态判断是否允许跨域
  • 适用于多租户、SAAS系统等复杂场景

缺点

  • 实现相对复杂
  • 需要手动维护CORS响应头逻辑
  • 性能略低于Spring内置CORS支持

方案4:Spring Security集成(带权限系统)

3.4.1 实现原理

在Spring Security安全框架中集成CORS,确保跨域请求在经过安全链时正确处理。

3.4.2 后端实现

依赖配置(pom.xml):

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency>

Security配置类

packagecom.example.config;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.security.config.annotation.web.builders.HttpSecurity;importorg.springframework.security.config.annotation.web.configuration.EnableWebSecurity;importorg.springframework.security.web.SecurityFilterChain;importorg.springframework.web.cors.CorsConfiguration;importorg.springframework.web.cors.CorsConfigurationSource;importorg.springframework.web.cors.UrlBasedCorsConfigurationSource;importjava.util.Arrays;/** * Spring Security + CORS 配置 * 关键:CORS必须在Security之前处理 */@Configuration@EnableWebSecuritypublicclassSecurityConfig{@BeanpublicSecurityFilterChainfilterChain(HttpSecurity http)throwsException{ http // 启用CORS(关键步骤).cors(cors -> cors.configurationSource(corsConfigurationSource()))// 禁用CSRF(前后端分离项目通常禁用).csrf(csrf -> csrf.disable())// 配置权限规则.authorizeHttpRequests(auth -> auth // 放行OPTIONS预检请求.requestMatchers(org.springframework.http.HttpMethod.OPTIONS,"/**").permitAll()// 公开接口.requestMatchers("/api/public/**").permitAll()// 需要认证的接口.anyRequest().authenticated());return http.build();}/** * CORS配置源 * Security会自动读取此配置 */@BeanpublicCorsConfigurationSourcecorsConfigurationSource(){CorsConfiguration configuration =newCorsConfiguration();// 允许的源(生产环境必须指定具体域名) configuration.setAllowedOrigins(Arrays.asList("http://localhost:8080","http://localhost:3000","https://www.example.com"));// 允许的方法 configuration.setAllowedMethods(Arrays.asList("GET","POST","PUT","DELETE","OPTIONS","PATCH"));// 允许的请求头 configuration.setAllowedHeaders(Arrays.asList("*"));// 允许携带凭证 configuration.setAllowCredentials(true);// 暴露的响应头 configuration.setExposedHeaders(Arrays.asList("X-Total-Count","Authorization"));// 预检缓存时间 configuration.setMaxAge(3600L);UrlBasedCorsConfigurationSource source =newUrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", configuration);return source;}}

3.4.3 前端配置

Axios配置(带Token认证)

// src/utils/request.jsimport axios from'axios';import{ Message }from'element-ui';const service = axios.create({baseURL:'http://localhost:8080',timeout:10000,withCredentials:true// 携带Cookie(如SessionId)});// 请求拦截器 service.interceptors.request.use(config=>{// 从localStorage获取Tokenconst token = localStorage.getItem('access_token');if(token){ config.headers['Authorization']='Bearer '+ token;}return config;},error=>{return Promise.reject(error);});// 响应拦截器 service.interceptors.response.use(response=>{const res = response.data;// 根据业务状态码处理if(res.code !==200){ Message.error(res.message ||'请求失败');// 401未授权,跳转登录页if(res.code ===401){ localStorage.removeItem('access_token'); window.location.href ='/login';}return Promise.reject(newError(res.message ||'Error'));}else{return res;}},error=>{ console.error('请求错误:', error);// 401未授权if(error.response && error.response.status ===401){ Message.error('未授权,请重新登录'); localStorage.removeItem('access_token'); window.location.href ='/login';}return Promise.reject(error);});exportdefault service;

登录示例

// src/api/auth.jsimport request from'@/utils/request';exportconstlogin=(data)=>{returnrequest({url:'/api/auth/login',method:'post', data });};exportconstgetUserInfo=()=>{returnrequest({url:'/api/user/info',method:'get'});};

3.4.4 优缺点分析

优点

  • 完美集成Spring Security安全体系
  • 支持Token认证、Session认证等多种认证方式
  • 适用于需要权限控制的复杂业务系统

缺点

  • 配置复杂度较高
  • 需要理解Spring Security的工作原理
  • 新手容易出错

方案5:Vue DevServer代理(开发环境)

3.5.1 实现原理

利用Webpack DevServer内置的http-proxy-middleware,在开发服务器层面对请求进行转发,绕过浏览器的同源限制。

3.5.2 前端配置

vue.config.js配置(Vue CLI项目):

// vue.config.js module.exports ={devServer:{port:8080,// 前端开发服务器端口host:'0.0.0.0',open:true,proxy:{// 代理规则1:/api开头的请求'/api':{target:'http://localhost:8080',// 后端真实地址changeOrigin:true,// 修改请求头中的Origin为目标地址ws:true,// 支持WebSocket代理pathRewrite:{'^/api':''// 去掉/api前缀(如果后端接口没有/api)},// 可选:添加自定义请求头headers:{'X-Dev-Proxy':'true'}},// 代理规则2:/upload开头的请求'/upload':{target:'http://localhost:9090',changeOrigin:true,pathRewrite:{'^/upload':'/files'}}}}}

vite.config.js配置(Vite项目):

// vite.config.jsimport{ defineConfig }from'vite'import vue from'@vitejs/plugin-vue'exportdefaultdefineConfig({plugins:[vue()],server:{port:5173,proxy:{'/api':{target:'http://localhost:8080',changeOrigin:true,rewrite:(path)=> path.replace(/^\/api/,'')}}}})

3.5.3 Axios配置

// src/utils/request.jsimport axios from'axios';const service = axios.create({// 开发环境使用相对路径(会被代理转发)// 生产环境需配置为真实的后端地址baseURL: process.env.NODE_ENV==='development'?'/api':'http://api.example.com',timeout:10000});exportdefault service;

环境变量配置(.env.development):

NODE_ENV=development VUE_APP_BASE_API=/api 

环境变量配置(.env.production):

NODE_ENV=production VUE_APP_BASE_API=https://api.example.com 

3.5.4 优缺点分析

优点

  • 开发环境最简单、最快捷的方案
  • 无需后端配合,前端独立完成
  • 支持WebSocket代理

缺点

  • 仅适用于开发环境,生产环境不可用
  • 生产部署时需要修改baseURL或使用其他方案
  • 调试时代理转发可能影响问题定位

方案6:Nginx反向代理(生产环境)

3.6.1 实现原理

通过Nginx作为反向代理服务器,前端请求Nginx同源地址,Nginx转发到后端。对浏览器而言是同源请求,完美解决跨域问题。

3.6.2 Nginx配置

基础配置(推荐)

server { listen 80; server_name www.example.com; # 前端静态资源 location / { root /usr/share/nginx/html; # Vue打包后的dist目录 index index.html; try_files $uri $uri/ /index.html; # 解决Vue路由刷新404 } # 后端API代理 location /api/ { # 转发到后端真实地址 proxy_pass http://localhost:8080/; # 关键:传递原始Host和客户端IP proxy_set_header Host $proxy_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; # WebSocket支持 proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } } 

完整CORS配置(后端不配置CORS时使用):

server { listen 80; server_name api.example.com; location / { # 允许的源(生产环境指定具体域名) add_header 'Access-Control-Allow-Origin' 'https://www.example.com' always; add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always; add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization, X-Requested-With' always; add_header 'Access-Control-Allow-Credentials' 'true' always; add_header 'Access-Control-Max-Age' '3600' always; # 处理OPTIONS预检请求 if ($request_method = OPTIONS) { return 204; } # 反向代理到后端 proxy_pass http://localhost:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } } 

动态允许源配置

server { listen 80; server_name api.example.com; # 动态设置允许的源 set $cors_origin ""; if ($http_origin ~* ^(https?://(localhost|www\.example\.com)(:[0-9]+)?$)) { set $cors_origin $http_origin; } location / { # 使用变量设置允许的源 add_header 'Access-Control-Allow-Origin' $cors_origin always; add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always; add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization' always; add_header 'Access-Control-Allow-Credentials' 'true' always; if ($request_method = OPTIONS) { return 204; } proxy_pass http://localhost:8080; } } 

3.6.3 前端配置

Axios配置

// src/utils/request.jsimport axios from'axios';// 生产环境使用Nginx代理的地址(同域)const service = axios.create({baseURL: process.env.NODE_ENV==='production'?'/api'// 生产环境:Nginx代理地址(同域):'http://localhost:8080',// 开发环境:使用后端直连或开发代理timeout:10000,withCredentials:true});exportdefault service;

3.6.4 优缺点分析

优点

  • 生产环境最推荐方案
  • 前后端同域,天然避免跨域问题
  • 支持负载均衡、缓存、HTTPS等高级功能
  • 无需修改后端代码

缺点

  • 需要额外的Nginx服务器
  • 配置相对复杂
  • 需要运维知识

四、最佳实践建议

4.1 开发环境

推荐方案:Vue DevServer代理 + 后端CORS全局配置

理由

  • 前端独立开发,不依赖后端配置
  • 快速迭代,方便调试
  • 为生产环境做好准备

示例配置

// 开发环境:vue.config.js module.exports ={devServer:{proxy:{'/api':{target:'http://localhost:8080',changeOrigin:true,pathRewrite:{'^/api':''}}}}}

4.2 生产环境

推荐方案:Nginx反向代理 + 后端CORS全局配置(双重保障)

理由

  • Nginx作为流量入口,统一处理跨域
  • 后端CORS作为备用,应对直接访问后端的情况
  • 支持多环境部署(开发、测试、生产)

架构图

浏览器 ↓ Nginx (80/443) ├─ / → 前端静态资源 (同域) └─ /api → 后端API (同域代理) ↓ Spring Boot (8080) 

4.3 复杂权限系统

推荐方案:Spring Security + CORS + Token认证

关键配置

@BeanpublicSecurityFilterChainfilterChain(HttpSecurity http)throwsException{ http .cors().and().csrf().disable().authorizeHttpRequests(auth -> auth .requestMatchers(HttpMethod.OPTIONS,"/**").permitAll().requestMatchers("/api/public/**").permitAll().anyRequest().authenticated());return http.build();}

前端Token管理

// 请求拦截器:自动添加Token service.interceptors.request.use(config=>{const token = localStorage.getItem('token');if(token){ config.headers['Authorization']='Bearer '+ token;}return config;});

4.4 多租户/SAAS系统

推荐方案:过滤器Filter + 动态跨域配置

实现思路

  • 根据租户域名动态设置允许的源
  • 支持租户级别的跨域白名单管理
  • 从数据库或配置中心读取跨域规则
privatebooleanisAllowedOrigin(String origin,String tenantId){// 从数据库查询该租户的跨域白名单List<String> allowedOrigins = tenantService.getCorsWhiteList(tenantId);return allowedOrigins.contains(origin);}

五、常见问题排查

5.1 配置失败的典型原因

问题1:No ‘Access-Control-Allow-Origin’ header is present

原因

  • 后端未配置CORS
  • Nginx未添加跨域头
  • OPTIONS预检请求失败

排查步骤

  1. 打开浏览器开发者工具 → Network
  2. 查看请求的Response Headers
  3. 检查是否有Access-Control-Allow-Origin字段
  4. 检查OPTIONS请求是否返回204或200

问题2:Credential is not supported for wildcard origin

原因

  • 同时设置了allowCredentials=trueallowedOrigins="*"
  • 浏览器不允许通配符源携带Cookie

解决方案

// 错误配置 config.setAllowCredentials(true); config.setAllowedOrigins(Arrays.asList("*"));// 正确配置 config.setAllowCredentials(true); config.setAllowedOrigins(Arrays.asList("http://localhost:8080"));

问题3:OPTIONS预检请求返回404/403

原因

  • 后端未实现OPTIONS接口
  • Security拦截了OPTIONS请求
  • Nginx未处理预检请求

解决方案

// Security放行OPTIONS http.authorizeHttpRequests(auth -> auth .requestMatchers(HttpMethod.OPTIONS,"/**").permitAll());
# Nginx处理OPTIONS if ($request_method = OPTIONS) { return 204; } 

5.2 Nginx配置踩坑

坑1:proxy_pass的斜杠问题

# 错误:路径会保留/api location /api/ { proxy_pass http://localhost:8080; # 请求 /api/user → http://localhost:8080/api/user } # 正确:去掉/api前缀 location /api/ { proxy_pass http://localhost:8080/; # 请求 /api/user → http://localhost:8080/user } 

坑2:缺少always参数

# 错误:错误响应时不会添加跨域头 add_header 'Access-Control-Allow-Origin' 'http://localhost:8080'; # 正确:所有响应都添加跨域头 add_header 'Access-Control-Allow-Origin' 'http://localhost:8080' always; 

5.3 Cookie携带问题

现象:请求未携带Cookie或Set-Cookie不生效

原因

  • 前端未设置withCredentials: true
  • 后端未设置allowCredentials: true
  • Cookie的SameSite属性设置不当

解决方案

前端

axios.get('/api/user',{withCredentials:true});

后端

config.setAllowCredentials(true); config.setAllowedOrigins(Arrays.asList("http://localhost:8080"));// 不能是*

Cookie设置

Cookie cookie =newCookie("token", tokenValue); cookie.setHttpOnly(true); cookie.setSecure(true);// HTTPS必需 cookie.setPath("/");// 如果需要跨域,设置SameSite为None cookie.setAttribute("SameSite","None"); response.addCookie(cookie);

5.4 调试技巧

技巧1:使用curl测试CORS

# 测试OPTIONS预检curl-X OPTIONS -H"Origin: http://localhost:8080"\-H"Access-Control-Request-Method: GET"\-v http://localhost:8080/api/user # 查看响应头curl-I http://localhost:8080/api/user 

技巧2:浏览器Network面板分析

  1. 打开开发者工具 → Network
  2. 勾选"Preserve log"
  3. 发送跨域请求
  4. 查看请求详情:
    • Request Headers:检查Origin、Access-Control-Request-Method
    • Response Headers:检查Access-Control-Allow-*
    • Console:查看具体错误信息

技巧3:临时禁用浏览器安全策略(仅用于调试)

# Chrome启动参数(仅开发调试使用,生产环境禁止) chrome.exe --disable-web-security --user-data-dir="C:/temp/chrome-dev"

六、总结

6.1 方案对比表

方案适用场景推荐度生产可用性
@CrossOrigin注解少量接口测试⭐⭐✅ 是
全局CORS配置企业级标准方案⭐⭐⭐⭐⭐✅ 是
过滤器Filter动态权限控制⭐⭐⭐⭐✅ 是
Spring Security集成带权限系统⭐⭐⭐⭐⭐✅ 是
Vue DevServer代理开发环境⭐⭐⭐⭐⭐❌ 否
Nginx反向代理生产环境⭐⭐⭐⭐⭐✅ 是

6.2 核心要点

  1. 跨域是浏览器的安全机制,服务器之间无此限制
  2. CORS是最标准的解决方案,推荐后端配置
  3. 开发环境用代理,生产环境用Nginx
  4. allowCredentials=true时,allowedOrigins不能是"*"
  5. Spring Security需放行OPTIONS预检请求
  6. Nginx配置注意斜杠和always参数
  7. 携带Cookie需前后端同时配置

6.3 推荐架构

标准企业级项目

开发环境:Vue DevServer代理 + 后端CORS全局配置 生产环境:Nginx反向代理 + 后端CORS全局配置(双重保障) 权限系统:Spring Security + Token认证 

参考资料

Read more

RUST:异步代码的测试与调试艺术

RUST:异步代码的测试与调试艺术

RUST:异步代码的测试与调试艺术 一、异步测试的本质与难点 1.1 异步测试与同步测试的区别 💡在Rust同步编程中,测试通常是顺序执行的,每个测试函数会阻塞线程直到完成,结果是确定的。而异步测试的结果可能受到任务调度、网络延迟、数据库连接等因素的影响,时序性和状态管理更加复杂。 同步测试示例: #[cfg(test)]modtests{#[test]fntest_add(){assert_eq!(1+1,2);}} 异步测试示例(使用Tokio测试宏): #[cfg(test)]modtests{usetokio::time::sleep;usestd::time::Duration;#[tokio::test]asyncfntest_async_add(){sleep(Duration::from_millis(100)).await;assert_

By Ne0inhk
复杂 SQL 过滤时机过晚?金仓基于代价的连接条件下推方案来了

复杂 SQL 过滤时机过晚?金仓基于代价的连接条件下推方案来了

复杂查询中基于代价的连接条件下推实践与思考 在实际的业务系统中,SQL 往往并不像教科书示例那样简洁。随着业务复杂度的提升,CTE、多层子查询、窗口函数、聚集计算被大量用于组织逻辑。然而,这类 SQL 在带来可读性的同时,也给查询优化器带来了巨大的挑战,尤其是在 JOIN 条件无法有效提前过滤数据 的场景下,性能问题尤为突出。本文将围绕一个在真实客户场景中频繁出现的问题——复杂查询中 JOIN 条件下推失败导致的性能瓶颈,系统性地介绍一种 基于代价模型的连接条件下推(Cost-based Join Predicate Pushdown) 的设计与实现思路。 一、问题背景 1.1 客户场景中的典型痛点 在很多客户业务中,SQL 通常采用如下模式来组织逻辑: * 在子查询或 CTE 中完成大量计算(去重、聚集、窗口函数等) * 在外层再与其他表进行 JOIN,并施加高选择性的过滤条件 例如: 从业务语义上看,这条

By Ne0inhk

webdriver_manager终极指南:彻底解决Selenium浏览器驱动管理难题

webdriver_manager终极指南:彻底解决Selenium浏览器驱动管理难题 【免费下载链接】webdriver_manager 项目地址: https://gitcode.com/gh_mirrors/we/webdriver_manager 在Selenium自动化测试实践中,浏览器驱动管理往往是开发者面临的首要技术障碍。据统计,超过60%的Selenium新手错误都源于驱动版本不匹配或配置不当。webdriver_manager作为专业的Python测试工具,通过智能化的驱动管理机制,让开发者彻底告别手动下载、版本匹配和路径配置的繁琐流程。 驱动管理痛点深度解析 传统Selenium测试环境配置存在三大核心痛点: 版本兼容性问题:浏览器频繁更新导致驱动版本不匹配,测试脚本频繁失效 环境配置复杂性:不同操作系统下驱动路径配置差异大,团队协作困难 维护成本高昂:手动管理多个浏览器驱动版本,耗费大量开发时间 核心功能架构解析 webdriver_manager采用模块化设计,通过四大核心组件实现智能驱动管理: 自动化版本检测机制 系统自动识别本地安装

By Ne0inhk