Spring Boot + Vue前后端分离项目实战:从搭建到部署全流程
2026/9/15 18:05:18 网站建设 项目流程

前后端分离这个词,我在面试里被问了不下二十次,在公司也带过好几个从单体项目转过来的新人。很多人一上来就慌:两个项目怎么起、端口怎么配、请求发过去都是报错、跨域到底谁解决。真上手并不复杂,但网上教程要么太老,还在用Vue CLI 2.x那一套;要么只讲单边,后端讲完了前端一笔带过。这篇我把一套完整的springboot+vue前后端分离项目从环境准备、工程搭建、联调debug到打包部署,全部过一遍,新手能照着做完,有点基础的也能顺手补上几个你平时没注意的细节。

先说清楚这篇覆盖什么:一个Spring Boot 2.7/3.x后端接口服务,一个Vue 3 + Vite前端单页应用,两者通过HTTP JSON通信。全流程能跑通一个简单的增删改查,最后给出部署到服务器的方案。同时会穿插讲几个你在实际开发中一定会撞上的坑,包括版本不匹配、npm安装失败、跨域配置失效、打包后刷新404这些。

1. 前后端分离解决了什么问题:想明白架构逻辑再动手

很多新手学前后端分离,一上来就急着敲代码,结果目录建了一堆,不知道数据到底是怎么流动的。先不急着写,花三分钟理解这套东西的运行逻辑,后面排错能省一半时间。

1.1 传统开发方式的问题在哪

以前做Java Web项目,典型做法是JSP + Servlet,前端页面直接写在服务端工程里。一个登录页面,左边是HTML标签,右边嵌着一堆<% %>脚本,里面还混着Java代码。前端要调样式,得让后端把整个项目重启一遍;后端想改个数据结构,还得先去前端页面上找哪里引了这个字段。项目大了之后,代码跟毛线团一样,牵一发动全身。

更麻烦的是分工。前端和后端挤在同一个代码仓库,合并分支必然冲突;联调的时候,两边代码没合并完根本跑不起来,开发效率被严重拖累。前后端分离就是把这两块硬拆开,谁也别管谁,只通过接口互相通信。

1.2 分离之后的数据流是什么样的

现在的前后端分离架构,核心就一句话:前端负责展示和交互,后端负责数据和业务逻辑,两者之间通过HTTP接口(一般是JSON格式)对话。

一个用户在前端页面上点了一下“查询列表”,实际发生的事情是:

  1. Vue组件里的事件被触发
  2. axios(前端发HTTP请求的工具)向后端某个URL发一个GET请求,比如http://localhost:8080/api/user/list
  3. 后端Spring Boot的Controller接收到这个请求,调用Service层处理业务,再从数据库查出数据
  4. 查到的数据被序列化成JSON,通过HTTP响应返回给前端
  5. 前端拿到这段JSON,在Vue的data或状态管理里更新,页面自动重新渲染

整个过程里,前端和后端唯一约定的东西,就是“接口长什么样”:请求路径、请求方式、参数名、返回数据结构。只要这个约定不变,前端把页面从Vue换成React,后端只需静静地看着,不用改一行代码;后端把数据库从MySQL换成PostgreSQL,前端也不会有任何感知。这就是“高内聚低耦合”在Web开发里的最典型体现。

注意:前后端分离不是“不用看后端代码了”,而是“不依赖后端代码才能开发”。接口文档和字段约定依然是协同时的重中之重。

1.3 这套架构里你必须搞懂的三个关键点

第一是跨域。前端跑在http://localhost:5173,后端跑在http://localhost:8080,端口不同,浏览器的同源策略就会拦截响应。这个本文第五章会重点讲。第二是接口约定。前后端开发可以并行,前提是接口文档先定好,字段名、类型、分页参数、错误码规范都要明确。第三是构建与部署分离。前端打包后是一堆静态文件,由Nginx这类Web服务器托管;后端打包成一个可执行的JAR包,独立运行。二者可以部署在同一台机器,也可以分开部署,互不影响。

