AWS Elastic Beanstalk部署Spring Boot+React应用的前端异常问题
问题背景
开发了一个包含Java Spring后端和React前端的简单应用,本地运行正常,但部署到AWS Elastic Beanstalk后React前端功能异常。应用分为backend和frontend两个子模块,后端通过Controller提供接口,前端通过React调用接口并渲染页面。本地启动后端后执行npm start即可正常工作,但部署到AWS EB后,浏览器仅显示"Start page"文本,无React的头部和样式,推测React未正常运行。部署方式为上传Maven构建的.jar文件,后端pom.xml已配置在maven install时将React的build目录收集到后端target目录中。
代码片段
Spring Controller
@RestController @CrossOrigin @RequestMapping() public class StartPageController { @GetMapping("/") public String startPage() { return "Start page"; } }
React App.js
import React, {useState, useEffect} from 'react'; import './App.css'; function App () { const [message, setMessage] = useState(""); useEffect(() => { // fetch('https://*mywebsite*.com/api/v1/hello') fetch('https://*mywebsite*.com') .then(response => response.text()) .then(message => { setMessage(message); }); },[]) return ( <div className="App"> <header className=""> <h1>React is here!</h1> <h2 className="App-title">{message}</h2> </header> </div> ) } export default App;
更新后的测试情况
按照建议本地测试.jar文件并重构代码后,成功部署到AWS,但仍存在React与后端的连接问题:
- 保留
StartPageController(映射"/"路径),且App.js调用fetch('https://*mywebsite*.com')时,访问根域名仅显示"Start page"文本,无React功能。 - 注释
StartPageController,保留BasicController(映射"api/v1/hello"),且App.js调用fetch('https://*mywebsite*.com/api/v1/hello')时:- 访问根域名可显示"React is here!"和"Hello Everyone !"文本,React功能正常;
- 直接访问
/api/v1/hello仅显示"Hello Everyone !"文本,无React功能。
// 第二种场景的BasicController @RestController @CrossOrigin @RequestMapping(path = "api/v1") public class BasicController { @GetMapping("/hello") public String sayHello() { return "Hello Everyone !"; } }
疑问解答
1. 为何React无法配合"/"接口正常工作?
Spring的请求映射优先级高于静态资源访问。当Controller映射了根路径"/"时,所有访问根域名的请求都会被该Controller拦截,直接返回"Start page"字符串,不会去加载React打包后的静态index.html页面,自然无法触发React的渲染逻辑。
2. 为何第二种情况中,主域名显示React功能,而/api/v1/hello路径不显示?
- 主域名没有对应的Controller映射,Spring会自动查找静态资源目录下的index.html文件并返回,因此React应用正常加载,之后通过fetch调用后端接口获取数据并渲染。
/api/v1/hello是后端接口的专属路径,被Controller处理后直接返回接口的文本结果,这是后端接口的预期行为——接口只负责提供数据,而React是在前端页面中调用该接口来展示数据,并非让接口返回React页面。
3. 据了解AWS会对"/"接口进行健康检查,为何注释对应Controller后应用仍能正常运行?
AWS Elastic Beanstalk的健康检查默认仅校验请求的HTTP状态码是否为2xx。当没有Controller映射"/"时,Spring会返回静态资源的index.html页面,HTTP状态码为200,符合健康检查的通过条件。如果需要更精准的健康检查,可在EB的配置中修改健康检查路径,比如指定为专门的健康检查接口(如/health)。
内容的提问来源于stack exchange,提问作者pragmatic

