ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

SpringBoot+Vue+MySQL全栈项目实战:信息管理系统搭建全解析

SpringBoot+Vue+MySQL全栈项目实战:信息管理系统搭建全解析 这套入门级的SpringBootVueMySQL网站信息管理项目很多朋友问我要搭建细节。它自带用户登录、后台管理、内容发布全套流程开箱即跑特别适合毕业设计、期末课程作业或者想快速上手全栈开发的新人。下面我把整个项目从设计思路到实际跑的每一步都拆开讲包括我踩过的坑。1. 项目拆解这套三层架构到底在做什么1.1 为什么是SpringBootVueMySQL这套经典组合先聊聊技术选型。在Java Web领域SpringBoot基本上已经成了事实标准。它内嵌了Tomcat省去了繁琐的XML配置一个main方法就能启动整个后端服务。Vue在前端生态里的地位类似组件化开发让页面逻辑变得清晰响应式数据绑定省掉了一大堆操作DOM的代码。MySQL则是轻量级关系型数据库的常青树对于信息管理这类事务型系统绰绰有余。这三者的分工特别明确MySQL存数据SpringBoot提供接口和处理业务逻辑Vue负责把数据渲染成页面。我给这套项目定的目标就是开箱即跑所以后端做到了零XML配置前端用Vue CLI构建数据库脚本直接导入就能用。你不用再像老项目那样折腾各种环境变量、路径配置这套东西把配置都收敛在了application.yml和.env文件里。1.2 信息管理系统的核心业务闭环一个标准的网站信息管理系统核心就三件事账号权限管理、信息内容发布、前台展示与检索。开发这份源码时我按照“管理后台前台展示”的模式设计覆盖了一个中小型网站的日常运营场景。管理端通常包含用户管理、栏目分类、文章/资讯发布、置顶推荐、敏感词过滤这些模块。前台则要根据栏目动态渲染页面支持搜索、分页、按时间排序。这些都是CMS系统的基础能力这套源码把它们做成了可以二次开发的骨架你自己加个轮播图、友情链接模块都不费劲。提示如果你第一次拿到这套源码先不要急着改业务代码按给出的运行步骤把环境跑通再对照数据库表结构看代码效率会高很多。1.3 项目目录结构与阅读顺序建议很多朋友拿到源码习惯先打开pom.xml一顿操作这其实是误区。我建议按这个顺序看代码源码包根目录 ├── backend/ # SpringBoot后端 │ ├── src/main/java # Java源码 │ ├── src/main/resources/application.yml # 后端核心配置 │ └── pom.xml # Maven依赖管理 ├── frontend/ # Vue前端 │ ├── src/views/ # 页面组件 │ ├── src/router/ # 前端路由 │ └── package.json # 前端依赖管理 └── sql/ # 数据库初始化脚本先看sql目录里的建表语句理解数据模型接着看后端controller层的接口列表明白能调用哪些功能再看前端页面搞清楚谁调了谁。这样整个数据流向在你脑子里就清晰了。后面我会逐个环节讲解核心代码的实现逻辑跟随操作即可。2. 后端核心SpringBoot接口与权限控制的落地实现2.1 springbootjavamaven项目构建的依赖管理SpringBoot项目离不开Maven的依赖管理。我见过不少新手直接把网上复制的一大段依赖粘到pom.xml里结果版本冲突各种报错。这套源码里的依赖搭配是经过实战验证的核心部分如下parent groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-parent/artifactId version2.7.18/version relativePath/ /parent dependencies !-- Web开发起步依赖 -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency !-- MyBatis-Plus 数据库ORM简化CRUD -- dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-boot-starter/artifactId version3.5.3/version /dependency !-- MySQL驱动 -- dependency groupIdcom.mysql/groupId artifactIdmysql-connector-java/artifactId scoperuntime/scope /dependency !-- Lombok省掉getter/setter -- dependency groupIdorg.projectlombok/groupId artifactIdlombok/artifactId optionaltrue/optional /dependency !-- JWT认证 -- dependency groupIdio.jsonwebtoken/groupId artifactIdjjwt/artifactId version0.9.1/version /dependency /dependencies这里特别说一下MyBatis-Plus的选择理由。传统MyBatis写SQL还得维护一堆XML文件对于信息管理系统这种简单CRUD来说太重了。MyBatis-Plus内置了通用的insert、selectPage等方法大部分数据库操作一行代码都不用写SQL。只有复杂的多表查询才需要手写SQL这正好卡在效率与灵活的平衡点上。2.2 数据库连接与springboot配置的核心配置文件application.yml是整个后端的心脏。我刚拿到官网下载的MySQL时配置了SSL导致启动报错这些坑后面在问题排查环节细说。标准配置长这样server: port: 8080 servlet: context-path: / spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/web_info_system?useUnicodetruecharacterEncodingutf-8useSSLfalseserverTimezoneAsia/ShanghaiallowPublicKeyRetrievaltrue username: root password: 你的数据库密码 jackson: date-format: yyyy-MM-dd HH:mm:ss time-zone: GMT8 mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl global-config: db-config: id-type: auto有几个参数我建议你一定不要随意删。serverTimezoneAsia/Shanghai解决时区差8小时的问题useSSLfalse避免本机测试时的SSL握手提示allowPublicKeyRetrievaltrue配合MySQL 8.0新版连接驱动使用不然会报Public Key Retrieval错误。字符集务必指定为utf-8否则插入中文直接乱码。log-impl配置成StdOutImpl会在控制台打印所有SQL语句这对前期调试帮助极大。上线时删掉这行就行不会有任何功能影响。2.3 认证与授权基于JWT的用户登录设计信息管理系统的后台管理必须做权限控制。我用JWTJSON Web Token做无状态认证这套方案比传统的Session更符合前后端分离架构。浏览器发起登录请求后后端验证账号密码成功后签发一个有效期2小时的Token返回给前端。前端每次请求都带上这个Token后端通过拦截器判断身份合法性。令牌生成的核心代码封装在工具类里public class JwtUtil { private static final String SECRET_KEY your-secret-key-change-me; private static final long EXPIRE_TIME 2 * 60 * 60 * 1000; // 2小时 public static String generateToken(String username, Integer userId) { return Jwts.builder() .setSubject(username) .claim(userId, userId) .setIssuedAt(new Date()) .setExpiration(new Date(System.currentTimeMillis() EXPIRE_TIME)) .signWith(SignatureAlgorithm.HS256, SECRET_KEY) .compact(); } }配合拦截器实现接口保护放行登录接口、静态资源其余接口要求Token有效。这套设计真正做到了不清除Token服务端就无需存储水平扩展时无需共享Session各个服务间认证策略一致。2.4 SpringBoot整合业务层文章发布与栏目管理的接口约定接口设计直接决定前端开发的效率。我习惯用RESTful风格定义接口返回统一封装的结果对象Result。比如文章管理模块定义了这些核心接口接口路径请求方式功能说明是否需Token/api/article/listGET文章分页列表否/api/article/detail/{id}GET文章详情否/api/article/savePOST新增文章是/api/article/updatePUT编辑文章是/api/article/delete/{id}DELETE删除文章是/api/category/treeGET栏目树形结构否把所有接口都统一在Controller层Service层只做业务逻辑Mapper层只碰数据库。这样做的最大好处是前端拿到的数据格式永远是{ code: 200, data: ..., msg: 操作成功 }处理逻辑可以高度统一。如果你准备在这个项目上加模块照着这个模式抄就行。经验分享接口路径一定用复数名词列表接口一定分页。我早期写接口返回全量数据数据量一大前端页面直接卡死这是很痛的教训。3. 前端实现Vue 3项目结构、路由与API联动3.1 vue安装及环境配置与项目初始化前端环境是很多新手的一道坎。我推荐用Vue 3 Vite的组合比Vue CLI那套快太多。先确保本机装了Node.js 16.18以上版本然后执行# 全局安装Vite脚手架 npm create vitelatest frontend -- --template vue cd frontend # 安装项目依赖 npm install # 安装路由、状态管理、HTTP请求库 npm install vue-router4 pinia axios # 启动开发服务器 npm run dev启动后Vite默认跑在5173端口开发模式下它有热更新功能改代码浏览器秒刷新。但真实部署时前端构建后生成静态文件放在Nginx里做反向代理同时把/api路径转发到后端8080端口。这样前后端就像是同一个服务规避了跨域问题。开发模式下跨域用Vite的代理配置解决在vite.config.js里加上这段import { defineConfig } from vite import vue from vitejs/plugin-vue export default defineConfig({ plugins: [vue()], server: { port: 5173, proxy: { /api: { target: http://localhost:8080, changeOrigin: true } } } })这样前端请求就通过/api关键字转发到后端不需要改动业务代码。3.2 vue路由前端页面跳转与登录守卫逻辑Vue Router承担了前端所有页面跳转逻辑。一个信息管理系统通常有这些路由页面首页、文章列表、文章详情、登录页、后台管理首页、用户管理、栏目管理、文章编辑。我按模块划分路由文件// src/router/index.js import { createRouter, createWebHistory } from vue-router const routes [ { path: /, name: Home, component: () import(/views/Home.vue) }, { path: /article/:id, name: ArticleDetail, component: () import(/views/ArticleDetail.vue) }, { path: /login, name: Login, component: () import(/views/Login.vue) }, { path: /admin, name: Admin, component: () import(/layout/AdminLayout.vue), meta: { requiresAuth: true }, children: [ { path: , redirect: /admin/dashboard }, { path: dashboard, component: () import(/views/admin/Dashboard.vue) }, { path: user, component: () import(/views/admin/UserManage.vue) }, { path: article, component: () import(/views/admin/ArticleManage.vue) }, { path: category, component: () import(/views/admin/CategoryManage.vue) } ] } ]登录守卫是前端权限控制的核心。所谓守卫就是一个路由跳转前的钩子函数用户没有Token但访问了需要登录的页面直接重定向到登录页。router.beforeEach((to, from, next) { const token localStorage.getItem(token) if (to.meta.requiresAuth !token) { next(/login) } else { next() } })这套逻辑足够覆盖后台管理场景。注意localStorage里存Token有一个特点——浏览器关闭后Token依旧存在所以Token有效期2小时的机制还挺合理的。刷新页面后前端能直接恢复登录状态。3.3 vue样式与页面组件后台布局如何搭建后台管理界面的布局直接决定使用体验。我采用了典型的侧边栏顶栏内容区三段式结构。侧边栏放菜单顶栏放用户信息和退出按钮中间是内容区。这个布局用Vue实现非常自然顶栏和侧边栏作为AdminLayout.vue组件固定内容区用router-view /动态渲染子页面。以用户管理页为例主要包含一个搜索框、一个新增按钮、一个数据表格和一个分页器。Vue 3的script setup语法让代码很简洁template div classuser-manage el-card el-form inline el-form-item label关键词 el-input v-modelsearchKeyword placeholder用户名/昵称 / /el-form-item el-form-item el-button typeprimary clickloadUsers搜索/el-button /el-form-item /el-form el-table :datauserList border stripe el-table-column propid labelID width80 / el-table-column propusername label用户名 / el-table-column propnickname label昵称 / el-table-column propcreateTime label注册时间 / el-table-column label操作 width150 template #default{ row } el-button sizesmall typedanger clickdeleteUser(row.id)删除/el-button /template /el-table-column /el-table el-pagination v-model:current-pagepageNum v-model:page-sizepageSize :totaltotal current-changeloadUsers / /el-card /div /template我选用了Element Plus作为UI组件库它是Vue生态里最成熟的桌面端组件库表格、表单、弹窗这些后台管理高频组件做得非常完善。如果搞政务类系统还有个vue-admin系列的模板可以套但那个重了些这套轻量设计自己改改足够用了。3.4 前后端数据交互Axios请求封装与拦截器axios请求封装是前端工程化的标配它把HTTP请求逻辑统一管理。请求拦截器自动在header里加Token响应拦截器统一处理错误码。这样每个页面组件里只管调用api.getArticleList()不用关心Token怎么带、401怎么处理。// src/utils/request.js import axios from axios import { ElMessage } from element-plus import router from /router const request axios.create({ baseURL: /api, timeout: 10000 }) // 请求拦截器自动附带Token request.interceptors.request.use(config { const token localStorage.getItem(token) if (token) { config.headers.Authorization token } return config }) // 响应拦截器统一处理错误 request.interceptors.response.use( response { const res response.data if (res.code ! 200) { ElMessage.error(res.msg || 请求失败) return Promise.reject(new Error(res.msg)) } return res }, error { if (error.response?.status 401) { ElMessage.error(登录已过期请重新登录) localStorage.removeItem(token) router.push(/login) } else { ElMessage.error(网络异常请稍后重试) } return Promise.reject(error) } ) export default request这个封装解决了我之前在后端项目里遇到的问题接口请求失败时前端白屏毫无提示排查起来十分痛苦。现在把错误信息统一用ElMessage弹出来前端调试体验瞬间提升了一个档次。4. 数据库设计MySQL表结构规划与数据导入4.1 核心表结构设计思路信息管理系统最少需要四张表用户表、栏目分类表、文章表、操作日志表。我先从用户表说起因为它决定了权限体系。-- 用户表 CREATE TABLE sys_user ( id int NOT NULL AUTO_INCREMENT COMMENT 主键ID, username varchar(50) NOT NULL COMMENT 用户名, password varchar(100) NOT NULL COMMENT 密码(MD5加密), nickname varchar(50) DEFAULT NULL COMMENT 昵称, avatar varchar(255) DEFAULT NULL COMMENT 头像地址, role varchar(20) DEFAULT admin COMMENT 角色admin/editor, status tinyint DEFAULT 1 COMMENT 状态1启用/0禁用, create_time datetime DEFAULT NULL COMMENT 创建时间, update_time datetime DEFAULT NULL COMMENT 更新时间, PRIMARY KEY (id), UNIQUE KEY uk_username (username) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT系统用户表;密码字段严禁明文存储。源码里密码用MD5加密虽然现在MD5的安全性不再值得推荐但对于入门项目足够了。项目上建议升级到BCryptspring-security-crypto包直接支持改造成本很低。4.2 文章与栏目表的关联设计文章表是信息系统的核心业务表它通过category_id外键关联栏目表实现“一个栏目下有多个文章”的一对多关系。-- 栏目分类表 CREATE TABLE category ( id int NOT NULL AUTO_INCREMENT, name varchar(50) NOT NULL COMMENT 栏目名称, code varchar(50) DEFAULT NULL COMMENT 栏目编码, sort_order int DEFAULT 0 COMMENT 排序号, create_time datetime DEFAULT NULL, PRIMARY KEY (id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; -- 文章信息表 CREATE TABLE article ( id int NOT NULL AUTO_INCREMENT, title varchar(200) NOT NULL COMMENT 文章标题, summary varchar(500) DEFAULT NULL COMMENT 文章摘要, content mediumtext COMMENT 文章内容(HTML格式), cover_image varchar(255) DEFAULT NULL COMMENT 封面图地址, category_id int DEFAULT NULL COMMENT 所属栏目ID, is_top tinyint DEFAULT 0 COMMENT 是否置顶1是/0否, status tinyint DEFAULT 1 COMMENT 状态1发布/0草稿, view_count int DEFAULT 0 COMMENT 浏览量, create_by int DEFAULT NULL COMMENT 发布人ID, create_time datetime DEFAULT NULL, update_time datetime DEFAULT NULL, PRIMARY KEY (id), KEY idx_category_id (category_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT文章表;content字段用了mediumtext而不是varchar这是关键决策。文章正文动辄几千字用varchar(255)会截断数据。view_count字段做浏览量虽然并发高时会有锁竞争问题但中小网站完全不用担心用UPDATE article SET view_count view_count 1 WHERE id ?这种原子操作就可以。4.3 mysql安装配置教程与数据脚本导入步骤数据库初始化脚本在sql/init.sql里包含了建库、建表、插入初始管理员的完整操作。导入有两条路命令行方式推荐mysql -u root -p sql/init.sql执行后会提示输入密码回车后脚本自动完成建库建表和数据导入。图形化工具方式打开Navicat或者DBeaver新建连接然后“运行SQL文件”选择init.sql。注意一点脚本里如果有建库语句要先在工具里确认当前连接没有选库否则可能执行报错。脚本结尾通常有一条插入初始管理员的语句默认账号admin、密码admin123MD5加密后存储。首次登录后务必修改密码这个别偷懒。5. 环境准备与本地运行实操指南5.1 JDK、Node与MySQL版本选型避坑建议本地运行这套源码环境版本搞错是最大的坑。根据实测推荐以下版本搭配软件推荐版本版本说明JDK1.8SpringBoot 2.7最稳用17也能跑但有小坑Maven3.6.33.8对镜像配置有要求容易下载报错Node.js16.18 LTSVite 3/4都支持太新反而有兼容问题MySQL5.7或8.0连接串有微小差异脚本两者兼容IDEIDEA 2021社区版也够用装Lombok插件必需这里重点说说SpringBoot版本问题。现在搜索springboot看到的是3.0以上的资料但如果你用3.0Java版本必须17一些老版本的MyBatis-Plus也不兼容。为了一把跑通用SpringBoot 2.7.x JDK 8是最稳妥的组合。生产环境更新我建议等新项目再说旧项目升级代价不小。5.2 三步搞定后端启动从IDEA打开到控制台输出后端启动步骤极其简单但要小心每一步IDEA导入项目选择File - Open选中后端目录IDEA识别到pom.xml后自动下载依赖。这一步如果下载慢参考后面5.4节配置Maven镜像。修改数据库配置打开application.yml把username和password改成你本机的MySQL账号密码。密码里有特殊字符、#等整个值周围要加引号。运行启动类找到Application.java右键Run。控制台出现SpringBoot的LOGO后最后一行出现Started Application in x.x seconds说明启动成功。如果端口被占用修改server.port或者杀掉占用进程。后端启动成功后可以先在浏览器直接访问http://localhost:8080/api/article/list无需登录的接口看到JSON数据返回就说明后端环境OK。5.3 三步搞定前端启动npm依赖安装与代理配置前端启动更加顺手cd frontend npm install npm run dev第一行npm install是最容易出问题的环节。国内网络环境建议配置npmmirror镜像npm config set registry https://registry.npmmirror.comnpm run dev跑起来后终端会显示Local: http://localhost:5173/。浏览器访问这个地址页面能正常打开就算成功。然后测试登录功能填入初始化账号如果跳转到后台首页说明前后端联通没问题了。5.4 Maven依赖下载慢的终极解决方案Maven从中央仓库下载依赖在国内特别慢甚至超时失败。解决方案是配置阿里云镜像。找到Maven安装目录下conf/settings.xml在mirrors标签内加mirror idaliyunmaven/id mirrorOfcentral/mirrorOf name阿里云公共仓库/name urlhttps://maven.aliyun.com/repository/central/url /mirror如果你装的是IDEA内置的Maven用IDEA配置Settings - Build, Tools - Maven - settings.xml指定你刚改过的那个文件。之后再重新导入项目依赖下载速度会有质的飞跃。5.5 生产环境部署的另一种思路前后端分离的Nginx配置本地开发更推荐前后端分离模式但部署到服务器上时Nginx反向代理是标准做法。Nginx配置一块核心区域server { listen 80; server_name your-domain.com; # 前端静态文件 location / { root /app/frontend/dist; index index.html; try_files $uri $uri/ /index.html; # Vue History路由回退 } # 后端API反向代理 location /api/ { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } }注意后端接口路径都带/api前缀所以代理可以按照这个前缀转发。前端构建命令是npm run build输出到dist目录直接把这个目录指向Nginx的root就行。部署时Linux服务器跑后端的命令建议用nohupnohup java -jar web-info-system.jar app.log 21 6. 常见问题与排查技巧实录6.1 mysql ssl连接错误与Public Key Retrieval故障这是新手遇见最多的问题。启动后端时如果报SSL connection error或Public Key Retrieval is not allowed问题出在连接串。MySQL 8.0默认开启了caching_sha2_password认证驱动连接时需要额外处理。解决方案就是我在2.2节说的连接串末尾必须带useSSLfalseallowPublicKeyRetrievaltrue。还有一种情况密码是空密码也会导致认证失败。测试环境可以给MySQL root账号设置一个简单密码但千万别在生产环境用空密码。6.2 npm run dev之后页面打不开端口占用与依赖缺失排查前端启动失败通常分两种端口被占用Vite默认的5173端口被其它程序占用了。观察报错里的Port 5173 is in use提示更换端口// vite.config.js server: { port: 5174, strictPort: false // 端口不可用时自动换下一个 }依赖缺失npm install警告缺少peer dependencies或者启动时标志Could not resolve某个包。最省事的办法是删掉node_modules目录和package-lock.json重新执行npm install。这个方法能解决90%的前端依赖问题。6.3 中文乱码数据库字符集与前端页面的双重排查中文乱码是个多环节问题建议按照“数据流”顺序排查数据库表字符集先确认表是utf8mb4而不是latin1。如果建库时没指定可以直接改ALTER TABLE article CONVERT TO CHARACTER SET utf8mb4;后端连接串characterEncodingutf-8有没有写进application.yml。前端HTML编码.html文件头部有没有meta charsetUTF-8。Vue项目通常在index.html里已经设置好了。MySQL服务端字符集最容易被忽略。查询SHOW VARIABLES LIKE character_set_server如果是latin1修改my.cnf[mysqld] character-set-serverutf8mb4改完重启MySQL服务。这一套查下来乱码问题基本都能解决。6.4 Token过期后前端没有跳转登录页的处理Vue Router的守卫只处理前端路由跳转但接口请求返回401时前端路由层面是感知不到的。我在3.4节的响应拦截器里已经写了统一处理——收到401就清除本地Token跳转登录页。如果你改了代码没生效检查拦截器代码里localStorage.removeItem(token)是否执行了以及路由实例是否被正确导入。另外一个常见问题是Token过期时间到了但后端拦截器没有正确捕获过期的ExpiredJwtException导致返回的是500而不是401。排查后端控制台是否有io.jsonwebtoken.ExpiredJwtException异常拦截器的catch (Exception e)里要对JWT异常做专门判断。try { // 校验Token } catch (ExpiredJwtException e) { response.setStatus(401); response.setContentType(application/json;charsetutf-8); response.getWriter().write({\code\:401,\msg\:\登录已过期\}); return; } catch (JwtException e) { response.setStatus(401); response.getWriter().write({\code\:401,\msg\:\无效的Token\}); return; }7. 功能扩展方向与二次开发建议这套源码的定位是“可运行的骨架”。拿到手且跑通后根据自己的场景去改业务比从零写框架要高效得多。我列出三个我认为价值最高的扩展方向。文件上传与媒体资源管理。信息管理系统必然涉及图片上传目前很多源码只在数据库里存了一个图片URL字符串。你可以引入MinIO做对象存储。网上关于“minio加入到springboot”的资料非常多核心就是加依赖、配置客户端、提供上传接口。加个七牛云或阿里云OSS的SDK也能达到类似效果但MinIO可以本地起服务适合学习和测试。数据统计与图表看板。后台首页如果只有欢迎语就太浪费了。用ECharts配合后端统计接口做“文章发布趋势图”“栏目文章占比图”视觉效果好而且技术门槛不高。毕竟管理后台的核心价值是让管理者看清数据。多角色权限分离。目前实现的是单管理员角色。真正的CMS系统编辑、审核、管理员每个角色的权限都不一样。你可以在后端拦截器里加入角色判断在前端路由里用meta.roles配置可见性。这个扩展做完你对权限设计的理解能上一个台阶。我在实际项目里还有一个很深的体会给代码写注释不是浪费时间。我当初接手这个项目时原作者的基础代码没写注释导致我梳理逻辑花了整整两天。后来我养成了一个习惯每个Controller类顶部写一段接口职责说明每个复杂SQL写一句执行逻辑。这也是给未来接手的人包括三个月后的自己留了一份礼物。最终这套SpringBootVueMySQL的组合别追求用上最时髦的技术先把全链路的CRUD跑通把登录鉴权吃透把前后端数据交互搞明白这就是全栈开发最好的起点。你后续遇到的所有微服务、分布式、容器化难题都是在这套基础能力之上叠加的。把地基打好上面盖什么都稳。
返回列表