Vue + Vite + Axios 项目多环境以及部署前后端跨域

最近在前端多环境和部署服务器之后出现的跨域的问题。

多环境

前端多环境 Vite Axios

1.首先在项目目录下定义多环境的文件。

这里列举开发环境和发布环境

.env.development 环境

javascript 复制代码
# 开发时加载

// 此处为开发时接口
VITE_API_URL = 'http://localhost:8080/api'

.env production 环境

javascript 复制代码
# 发布时加载

// 生产时接口
VITE_API_URL = 'http://xxxxxxxxxxx/api'  线上后端地址
  1. 在配置的 Axios 识别环境
javascript 复制代码
const myAxios = axios.create({
    //识别环境
    baseURL: import.meta.env.VITE_API_URL as any,
    timeout: 5000,
    headers: { 'Content-Type': 'application/json;charset=UTF-8' },
    // @ts-ignore
    //跨域
    changeOrigin: true
});
  1. 项目因为使用的是 Vite 打包构建,所以在package文件下的 vite 的 build 命令加上 production
javascript 复制代码
"scripts": {
    "dev": "vite",
    "build": "vite build --mode production",
    "preview": "vite preview"
  },

后端多环境 Spring Boot

创建 application-prod.yml 文件,配置信息为线上环境的地址,比如数据库,redis等

javascript 复制代码
#项目名称,此处是spring boot 2.5版本之后的写法,之前的写法不能识别
spring:
  config:
    activate:
      on-profile:
        prod
  application:
    name: guanlixitong
    #数据库配置
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    username: dazi
    password: 123456
    url: jdbc:mysql://localhost:3306/dazi
  #sesson 失效时间 86400秒
  session:
    timeout: 86400  
    store-type: redis

部署命令

javascript 复制代码
java -jar ./{项目打包之后的 jar 包名称,比如maven打包之后target里的 jar 包} --spring.profiles.active=prod

项目启动日志

javascript 复制代码
INFO 14040 --- [           main] c.p.d.UserCenterBackendApplication       : The following 1 profile is active: "prod"
INFO 14040 --- [           main] o.a.catalina.core.AprLifecycleListener   : APR capabilities: IPv6 [true], sendfile [true], accept filters [false], random [true], UDS [true].   
INFO 14040 --- [           main] o.a.catalina.core.AprLifecycleListener   : APR/OpenSSL configuration: useAprConnector [false], useOpenSSL [true]
INFO 14040 --- [           main] o.a.catalina.core.AprLifecycleListener   : OpenSSL successfully initialized [OpenSSL 1.1.1v  1 Aug 2023]
INFO 14040 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]

可以看到识别到了 prod 环境,后端测试也可以发现能够连接上线上数据库了。

(后来线上测试发现 redis 能连上,也能存储数据,但是不能识别登录状态,头疼)

跨域

参考文档:SpringBoot设置Cors跨域的四种方式 - 简书 (jianshu.com)

官方文档:Spring 和 CORS 跨域 - spring 中文网 (springdoc.cn)

  1. Nginx 配置
javascript 复制代码
#跨域配置
location ^~ /api/ {
    proxy_pass http://127.0.0.1:8080;   #反向代理配置
    add_header 'Access-Control-Allow-Origin' $http_origin; #预检查请求也需要这行
    add_header 'Access-Control-Allow-Credentials' 'true';
    add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
    add_header Access-Control-Allow-Headers '*';
	  if ($request_method = 'OPTIONS'){
        add_header 'Access-Control-Allow-Credentials' 'true';
        add_header 'Access-Control-Allow-Origin' $http_origin;
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
        add_header 'Access-Control-Max-Age' 1728000;
        add_header 'Content-Type' 'text/plain; charset=utf-8';
        add_header 'Content-Length' 0;
        return 204;
    }
}
  1. 后端 @CrossOrigin 注解

在 controller 文件加上注解

javascript 复制代码
@CrossOringin(origins = {允许跨域的地址}, methods = {可以跨域的请求方式}, allowCredentials = "true")
  1. 添加 web 全局请求拦截器
java 复制代码
//新建config目录,新建在该目录下
@Configuration
public class WebMvcConfg implements WebMvcConfigurer {
 
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        //设置允许跨域的路径
        registry.addMapping("/**")
                //设置允许跨域请求的域名
                //当**Credentials为true时,**Origin不能为星号,需为具体的ip地址【如果接口不带cookie,ip无需设成具体ip】
                .allowedOrigins("http://localhost:9527", "http://127.0.0.1:9527", "http://127.0.0.1:8082", "http://127.0.0.1:8083")
                //是否允许证书 不再默认开启
                .allowCredentials(true)
                .allowedHeaders(CorsConfiguration.ALL)
                //设置允许的方法
                .allowedMethods(CorsConfiguration.ALL)
                //跨域允许时间
                .maxAge(3600);
    }
}