现在架构逻辑清楚了,开始动手。

2. 环境准备里的版本陷阱:JDK、Node、Maven怎么选不会打架

这一步看着没啥技术含量,但坑最深。我见过太多人项目启动失败,最后发现是JDK版本和Spring Boot版本不兼容。先说结论:如果你想用Spring Boot 3.x,必须装JDK 17及以上;如果你还在用JDK 8,老老实实选Spring Boot 2.7.x,不要追新。

2.1 版本对应关系速查

后端组件版本要求
JDK8 / 11只能跑Spring Boot 2.x
JDK17+可以跑Spring Boot 3.x
Spring Boot2.5~2.7稳定,资料多,适合学习
Spring Boot3.0+新特性多,但部分旧依赖不兼容
Maven3.6.3+都可以,3.8.x以上建议用3.8.8
前端组件版本说明
Node.js16.xVue 3 + Vite 3/4可用
Node.js18.x / 20.xVue 3 + Vite 5推荐,性能更好
npm8.x+随Node自带,尽量用长期支持版本
Vue CLI4.x / 5.x老项目多,新项目建议用create-vue

有个现实问题:现在新电脑默认装的都是JDK 17甚至21,你照着B站老教程用Spring Boot 2.x,启动时会直接报错。这不是你代码写错了,是版本匹配不上。反过来,你用了Spring Boot 3.x,代码里写javax.servlet包,也会编译失败——因为Spring Boot 3已经迁移到了jakarta命名空间。这种问题到处都有提问,关键词就是“springboot版本太高”。

2.2 JDK、Maven、Node的安装要点

JDK安装建议直接下载官方安装包或使用包管理器。安装完成后务必在命令行确认版本:

java -version javac -version

之前见过一个同事,JDK装了,但JAVA_HOME环境变量没配,IDE能启动,命令行编译的时候报“找不到javac”。要是你也是这样,去系统环境变量里补一个JAVA_HOME,指向JDK安装目录,再在PATH里添加%JAVA_HOME%\bin,Windows下注意别把变量名拼错了。

Maven装完之后,强烈建议修改settings.xml里的镜像源,否则首次拉依赖龟速,尤其是Spring Boot这种动辄几十个依赖的工程:

<mirror> <id>aliyunmaven</id> <mirrorOf>central</mirrorOf> <name>阿里云公共仓库</name> <url>https://maven.aliyun.com/repository/public</url> </mirror>

Node.js这边,我建议装一个nvm(Node Version Manager),Windows下用nvm-windows,macOS/Linux用官方nvm脚本。为什么要用nvm?因为不同项目的Node版本要求不一样,老项目可能要Node 14,新项目要Node 20,手动画切换就是自虐。有了nvm,一行命令切版本,省心很多。

nvm install 18.20.4 nvm use 18.20.4 node -v npm -v

2.3 环境自检清单

开写之前,确认以下命令全部正常:

  • java -version显示17+(或你决定用的版本)
  • mvn -v显示Maven版本和JDK信息
  • node -vnpm -v正常输出
  • IDE能正常识别JDK版本

顺便把IDE(推荐IDEA社区版或旗舰版)里的Maven设置指向你自己的settings.xml,不要用IDE自带的默认配置,不然刚才配的镜像源不生效。

3. 后端Spring Boot工程搭建:从零到能跑通接口

环境准备好之后就快多了。后端工程我用IDEA的Spring Initializr方式创建,你只要跟着点几下,一个标准的基础工程就出来了。

3.1 用IDEA创建Spring Boot工程的正确姿势

打开IDEA,新建项目,选择“Spring Initializr”。如果你是Spring Boot 3.x,JDK选17;如果你是2.7.x,JDK选8或11都行。依赖这边,先选这三个最核心的:

  • Spring Web:处理HTTP请求,提供RestController等能力
  • Spring Boot Actuator:监控和管理接口(可选,但建议加)
  • Lombok:省掉getter/setter样板代码

