SpringBoot+React 前后端分离
SpringBoot+React 前后端分离
后端
简单用 SpringBoot 起个服务,写个接口处理请求:
@RestController
@RequestMapping("/data")
public class DataController {
    @Autowired
    HttpRequestService httpRequestService;
    @Autowired
    TestService testService;
    @RequestMapping("/test")
    public List<?> reportTest(@RequestParam("file") MultipartFile file) throws IOException {
        InputStream inputStream = file.getInputStream();
        System.out.println(file.getName());
        List<TestEntity> testEntities = testService.DataListRead(inputStream, file.getOriginalFilename());
        httpRequestService.postTest(JSON.toJSONString(testEntities));
        // 进行文件的读取和处理操作
        return testEntities;
    }
}
我这个方法的具体业务就是接收前端请求传来的文件,调用 Service 解析内容并转发出去。直接返回解析后的对象列表了,这是不太好的,应该封装一个 ResponseBody 才对,但我这就随意了。
后端 SpringBoot 默认的端口是 8080,启动后放着就可以了。
前端
前端在 VSCode 中使用 NPM 初始化一个纯净的React项目,然后按步骤补充几个关键文件:
- App.js,应用程序最大的组件;
 - index.html,页面入口;
 - index.js,将 App 渲染到页面上;
 - style.css,让页面好看的(可选)。
 
首先是 App.js 组件:
import React, { useState } from 'react';
import axios from 'axios';
import './style.css';  // 引入样式文件
function FileUpload() {
  const [file, setFile] = useState(null);
  const [interfaceType, setInterfaceType] = useState(null);
  const handleSubmit = async (e) => {
    e.preventDefault();
    const formData = new FormData();
    formData.append('file', file);
    let url = '';
    switch (interfaceType) {
      case 'test':
        url = 'http://localhost:8080/data/test';
        break;
      case 'vehicle':
        url = 'http://localhost:8080/data/vehicle';
        break;
      case 'battery':
        url = 'http://localhost:8080/data/battery';
        break;
      default:
        return;
    }
    try {
      const res = await axios.post(url, formData, {
        headers: {
          'Content-Type': 'multipart/form-data'
        }
      });
      console.log(res);
      alert('文件上传成功');
    } catch (error) {
      console.error(error);
      alert('文件上传失败');
    }
  };
  return (
    <div>
      {/* <h1>文件上传</h1> */}
      <form onSubmit={handleSubmit}>
        <div>
          <label htmlFor="fileInput">请选择文件:</label>
          <input type="file" id="fileInput" accept=".xls,.xlsx" onChange={(e) => setFile(e.target.files[0])} />
        </div>
        <div>
          <label htmlFor="testOption">测试数据 </label>
          <input type="radio" name="interface" id="testOption" value="test" onChange={(e) => setInterfaceType(e.target.value)} />
        </div>
        <div>
          <label htmlFor="vehicleOption">车辆数据 </label>
          <input type="radio" name="interface" id="vehicleOption" value="vehicle" onChange={(e) => setInterfaceType(e.target.value)} />
        </div>
        <div>
          <label htmlFor="batteryOption">电池数据 </label>
          <input type="radio" name="interface" id="batteryOption" value="battery" onChange={(e) => setInterfaceType(e.target.value)} />
        </div>
        <div>
          <button type="submit">提交</button>
        </div>
      </form>
    </div>
  );
}
export default FileUpload;
仅由一个组件构成,其中使用了 axios 发送请求,参考 AXIOS 文档。
然后是 index.js 文件,将组件渲染到页面上:
import React from 'react';
import ReactDOM from 'react-dom/client';
import FileUpload from './App';
//ReactDOM.render(<FileUpload />, document.getElementById('root'));
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<FileUpload />);
由于使用 NPM 安装的 React 是18版本的,因此 ReactDOM.render 方法已经被弃用了,需要换成 ReactDOM.createRoot 方法,大同小异。
HTML 页面和 CSS 样式就不用放了,一个是只有个 root 节点,一个我自己都看不懂。
然后在项目路径下使用 npm start 启动项目,React 的默认端口是 3000,打开就可以看到页面了。
跨域问题
此时前端应用和后端服务都已经部署好了,在页面上发起请求尝试,在请求情况中可以看到请求失败了,状态为 CORS 错误,这是由于浏览器的同源策略导致的:
同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。在同一个协议,域名,端口号下时,是为同源。
同源策略是浏览器的行为,是为了保护本地数据不被 JS 代码获取回来的数据污染,因此拦截的是客户端发出的请求回来的数据接收,即请求发送了,服务器响应了,但是无法被浏览器接收。
在上面,我们访问的是 3000 端口的前端应用,而前端应用去后端服务 8080 端口请求数据,因此触发了浏览器的跨域请求保护。
当然 CORS 问题是可以解决的,而且解决的办法有很多,我选择最简单的一种,在后端服务的 Controller 上添加注解 @CrossOrigin:
@CrossOrigin
@RestController
@RequestMapping("/data")
public class DataController
这样这个 Controller 的请求就支持跨域访问了。但如果有很多地方或者整个项目都要支持跨域访问的话,还是使用 Config 配置的方式好一点。

                
            
        
浙公网安备 33010602011771号