TomEE服务器上Spring Boot Maven项目的React路由失效问题
问题描述
在TomEE服务器上部署整合React应用的Spring Boot Maven项目时,本地运行时React路由与Spring后端均正常,但部署到服务器后仅根路径(/)可正常访问,其他React路由(如/test)均返回Spring的404错误,服务器日志无报错信息。
相关代码
Spring控制器类
@CrossOrigin @RestController @RequestMapping("api") public class DemoController { @GetMapping("/demo") public List<String> demo(){ List<String> list = new ArrayList<>(Arrays.asList("Hello", "World", "from", "Spring!")); return list; } }
React App.js
import {Route, Routes} from "react-router-dom"; import Test from "./components/test"; function App() { return ( <Routes> <Route index element={<Test />} /> <Route path="test" element={<div>Test</div>} /> </Routes> ); } export default App;
React index.js
... import {BrowserRouter} from "react-router-dom"; const root = ReactDOM.createRoot(document.getElementById('root')); root.render( <React.StrictMode> <BrowserRouter basename={process.env.PUBLIC_URL}> <App /> </BrowserRouter> </React.StrictMode> );
环境配置
.env.localPUBLIC_URL=..env.productionPUBLIC_URL=/Expo-project-0.0.1-SNAPSHOT
package.json 脚本
"scripts": { "start": "react-scripts start", "build": "env-cmd -f ./.env.production react-scripts build", "test": "react-scripts test", "eject": "react-scripts eject" }
pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.7.9</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>no.hvl.dat109</groupId> <artifactId>Expo-project</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>war</packaging> <name>Expo-prosject</name> <description>Expo-prosject</description> <properties> <java.version>11</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <dependency> <groupId>org.postgresql</groupId> <artifactId>postgresql</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <scope>provided</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
已尝试的解决方法
- 在
.env文件中添加尾部斜杠 - 使用
HashRouter替代BrowserRouter - 修改控制器指向
index.html
解决方案
问题核心是:直接访问React路由时,TomEE会将请求转发给Spring处理,但Spring没有对应路径的控制器,因此返回404。需要让Spring将所有非API的GET请求转发到index.html,由React路由接管处理。
1. 添加前端路由转发控制器
创建控制器,匹配所有非API、非静态资源的GET请求,转发到index.html:
import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; @Controller public class ForwardController { // 匹配所有不含后缀的路径,排除API和静态资源 @GetMapping(value = "/**/{[path:[^\\.]*}") public String forwardToIndex() { return "forward:/index.html"; } }
2. 配置Maven复制React构建产物
修改pom.xml,添加资源复制插件,将React build后的文件自动复制到Spring的静态资源目录:
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> <!-- 复制React构建产物到Spring静态目录 --> <plugin> <artifactId>maven-resources-plugin</artifactId> <executions> <execution> <id>copy-react-build</id> <phase>process-resources</phase> <goals> <goal>copy-resources</goal> </goals> <configuration> <outputDirectory>${project.build.outputDirectory}/static</outputDirectory> <resources> <resource> <directory>${project.basedir}/build</directory> <filtering>false</filtering> </resource> </resources> </configuration> </execution> </executions> </plugin> </plugins> </build>
执行顺序:先运行npm run build生成React构建产物,再执行mvn package打包war包。
3. 验证上下文路径配置
确保.env.production中的PUBLIC_URL与TomEE部署的war包上下文路径完全一致:
PUBLIC_URL=/Expo-project-0.0.1-SNAPSHOT
如果自定义了TomEE的上下文路径(如在conf/server.xml中配置Context的path属性),需同步修改PUBLIC_URL的值。
4. 确认TomEE部署
将打包好的war包放入TomEE的webapps目录,TomEE会自动解压部署。若需自定义上下文路径,可在conf/server.xml中添加:
<Context docBase="Expo-project-0.0.1-SNAPSHOT" path="/your-custom-path" reloadable="true"/>
内容的提问来源于stack exchange,提问作者Espen Grebstad
相关产品推荐
相关产品推荐