如果你需要操作数据库,再加Spring Data JPAMyBatis FrameworkMySQL Driver。新手建议用JPA起步,SQL都不用自己写,理解起来更直观;有SQL基础的话可以选MyBatis-Plus,开发效率也高,国内用的团队多。我这里用MyBatis-Plus举例,毕竟真实项目里遇到得多。

创建完成后,IDEA会自动下载依赖并生成一个主类,长这样:

@SpringBootApplication public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } }

这个@SpringBootApplication是一个组合注解,它一次性解决了三件事:@SpringBootConfiguration标记这个类是配置类、@EnableAutoConfiguration开启自动装配、@ComponentScan扫描当前包及子包下的组件。这也是面试必问的“springboot自动装配”的入口。它的底层原理是:Spring Boot jar包里的META-INF/spring.factories文件声明了一堆自动配置类,程序启动时按条件(比如类路径下有没有某个依赖)决定加载哪些配置。你放一个spring-boot-starter-web依赖进pom,启动后DispatcherServlet、内嵌Tomcat就自动配好了,根本不用你手动写web.xml,这就是自动装配的功劳。

3.2 写一个能用的Controller

主类创建好之后,我们先不连数据库,写一个纯内存的接口验证链路通不通。建一个UserController

@RestController @RequestMapping("/api/user") public class UserController { private final Map<Long, String> users = new ConcurrentHashMap<>(); @GetMapping("/list") public Result<List<String>> list() { return Result.success(new ArrayList<>(users.values())); } @PostMapping("/add") public Result<Void> add(@RequestBody String name) { long id = users.size() + 1; users.put(id, name); return Result.success(null); } }

Result是一个统一响应体,通常长这样:

public class Result<T> { private int code; private String message; private T data; public static <T> Result<T> success(T data) { Result<T> r = new Result<>(); r.code = 200; r.message = "success"; r.data = data; return r; } }

@RestController注解是@Controller@ResponseBody的合体,方法返回的对象会自动序列化成JSON写入HTTP响应体。像@GetMapping("/list")这种写法,定义了“当有人GET请求/api/user/list路径时,执行这个list方法”。这个接口的URL拼起来是http://localhost:8080/api/user/list

写完后启动主类,浏览器访问http://localhost:8080/api/user/list,你会看到{"code":200,"message":"success","data":[]}。到这里,Spring Boot的web能力已经跑通了。

3.3 配置application.yml:常见坑位提前排掉

Spring Boot的默认配置在src/main/resources/application.properties,我更建议改成application.yml,结构清晰。核心配置如下:

server: port: 8080 spring: datasource: url: jdbc:mysql://localhost:3306/demo_db?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai username: root password: yourpassword driver-class-name: com.mysql.cj.jdbc.Driver jackson: date-format: yyyy-MM-dd HH:mm:ss time-zone: Asia/Shanghai mybatis-plus: configuration: map-underscore-to-camel-case: true mapper-locations: classpath:/mapper/**/*.xml logging: level: com.example.demo.mapper: debug

新手最容易踩的坑有三个:

第一,数据库连接URL里的serverTimezone必须配,否则高版本MySQL驱动会报时区错误。第二,驱动类名要写com.mysql.cj.jdbc.Driver,旧版的com.mysql.jdbc.Driver在MySQL 8下已经弃用。第三,map-underscore-to-camel-case: true这个配置能把数据库的user_name自动映射为Java实体里的userName,不配的话你查出来的字段会全部为null,而且很难排查。

如果你暂时没有数据库,可以先在pom里把MyBatis-Plus和MySQL依赖注释掉,只留web和lombok,最小化跑通。想加再取消注释,重启项目即可。

3.4 补充:一个完整的增删改查需要哪些文件

真实项目里肯定不是Controller一把梭。建议按下面的目录结构组织,这已经是行业通用规范了:

