You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React+Gradle Spring Boot部署Tomcat多环境(IST/UAT/Prod)URL配置咨询

我之前刚好处理过类似的Spring Boot+React多环境部署场景,给你分享几个实用的方案,都能完美解决fetch URL随环境动态变更的需求:

方案1:Spring Boot启动时动态替换React静态文件占位符

这个方案的核心是让Spring Boot根据当前环境配置,在启动时替换React构建产物里的API地址占位符,不需要React额外发起请求。

  • 第一步:在React项目的public/index.html中添加全局变量占位符
    在<head>标签里插入一段脚本,预留API地址的占位符:

    <script>
      window.API_BASE_URL = '{{API_BASE_URL_PLACEHOLDER}}';
    </script>
    
  • 第二步:配置Spring Boot多环境属性文件
    在src/main/resources下创建对应环境的配置文件:

    • application-ist.properties:app.api.base-url=http://ist-api.your-domain.com
    • application-uat.properties:app.api.base-url=http://uat-api.your-domain.com
    • application-prod.properties:app.api.base-url=http://prod-api.your-domain.com
      主配置文件application.properties可以加个默认值:app.api.base-url=http://localhost:8080
  • 第三步:编写Spring Boot启动时的占位符替换逻辑
    创建一个组件,在应用启动后读取配置并替换index.html里的占位符:

    import org.springframework.boot.context.event.ApplicationReadyEvent;
    import org.springframework.context.event.EventListener;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.stereotype.Component;
    import java.io.File;
    import java.nio.charset.StandardCharsets;
    import java.nio.file.Files;
    
    @Component
    public class ReactEnvInitializer {
    
        @Value("${app.api.base-url}")
        private String apiBaseUrl;
    
        @EventListener(ApplicationReadyEvent.class)
        public void replaceApiUrlPlaceholder() throws Exception {
            File indexHtml = new File("target/classes/static/index.html");
            if (indexHtml.exists()) {
                String content = Files.readString(indexHtml.toPath(), StandardCharsets.UTF_8);
                content = content.replace("{{API_BASE_URL_PLACEHOLDER}}", apiBaseUrl);
                Files.writeString(indexHtml.toPath(), content, StandardCharsets.UTF_8);
            }
        }
    }
    
  • 第四步:React代码中使用全局变量
    发起请求时直接调用这个全局变量:

    fetch(`${window.API_BASE_URL}/api/your-endpoint`)
      .then(res => res.json())
      .then(data => console.log(data));
    
  • 第五步:启动Spring Boot时指定环境

    # 启动IST环境
    java -jar your-spring-boot-app.jar --spring.profiles.active=ist
    
    # 启动UAT环境
    java -jar your-spring-boot-app.jar --spring.profiles.active=uat
    
    # 启动Prod环境
    java -jar your-spring-boot-app.jar --spring.profiles.active=prod
    

方案2:Spring Boot提供环境配置接口,React启动时请求

这个方案更灵活,React在初始化时先请求后端的配置接口,获取当前环境的API地址,适合需要动态调整配置的场景。

  • 第一步:编写Spring Boot配置接口
    创建一个Controller返回当前环境的API配置:

    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
    import java.util.Map;
    
    @RestController
    public class EnvConfigController {
    
        @Value("${app.api.base-url}")
        private String apiBaseUrl;
    
        @GetMapping("/api/env/config")
        public Map<String, String> getEnvConfig() {
            return Map.of("apiBaseUrl", apiBaseUrl);
        }
    }
    
  • 第二步:React中获取并全局共享配置
    在入口文件src/index.js里,通过Context共享配置:

    import { createContext, useState, useEffect } from 'react';
    import ReactDOM from 'react-dom/client';
    import App from './App';
    
    export const EnvContext = createContext();
    
    const Root = () => {
      const [envConfig, setEnvConfig] = useState({ apiBaseUrl: '' });
    
      useEffect(() => {
        fetch('/api/env/config')
          .then(res => res.json())
          .then(config => setEnvConfig(config))
          .catch(err => console.error('Failed to load environment config:', err));
      }, []);
    
      return (
        <EnvContext.Provider value={envConfig}>
          <App />
        </EnvContext.Provider>
      );
    };
    
    ReactDOM.createRoot(document.getElementById('root')).render(<Root />);
    
  • 第三步:React组件中使用配置
    在需要发起请求的组件中,通过Context获取API地址:

    import { useContext } from 'react';
    import { EnvContext } from '../index';
    
    const DataFetcher = () => {
      const { apiBaseUrl } = useContext(EnvContext);
    
      const fetchData = () => {
        fetch(`${apiBaseUrl}/api/your-endpoint`)
          .then(res => res.json())
          .then(data => console.log(data));
      };
    
      return <button onClick={fetchData}>Fetch Data</button>;
    };
    
    export default DataFetcher;
    

方案3:Gradle构建时注入React环境变量

如果你的CI/CD流程是先构建React再打包Spring Boot,可以让Gradle根据指定的环境,在构建React时直接注入对应的API地址。

  • 第一步:配置React多环境构建脚本
    在React项目的package.json中添加不同环境的build命令:

    "scripts": {
      "build": "react-scripts build",
      "build:ist": "REACT_APP_API_BASE_URL=http://ist-api.your-domain.com react-scripts build",
      "build:uat": "REACT_APP_API_BASE_URL=http://uat-api.your-domain.com react-scripts build",
      "build:prod": "REACT_APP_API_BASE_URL=http://prod-api.your-domain.com react-scripts build"
    }
    
  • 第二步:配置Gradle构建逻辑
    在Spring Boot的build.gradle中,根据指定的profile执行对应的React构建命令,并将产物复制到Spring Boot的静态资源目录:

    plugins {
        id 'org.springframework.boot' version '3.1.0'
        id 'io.spring.dependency-management' version '1.1.0'
        id 'java'
    }
    
    def activeProfile = project.findProperty('spring.profiles.active') ?: 'dev'
    
    task buildReact(type: Exec) {
        workingDir 'src/main/react' // 你的React项目根目录
        switch(activeProfile) {
            case 'ist': commandLine 'npm', 'run', 'build:ist' break
            case 'uat': commandLine 'npm', 'run', 'build:uat' break
            case 'prod': commandLine 'npm', 'run', 'build:prod' break
            default: commandLine 'npm', 'run', 'build'
        }
    }
    
    task copyReactBuild(type: Copy) {
        from 'src/main/react/build'
        into 'src/main/resources/static'
    }
    
    buildReact.finalizedBy copyReactBuild
    processResources.dependsOn buildReact
    
  • 第三步:React代码中使用环境变量
    直接调用React内置的环境变量:

    fetch(`${process.env.REACT_APP_API_BASE_URL}/api/your-endpoint`)
      .then(res => res.json())
      .then(data => console.log(data));
    
  • 第四步:Gradle打包时指定环境

    # 打包IST环境
    ./gradlew build -Pspring.profiles.active=ist
    
    # 打包UAT环境
    ./gradlew build -Pspring.profiles.active=uat
    
    # 打包Prod环境
    ./gradlew build -Pspring.profiles.active=prod
    

方案选型建议

  • 方案1适合追求性能、不需要动态调整配置的场景,启动时一次性替换完成;
  • 方案2灵活性最高,甚至可以配合Spring Cloud Config实现运行时配置更新;
  • 方案3适合CI/CD流程标准化的场景,构建时就生成对应环境的部署包,部署流程更简洁。

内容的提问来源于stack exchange,提问作者user1912935

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 08:20:42