二选一即可
---------------------------------------------------------------
//Spring 中文网
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 WebMvcConfiguration implements WebMvcConfigurer{
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")                  // 允许跨域请求的path,支持路径通配符,如:/api/**
            .allowedOrigins("*")                    // 允许发起请求的源
            .allowedHeaders("*")                    // 允许客户端的提交的 Header,通配符 * 可能有浏览器兼容问题
            .allowedMethods("GET")                  // 允许客户端使用的请求方法
            .allowCredentials(false)                // 不允许携带凭证
            .exposedHeaders("X-Auth-Token, X-Foo")  // 允许额外访问的 Response Header
            .maxAge(3600)                           // 预检缓存一个小时
            ;
    }
}
  1. CorsFilter
java 复制代码
import java.time.Duration;

import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.http.HttpHeaders;
import org.springframework.util.StringUtils;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.filter.CorsFilter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebMvcConfiguration implements WebMvcConfigurer{

    // 通过 FilterRegistrationBean 注册 CorsFilter
    @Bean
    public FilterRegistrationBean<CorsFilter> corsFilter() {
        
        // 跨域 Filter
        CorsFilter corsFilter = new CorsFilter(request -> {
            
            // 请求源
            String origin = request.getHeader(HttpHeaders.ORIGIN);
            
            if (!StringUtils.hasText(origin)) {
                return null; // 非跨域请求
            }
            
            // 针对每个请求,编程式设置跨域
            CorsConfiguration config = new CorsConfiguration();
            
            // 允许发起跨域请求的源,直接取 Origin header 值,不论源是哪儿,服务器都接受
            config.addAllowedOrigin(origin);
            
            
            // 允许客户端的请求的所有 Header
            String headers = request.getHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_HEADERS);
            if (StringUtils.hasText(headers)) {
                config.setAllowedHeaders(Stream.of(headers.split(",")).map(String::trim).distinct().toList());
            }
            
            // 允许客户端的所有请求方法
            config.addAllowedMethod(request.getHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD));
            // 允许读取所有 Header
            // 注意,"*" 通配符,可能在其他低版本浏览中不兼容。
            config.addExposedHeader("*");
            // 缓存30分钟
            config.setMaxAge(Duration.ofMinutes(30));
            // 允许携带凭证
            config.setAllowCredentials(true);
            return config;
        });
        
        FilterRegistrationBean<CorsFilter> bean = new FilterRegistrationBean<>(corsFilter);
        bean.addUrlPatterns("/*");                  // Filter 拦截路径
        bean.setOrder(Ordered.LOWEST_PRECEDENCE);   // 保证最先执行
        return bean;
    }
}

可能出现的问题

java 复制代码
//报错信息
The 'Access-Control-Allow-Origin' header contains multiple values'*, *', but only one is allowed.

域名冲突,可能是上述配置跨域重复,比如 Nginx 配置和后端配置,只需要删除某一个即可,比如 Nginx 配置中的关于请求头,请求方法等,具体看实际测试情况。

上述配置 最后选择了 Nginx 配置,注解在开发时有效,但是一部署线上之后就不生效,原因不知。其他的或多或少会报错,比如 Get 请求不跨域,Post 请求就跨域。。。

知识尚浅,有错误烦请指出。

相关推荐
devilnumber8 分钟前
如何在java的Lambda中安全地修改外部变量?
java·安全·lambda
大得3698 分钟前
langchain使用
java·python·langchain
带刺的坐椅10 分钟前
SolonCode CLI 的心智记忆功能:让 AI 编程助手越用越懂你
java·ai·llm·cli·soloncode
我命由我1234520 分钟前
Visual Studio - Visual Studio 注释快捷键
java·c语言·开发语言·c++·ide·java-ee·visual studio
lemon_sjdk27 分钟前
DecimalFormat
java·开发语言·python
Nontee31 分钟前
一、Java 基础 面试题解答(72题)
java·开发语言
兰令水32 分钟前
topcode【随机算法题】【2026.5.16打卡-java版本】
java·数据结构·算法
摇滚侠32 分钟前
SpringBoot 面试题 真正的 offer 偏方 Java 基础 Java 高级
java·spring boot·后端
AI人工智能+电脑小能手38 分钟前
【大白话说Java面试题 第58题】【JVM篇】第18题:讲一下三色标记
java·开发语言·jvm
huaiixinsi38 分钟前
Java 后端面试高频题整理(02)
java·开发语言·spring·面试·职场和发展·架构·maven