com.example.demo ├── controller/ # 接收前端请求,返回结果 ├── service/ # 业务逻辑层,处理具体业务 ├── mapper/ # 数据访问层,操作数据库 ├── entity/ # 数据库表对应的实体类 ├── common/ # 通用类:Result、异常处理、工具类 └── config/ # 配置类:跨域、拦截器、自定义配置

Controller只做参数接收和结果返回,业务逻辑写在Service层里,SQL操作封装在Mapper层。很多新手把所有代码堆在Controller里,一时是爽了,项目稍微一复杂就变成大泥球,维护成本直线上升。

4. 前端Vue工程搭建:npm这条路上的常见坑

后端接口有了,前端开始。这里最大的变化是:现在官方推荐用create-vue(也就是Vite)创建新项目,而不是用老的Vue CLI。你搜“vue安装及环境配置”的时候会看到大量旧教程还在用npm install -g @vue/cli然后vue create,这个流程在新项目里已经不建议用了。Vue CLI成立于webpack时代,启动和构建都慢,Vite用了浏览器原生ES Module,开发时启动秒开,热更新跟手,新一代项目的默认选择。

4.1 用Vite创建Vue 3项目

在命令行执行:

npm create vue@latest

它会问你要不要安装create-vue,按y,然后提示项目名称。接着会让你选一系列功能,新手先都选“No”,最多把Vue RouterPinia选上,这俩是后面必用的。TypeScript要不要?如果你之前用的都是JavaScript,第一步先用JS,别在学习的路上同时新增一个TS的变量。项目创建完,进入目录装依赖启动:

npm install npm run dev

浏览器打开http://localhost:5173,Vite的欢迎页出来了。这就算成功跑起来了。

4.2 npm install失败和慢的问题怎么治

这是前端新人第一道坎:“我啥都没写,为什么npm install就飘红?”原因五花八门,但95%都是网络或源的问题。Node的默认包源在国外,国内访问极其不稳定,解决办法是切换到国内镜像源。

npm config set registry https://registry.npmmirror.com

设完检查一下:npm config get registry,能看到淘宝镜像地址就对了。然后删除node_modulespackage-lock.json,重新npm install,速度会很可观。

如果还报错,看是不是node-sass这类老模块的锅。node-sass是个毒瘤,依赖Node版本,稍有偏差就编译失败。新项目如果用到了scss,建议直接装最新版的sass(Dart Sass),用法差不多,但纯Java实现,不依赖Node版本,安装几乎不会出问题。旧项目不得不继续用node-sass的,压箱底的手段是nvm切Node版本,直到跟node-sass的版本对上。

4.3 配置路由:前端页面是怎么跳转的

Vue Router其实就是一张映射表,把“URL路径”映射到“Vue组件”。配置在src/router/index.js里:

import { createRouter, createWebHistory } from 'vue-router' import UserList from '@/views/UserList.vue' import UserDetail from '@/views/UserDetail.vue' const router = createRouter({ history: createWebHistory(), routes: [ { path: '/', redirect: '/user' }, { path: '/user', component: UserList }, { path: '/user/:id', component: UserDetail } ] }) export default router

/user/:id中的:id是路由参数。页面上跳转时用router.push('/user/1')或者<router-link to="/user/1">。在组件里通过route.params.id拿到这个参数。两种模式里,createWebHistory是HTML5 History模式,路径干净没有/#/,好看也好分享,但有个前提:部署到服务器时必须让Nginx把所有路径都指回index.html,否则刷新页面直接404。后面部署章节会细说。

如果你不想配History模式,用createWebHashHistory会更省事,路径里多个#,刷新不会出问题,适合图省事或者没有Nginx控制权的场景。两种模式我实际项目都用过,小项目和学习阶段无所谓,正式对外服务我还是喜欢History模式,干净、专业,代价就是nginx配置多两行。

4.4 封装axios请求:以后改接口地址不用满项目翻

前端发HTTP请求基本都用axios,但不要让每个页面自己裸调axios,一定要统一封装一下。新建src/utils/request.js

import axios from 'axios' const request = axios.create({ baseURL: '/api', timeout: 10000 }) request.interceptors.request.use(config => { // 在这里统一加token,比如config.headers.Authorization = 'Bearer ' + getToken() return config }) request.interceptors.response.use( response => { // 统一处理响应体,如果code不是200就报错 const res = response.data if (res.code !== 200) { alert(res.message || '请求失败') return Promise.reject(new Error(res.message)) } return res }, error => { alert('网络异常,请稍后重试') return Promise.reject(error) } ) export default request

然后页面里调用:

import request from '@/utils/request' const { data } = await request.get('/user/list')

这里有个细节:baseURL: '/api',写的是相对路径。在开发环境下,Vite会把/api代理到后端地址,这样就不存在跨域问题了;生产环境Nginx会把/api反代到内网后端地址。所有的环境差异都被限制在这一个字符串里,改起来集中,不用在几十个页面里头改。

同时,建议把不同环境的接口地址放到.env.development.env.production里:

# .env.development VITE_API_BASE_URL = '/api'
# .env.production VITE_API_BASE_URL = '/api'

VITE_前缀开头的变量会被Vite自动加载,在项目里通过import.meta.env.VITE_API_BASE_URL读取。要是哪天后端地址变了,改这一处就好。

5. 前后端联调:跨域、代理与接口对接实战

前后端都准备就绪,直接调接口。你大概率会撞到的问题就是跨域。前端http://localhost:5173请求后端http://localhost:8080,浏览器控制台报一个红色错误:“Access to XMLHttpRequest at ... has been blocked by CORS policy”。别慌,这个就代表跨域了,解决方案有两种,搞清楚再用。

5.1 方案一:后端开启CORS,一劳永逸但要注意细节

后端加一个全局跨域配置类,这是最简单的方案。新建config/CorsConfig.java

@Configuration public class CorsConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOriginPatterns("*") .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") .allowedHeaders("*") .allowCredentials(true) .maxAge(3600); } }

调用接口后访问就正常了。这里要记住一个关键点:如果allowCredentials(true)allowedOrigins("*")会不生效,这是浏览器的安全策略——不允许携带cookie的请求发给任意源。所以要用allowedOriginPatterns("*")替代,这是Spring Boot 2.4以后推荐的做法,低版本只有allowedOrigins,需要手动列出具体来源地址。

业务代码里还有另一种更轻量的方式:在Controller或方法上直接加@CrossOrigin(origins = "http://localhost:5173")。这种方式粒度可控,适合只想给某个接口开权限的场景,但项目里接口多的时候,一个个加太麻烦,全局配置还是主流。

5.2 方案二:前端Vite代理,开发环境更优雅

实际开发中,我更推荐用Vite的代理来解决联调跨域,因为这样可以保持后端代码纯净,不写那些跟业务无关的CORS代码。在vite.config.js里加一段:

export default defineConfig({ server: { port: 5173, proxy: { '/api': { target: 'http://localhost:8080', changeOrigin: true, rewrite: path => path.replace(/^\/api/, '') } } } })

这个配置的含义是:只要前端请求/api开头的地址,Vite开发服务器就替你把请求转发到http://localhost:8080,然后把开头的/api前缀去掉。相当于中间架了一座桥,浏览器眼里你的请求从来没离开过localhost:5173,跨域问题自然就不存在。

这里有个容易懵的点:后端接口的路径到底带不带/api如果不带,代理配置里的rewrite就必须有,把前缀剥掉,否则请求发到后端变成/api/user/list,而后端路径只有/user/list,直接404。反过来,如果后端接口设计时就把/api作为统一前缀写进了@RequestMapping("/api/user"),那前端的baseURL和代理配置都要跟着调整,不能剥掉前缀。前后端在这个地方一定要对齐,这是联调最常见的第一类失误。

5.3 联调验证:从前端页面完整调用后端接口

我们写一个最简单的Vue页面来验证。src/views/UserList.vue

<script setup> import { ref, onMounted } from 'vue' import request from '@/utils/request' const users = ref([]) const fetchUsers = async () => { const res = await request.get('/user/list') users.value = res.data } onMounted(fetchUsers) </script> <template> <ul> <li v-for="user in users" :key="user.id">{{ user.name }}</li> </ul> </template>

启动后端,npm run dev启动前端,打开页面,如果能看到从后端返回的数据,联调链路就通了。这个过程中你可能遇到几个典型问题:

问题一:时间格式不对。后端返回LocalDateTime时,默认可能是一长串数字(时间戳)或者带T的格式。解决方案在后端配置Jackson的date-format,前端这边也要注意解析逻辑。前后端任何一方没处理好,页面上就是一行看不懂的字符。

问题二:Long类型精度丢失。数据库自增主键如果是Long类型,返回给前端时会变成1656647829564637185这样的19位数字,而JavaScript的Number类型最多安全表示16位,导致前端拿到的id最后几位变成0。这个坑特别隐蔽,列表里点了一个ID,后端收到的却是另一个。解决方法是让后端序列化时把这个字段转成字符串——在实体类字段上加@JsonSerialize(using = ToStringSerializer.class)即可,或者在全局配置里处理。

问题三:请求404但后端明明有接口。这个之前说过,查一下代理的rewrite是否把前缀剥干净了。打开浏览器F12,看Network里请求的实际URL是什么,比对后端@RequestMapping的路径,非常直观。

5.4 一个小技巧:善用浏览器的Network面板

联调时不要瞎猜,学会看Network面板。点一下请求,看四块信息:

  • Headers里的Request URL:确认请求发给了谁
  • Payload:确认前端传参是否正确
  • Response:确认后端返回了什么
  • Status Code:确认是400(参数问题)还是404(路径问题)还是500(后端代码异常)

500错误时,打开后端控制台,找到报错的异常堆栈,多半是业务代码抛了NPE或者SQL写错了。联调的能力基本等于“前端会看Network、后端会看堆栈”,这俩加一起能解决九成问题。

6. 从本地到可交付:打包部署与性能安全细节

本地跑通只是第一步,真正要交付,得把前后端分别打包,部署到服务器上。这一章的坑多到可以单独出一篇,这里挑最核心的说。

6.1 后端打包运行

后端打包非常简单,在项目根目录执行:

mvn clean package -DskipTests

打完包后在target目录下会生成一个demo-0.0.1-SNAPSHOT.jar。上传到服务器,直接:

java -jar demo-0.0.1-SNAPSHOT.jar

默认加载的是application.yml里的开发配置。生产环境往往需要覆盖数据库地址、密码这些,推荐把配置外置,比如在jar包同目录放一个application-prod.yml,然后:

java -jar demo-0.0.1-SNAPSHOT.jar --spring.profiles.active=prod

这样做的好处是,重新部署时不用重新打包,改配置也只动外部文件,不动jar包。我见过有团队每次改数据库密码都重新打一次包,纯属浪费时间。

生产环境跑jar不建议直接用java -jar挂在前台,用nohup放后台,或者用systemd做成服务:

nohup java -jar demo-0.0.1-SNAPSHOT.jar --spring.profiles.active=prod > app.log 2>&1 &

6.2 前端打包与Nginx部署

前端打包:

npm run build

生成一个dist目录,里面是index.html和一堆静态资源。把这个目录上传到服务器的Nginx静态页面目录,然后配置一个站点:

server { listen 80; server_name yourdomain.com; root /var/www/dist; index index.html; # 重要:History路由的回退配置 location / { try_files $uri $uri/ /index.html; } # 前端/api请求反向代理到后端服务 location /api/ { proxy_pass http://127.0.0.1:8080/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } # 静态资源缓存 location /assets/ { expires 30d; add_header Cache-Control "public, immutable"; } }

这里的try_files $uri $uri/ /index.html;就是解决History路由404的关键。它的含义是:先找对应的文件,找不到就找对应目录,再找不到就回退到index.html,由前端路由接管。没有这行配置,你访问http://yourdomain.com/user刷新页面,Nginx找不到/user这个文件,直接给你一个404;有了它,所有未匹配路径都回到Vue内部路由去解析,刷新就不挂了。

location /api/里的proxy_pass http://127.0.0.1:8080/,注意最后这个斜杠,它会把/api前缀剥掉,跟Vite代理的rewrite效果一样。如果后端接口设计是带/api的,这里就写成proxy_pass http://127.0.0.1:8080;不带斜杠,不要把前缀去掉。跟开发环境保持一致,互相照应着配。

6.3 这些安全问题越早知道越好

接口裸奔上线是大忌。结合热词里提到的“springboot heapdump敏感信息泄露漏洞”,我单独说几个一定要处理的安全点。

第一,Actuator端点一定要管控。如果你引入了spring-boot-starter-actuator,默认会暴露/actuator/env/actuator/heapdump等端点。heapdump会把JVM堆内存导出来,里面可能包含数据库密码、token、密钥等敏感信息,一旦泄露等于给攻击者递刀。生产环境务必关闭非必要端点:

management: endpoints: web: exposure: include: health,info

你要是根本用不到监控,干脆把Actuator依赖从pom里去掉,最干净。

第二,数据库密码不要明文写在配置文件里。生产环境的密码用环境变量传入,比如:

spring: datasource: password: ${DB_PASSWORD}

然后启动时设置环境变量,或者用配置中心统一管理。这是投入最小、收益最大的一道防线。

第三,接口鉴权。凡是对外提供的API,除了登录接口,都应该校验身份。最常用的方案是JWT,登录成功后后端签发一个token,前端请求时在Header里带上Authorization: Bearer <token>,后端用拦截器或Spring Security统一校验。密码存库一定要用BCrypt加密,不要用MD5。MD5现在用彩虹表几秒就能暴力破解,纯属裸奔。

第四,统一异常处理。@RestControllerAdvice@ExceptionHandler把未捕获的异常兜住,不要把堆栈信息直接返回给前端。给用户看的是“服务器开小差了”,真正的错误详细记在日志里。这也是Web安全里“不要泄露内部实现信息”的基本原则。

6.4 扩展方向:这些热词背后是下一阶段的进阶点

当你跑通了上面的全链路,你其实已经掌握了前后端分离项目中最核心的主干。很多人在此基础上,会基于热搜词继续延展自己的技术栈:

  • vue播放m3u8:这是视频流播放场景,Vue前端里用video.jshls.js播放m3u8流媒体格式,配合后端文件服务或流媒體服务器,是视频类项目常见需求
  • 若依vue开源项目:若依(RuoYi)是一套开源的基于Spring Boot + Vue的后台管理脚手架,代码生成、权限管理、部门管理都内置好了,你对照它的代码能学到很多企业级项目的组织方式,但建议先自己从零走一遍,直接看它的代码容易看不懂
  • flowable整合springboot:这是工作流引擎集成场景,适合考勤审批、工单流转这类业务,属于Spring Boot生态里的进阶整合
  • redis在springboot中的使用:缓存是后端性能优化绕不开的一环,用Redis做热点数据的缓存,加一个注解就能大幅降低数据库压力

这些方向都建立在“前后端分离项目能跑通”的基础上。地基不牢,谈这些等于往沙子上盖楼。

最后分享几个我实际带人时反复强调的习惯。一是前后端开发一定要先定接口再动手,别前端敲着代码等后端改路径,后端画着接口等前端发请求。花二十分钟对清楚路径、参数、字段名,后面至少省出两小时的联调时间。二是环境变量和配置文件的区分要养成肌肉记忆,本地开发一套配置,生产一套配置,靠profile切换,不要把本地数据库密码提交到代码仓库。三是遇到报错先读日志,从前到后读一遍再动手改,很多时候异常信息已经把答案告诉你了,只是你没耐心看。以上这些真正做到,你就从“能跑通”迈进了“能干活”的阶段。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询