资讯动态

前后端分离的作家信息管理系统:SpringBoot+Vue+MyBatis实战全解析

发布时间:2026/10/21 21:52:01 来源:尧图企业网站定制
如果你正在物色一个能拿得出手的Java全栈实战项目或者说是在准备毕业设计、课程设计那么“前后端分离的作家信息管理系统”这个方向真的非常典型。项目用SpringBoot做后端服务Vue做管理界面MyBatis负责数据库访问MySQL存数据整个链路非常完整而且“获奖作家”这个主题让系统天然带有数据检索、分类统计、荣誉档案管理这类功能场景不会让人觉得是空架子。这类系统最核心的价值在于它不是一个简单的CRUD演示而是可以扩展成多种信息管理场景的通用的数据管理系统。无论是管理作家、管理图书还是管理其他的领域专家资料只要把字段换一下骨架就都能复用。对初学者来说可以从这个项目里看到真实项目开发的全流程——从数据库设计、接口定义到页面交互、联调部署。对经验不多的开发者来说这套技术组合也是面试和工作中出现频率最高的非常值得吃透。这篇内容我就按我自己做类似项目的思路把这套系统的设计逻辑、编码要点、部署步骤和遇到的坑完整梳理一遍。希望能帮到你。1. 项目整体设计与技术选型思路1.1 为什么要做前后端分离我最早接触这类管理系统的时候用的还是传统模板引擎那套写法Java代码里套HTML页面逻辑混在一起。后来做过几个前后端分离的项目再回头去看确实能明显感觉到优势。对这个作家管理系统来说前后端分离从架构上把“数据处理”和“页面展示”彻底解耦了后端只负责提供接口把作家信息、获奖记录这些数据以JSON格式返回前端只负责界面渲染通过Ajax请求拿数据再展示到表格和图表上。这样的拆分带来几个实际好处。第一前后端可以并行开发前端先根据约定好的接口文档做页面后端同时做接口实现不用互相等着。第二独立部署之后后端接口不只有Web端能用以后如果想做个移动端或者小程序直接复用同一套API就好了。第三对于个人学习来说调试起来思路也很清晰——接口报错就查后端页面渲染不对就查前端问题定位的边界非常明确。有一个地方需要提前明确前端和后端的职责边界到底在哪里。很多新手容易把一些业务逻辑比如“获奖年份是否合法”这种判断同时写在前端和前端里造成重复逻辑。我的习惯是前端做基础校验必填项、格式检查用来提升交互体验后端做最终的数据合法性校验保证接口的安全性。这样前后端各司其职。1.2 技术栈选型与取舍这个项目选的是SpringBoot Vue MyBatis MySQL组合可以说是目前Java开发里最经典的一套搭配了。SpringBoot的好处不用多说它让项目搭建变得非常简单。以前用SSM的时候光配置各种XML就够折腾半天的SpringBoot把大部分配置自动化了我们用注解就能完成配置比如RestController、Service、Mapper这些开发效率提高了不少。对于作家管理系统这种规模的项目来说SpringBoot默认提供的内嵌Tomcat容器也让打包部署省了很多事——直接打成一个jar包就能跑。MyBatis和SpringData JPA之间我更倾向于MyBatis。虽然JPA的自动建表、自动CRUD上手很快但MyBatis在SQL层面的控制力更强。这个系统里有不少按条件动态查询的场景按作家姓名模糊搜索、按获奖级别筛选、按作品数量进行统计排序这些SQL在Mapper文件里写动态SQL非常直观也能针对复杂查询做手工优化。相比之下JPA的复杂查询在调试和优化的时候往往绕不开自己对SQL的理解和检查。前端选了Vue加上Element UI组件库做后台管理系统效率很高。现在Vue3已经非常成熟我用的是Vue3配合Element Plus。如果还是用Vue2的话建议搭配Element UI。需要提醒的是Vue2和Vue3在路由、打包、响应式原理上差别很大不要混着学选一个版本就按着那个版本的生态来。MySQL是经典的的关系型数据库数据关系简单清晰作家的基本信息、获奖记录、代表作品表之间用主外键关联起来特别适合关系型存储。这个系统完全不涉及复杂的非结构化数据用MySQL既稳定又方便。1.3 功能模块与页面规划做管理系统之前强烈建议先把功能模块梳理干净。我的习惯是先画一个简单的文字版功能清单然后再动手写代码。这个作家信息管理系统核心可以分成以下几块。基本信息管理作家档案的增删改查包括姓名、籍贯、生卒年、文学体裁类型、个人简介等信息。获奖信息管理记录作家获得的各类奖项包括颁奖年份、奖项名称、获奖作品、奖项等级等。代表作品管理维护作家的代表作列表包括作品名称、作品类型、出版年份、荣誉情况等信息。数据统计与检索在前端提供快速筛选体裁、获奖级别、所属地区以及简单的可视化统计例如按体裁统计作家数量。在页面规划上我用一个左侧菜单栏右侧内容区的经典布局。菜单包含作家列表、获奖管理、数据统计、系统管理。作家列表是主页面展示搜索区域、统计卡片和数据表格数据统计页用ECharts展示柱状图或饼图系统管理里可以放管理员登录和基础配置。这样的结构逻辑简单对入门者压力不大。2. 数据库设计与后端实现要点2.1 数据表结构与字段规划数据库设计是整个项目的地基表结构一旦确定后面的接口、页面全都要照着来。我先说具体的三张核心表作家基本信息表、获奖记录表、代表作品表。作家基本信息表我习惯给它取名为t_writer。字段大概包括id主键、writer_name姓名、pen_name笔名、gender性别、birth_date出生日期、death_date逝世日期可空、birth_place籍贯、category_id所属体裁ID、brief_intro个人简介、cover_url头像图片地址、create_time创建时间、update_time更新时间。注意像“籍贯”这种字段如果你在应用里要按地区筛选最好单独存储省份和城市或者在设计阶段统一规范格式。获奖记录表t_award字段包括id、writer_id作家ID、award_name奖项名称、award_level奖项级别国家最高奖、重要文学奖等、award_year获奖年份、related_work获奖作品、remark备注。这张表和作家表是多对一关系一个作家可以有多条获奖记录。代表作品表t_work字段包括id、writer_id作家ID、work_name作品名称、work_type作品类型小说/诗歌/散文/报告文学等、publish_year出版年份、award_status是否获奖、summary内容简介。除了这三张表我还会做一张t_category体裁分类表存文学体裁的分类信息。这样文化分类可以作为独立的字典管理后端接口返回分类列表前端下拉框动态加载。整体数据关系不算复杂但每组关系都对应着前端的一个具体功能点理解了这几张表的关系整个项目的数据流就清楚了。设计表结构时有个细节需要强调字符串字段必须要考虑字符集问题。尤其是作家简介这种可能包含生僻字、特殊标点的文本一定要把数据库、表、字段的字符集统一设置为utf8mb4而不是utf8。utf8mb4才是真正完整的UTF-8编码支持有些字数少的生僻字在utf8下会存不进去直接报错我就在一个作者生僻字的存储上踩过这个坑。MyBatis开启驼峰映射map-underscore-to-camel-case让数据库列名writer_name和Java属性writerName自动对应代码里会少很多繁琐的映射工作。2.2 MyBatis下的SQL编写细节MyBatis的Mapper层是这个项目后端最核心的部分。我常用的方式是写一个WriterMapper接口再用对应的XML文件写SQL而不是用注解直接写在接口上。原因很简单动态SQL在XML里写结构更清晰尤其是在拼接多条件查询的时候复杂程度一上来注解方式根本不好维护。举一个最常见的按条件分页查询例子。前端传入作家姓名关键字、体裁ID、获奖情况筛选条件后端根据这些条件动态组装SQL配合MyBatis的动态where标签和if标签实现。像这样select idselectWriterList parameterTypemap resultTypecom.example.entity.Writer SELECT w.*, c.category_name AS categoryName FROM t_writer w LEFT JOIN t_category c ON w.category_id c.id where if testwriterName ! null and writerName ! AND w.writer_name LIKE CONCAT(%, #{writerName}, %) /if if testcategoryId ! null AND w.category_id #{categoryId} /if if testawardLevel ! null and awardLevel ! AND w.id IN ( SELECT writer_id FROM t_award WHERE award_level #{awardLevel} ) /if /where ORDER BY w.create_time DESC /select这里有几个关键点要说明。第一模糊查询不要直接写LIKE %#{value}%这种语法MyBatis会把它当成字符串的一部分处理匹配永远失效正确做法是CONCAT(%, #{writerName}, %)。第二#{}和${}要严格区分#{}会预编译成?占位符能有效防止SQL注入平时一律用#{}而${}是直接拼接字符串只能在表名、排序字段这类不能用占位符的场景下使用而且必须严格控制参数来源。第三多表查询的时候建议提前规划好JOIN关系获奖筛选这里如果担心单独子查询效率可以改为直接关联t_award表再配合DISTINCT具体取哪种要看实际数据量情况。还有一个容易忽略的点批量插入获奖记录。如果一个作家有多条获奖记录前端一次提交多条后端别在Java里循环执行单条insert性能差且事务也不好控制。直接使用MyBatis的foreach标签一次插入全部效率会高很多insert idbatchInsertAward INSERT INTO t_award (writer_id, award_name, award_level, award_year, related_work, remark) VALUES foreach collectionlist itemaward separator, (#{award.writerId}, #{award.awardName}, #{award.awardLevel}, #{award.awardYear}, #{award.relatedWork}, #{award.remark}) /foreach /insert2.3 统一接口与全局异常处理的封装写后端接口时最忌讳的就是每个接口的返回结构都不一样。比如一个返回字符串另一个直接返回对象还有一个只在出错时返回错误信息。这样前端同学处理起来非常崩溃。我在这套系统里统一封装了一个Result类结构固定为三个字段code表示状态码、message表示提示信息、data表示实际数据。所有接口无论成功失败都返回这个结构成功时code为200失败时根据业务规则定义其他的错误码。前端写一个统一的响应拦截器先判断code不是200就直接弹错误提示不需要在每个页面上重复处理。全局异常处理模块也值得投入时间实现一次。用RestControllerAdvice注解定义一个全局异常处理器把参数校验异常、业务异常、数据库异常分别映射到对应的返回信息。这样做的好处非常实际代码里不需要到处写try-catch业务代码干净清爽所有异常都从同一个出口出去。安全方面这个系统至少要做一层管理员登录验证。虽然完整实现JWT或者Spring Security认证也不算复杂但如果你只是想先跑通完整功能也可以用最基础的思路——登录成功后把用户信息存到Session里后端写一个拦截器校验未登录请求直接返回401前端根据401跳转到登录页。等基础版本跑顺了再升级成JWT方案也不迟。3. Vue前端界面实现与联调细节3.1 前端项目搭建与目录结构前端我用Vue3来搭建官方推荐用Vite作为构建工具。Vite启动速度比老牌Webpack快太多了开发调试体验比较友好。不过要提醒一下如果用Vue3Vite后面打包发布时生成的dist目录结构、Nginx配置方式和Vue2有些细节上的区别自己心里要有数。创建项目时可以先手动明确一下目录结构。一般会分成api所有接口请求封装、views页面组件、components公共组件、router路由配置、store状态管理、utils工具函数这几大块。这个结构能让你在项目变大以后依然保持清晰。举个例子api/writer.js里面写作家相关的所有接口调用函数比如getWriterList、saveWriter、deleteWriter这样页面组件里只负责调用这些函数不直接写axios请求后续接口地址一改只动一处就好。一个规范的项目里axios一定要封装成公共实例。统一配置baseURL、请求超时时间添加请求拦截器自动附带登录凭证添加响应拦截器统一解析Result结构体。在这里有个经验值得借鉴拦截器里不要只弹出一个笼统的“请求失败”要把后端返回的message透传过来比如“该作家姓名已存在”这样的提示对操作者来说才有意义。3.2 核心列表页与检索交互作家列表页是整个系统使用频率最高的页面。我的实现思路是页面顶部是一个搜索表单区域中间是表格区域底部是分页器右上角是“新增作家”按钮。这个布局在当前管理系统里是通用做法使用者一看就明白。搜索表单包含三个字段姓名关键字输入框、体裁下拉选择、获奖情况筛选。搜索表单提交后调用getWriterList接口传入当前页页码、每页条数和表单数据。这里有个小细节每页条数我习惯默认10条但要允许用户调成20或50前端改变后要重新请求列表。搜索条件每次变化时页码要重置回1否则如果当前在第5页但你换了搜索关键词很可能返回的就是空列表。表格列主要包括作家姓名、笔名、体裁、籍贯、作品数、获奖数、最后更新时间、操作按钮。其中操作按钮一般是“查看”“编辑”“删除”。删除操作需要二次确认我用的是组件库的ElMessageBox.confirm弹窗避免用户误点一下就把数据清掉了。查看详情可以弹一个对话框展示该作家的完整信息包括个人简介和获奖时间线。如果有大量数据还建议增加“批量删除”功能后端需要额外提供一个接收ID数组的删除接口。这里虚一个典型场景来说明交互设计编辑获奖记录的时候前端要支持动态增删行。每行包含奖项名称、级别、年份、获奖作品用户点“添加一行”就往表单里push一个空对象提交时把所有行一起提交到后端批量保存。这个交互在Element Plus的表格加表单组合上很容易实现但要注意校验——获奖年份不能为空获奖作品不能太长至少控制在文本限制以内。3.3 统计图表与数据可视化的实现这个系统既然叫获奖知名作家信息管理系统那“奖”字的统计展示就不能只停留在列表里。可视化是提升系统档次的关键加分项。我选了ECharts这个图表库功能强大到基本没有什么图表是它画不出来的。在统计页面我做了两个图表一个饼图展示不同体裁的作家数量占比一个柱状图展示每一位获奖作家获得的重大奖项数量。两个图表的数据来源完全可以通过同一个后端统计接口返回——后端用GROUP BY分组按体裁统计作家数量再写一个按获奖记录表统计作家获奖次数的SQL。前端只需要在轮询到后端返回数据后把数据转化成ECharts的series所需的格式然后调用setOption方法。图表初始化的时间点需要注意。ECharts绑定在某个DOM元素上所以一定要在页面组件挂载完成、DOM已经存在后再初始化否则会因为找不到渲染容器而报错。同时图表容器的宽度高度如果有待变化最好在窗口调整大小时重新调用resize方法刷新否则会出现图表变形的问题。这些虽然是细节但恰恰是经常被忽视、又最容易影响展示效果的地方。3.4 前后端联调的环境配置方法联调阶段最容易踩的坑就是跨域问题。本地开发时前端开发服务器默认跑在5173端口Vite默认或者8080端口后端接口跑在8080或9090端口两个端口不一样浏览器就会拦截跨域请求。开发环境的联调方案我用过两种。第一种是在后端写一个CorsConfig配置类通过注册CorsFilter来允许指定来源的跨域请求。这个方案配置简单但要注意别把allowedOrigins直接写成*因为*意味着任何站点都能调用你的接口安全上不太建议。第二种方案是前端通过Vite的代理来转发。在vite.config.js里配置server: { port: 5173, proxy: { /api: { target: http://localhost:8080, changeOrigin: true } } }这样前端请求/api/writer/list的时候开发服务器会转发到http://localhost:8080/api/writer/list浏览器看到的始终是同源请求也就绕过了跨域限制。我在实际项目里更推荐代理方式因为生产环境本来就会用Nginx做反向代理开发环境和生产环境的行为是一致的。联调还有一个检查点确认请求方式、参数名和返回格式。建议打开浏览器的开发者工具看Network面板里请求的实际情况核对接口返回的Response数据结构和前端请求体是否匹配。很多时候“联调失败”不是因为后端不行而是前端传参名写错、后端参数名对不上查半天才发现是小字段名不一致。多沟通、多用工具能省下很多Debug时间。4. 完整部署流程与实操记录4.1 本地运行环境准备不论系统做成什么样部署都要从环境准备开始。我不建议用太新的版本尽量靠近长期稳定的版本组合。后端要装JDK8或JDK11SpringBoot2.x都支持得很稳Maven 3.6以上MySQL 5.7或8.0。前端要装Node.js 16以上。其中有一个容易出问题的地方JDK17和旧版SpringBoot的兼容性可能会出问题如果你的SpringBoot主版本是2.3.x以下就别用JDK17了。如果你打算换JDK17就配合SpringBoot 2.7以上或者直接上SpringBoot 3.x不过SpringBoot 3.x要求JDK17及以上的同时MyBatis相关的starter也要注意适配版本。如果你不想在这种兼容性问题上消耗时间直接选用一套目前主流教材和模板里最常见的组合——JDK8 SpringBoot 2.7 MySQL 8.0这套组合我怕你踩的坑最少。MySQL这边导入SQL脚本后要检查一下建库语句里的编码设置。我之前一般会在脚本最开始写上CREATE DATABASE IF NOT EXISTS writer_db DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; USE writer_db;这样可以保证整个库的默认字符集没问题。然后修改后端application.yml里的数据库地址、用户和密码。其实我们经常在部署文档里看到数据库连接地址是localhost:3306这里如果是在服务器上可能你要改成服务器的内网地址或是直接用localhost都可以只要能连通就行。4.2 SpringBoot打包与启动命令后端项目打包之前先确认单元测试不会拦路。现在很多项目模板里自带的测试类打包时报错很常见。一个稳妥的方式是在打包命令里跳过测试mvn clean package -DskipTests如果Maven在下载依赖时非常慢考虑配置一下阿里云的私服镜像地址在settings.xml的mirrors节点里加入镜像配置下载速度能快好几倍。我早期经历过一个项目光下载依赖就花了半个多小时的惨痛教训换镜像之后几分钟就全部下来了。打包成功之后target目录下会有一个xxx.jar文件。本地可以直接用java -jar writer-system-0.0.1-SNAPSHOT.jar运行过程中如果提示端口被占用可以使用--server.port8081或者修改配置文件来重设端口。生产环境建议还是用systemd方式托管Java进程这样即使程序异常退出也能自动拉起崩溃了看一眼日志就能恢复。这里我只说一个最基础的systemd配置思路创建一个writer.service服务文件指定ExecStart为启动jar包的命令设置日志输出路径然后systemctl enable开机自启、systemctl restart writer管理进程这样就比手动挂一个窗口灵活稳当。4.3 Vue构建与Nginx发布前端构建命令非常直接npm run build构建完成后项目根目录下会生成一个dist文件夹里面就是纯静态文件。接下来用Nginx托管这些静态文件并把/api请求反向代理到后端服务的地址。我常用的Nginx配置是这个样子server { listen 80; server_name your_domain_or_ip; root /data/project/writer/dist; index index.html; location /api/ { proxy_pass http://127.0.0.1:8080/api/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } location / { try_files $uri $uri/ /index.html; } }这里location /中的try_files是Vue项目部署的命门。如果你用的是history路由模式页面访问某个子路由后刷新Nginx会先尝试查找对应的真实文件路径找不到就回退到index.html由Vue路由在前端重新匹配。如果漏了这一行会出现“页面刷新后就404”的经典问题。后端接口路径也要匹配。前端axios实例里的baseURL如果配置成/api那么/api/writer/list这样的请求会直接由Nginx转发到后端Tomcat的/api/writer/list。这就要求后端Controller的Request路径里也要加上/api前缀或者在后端配置server.servlet.context-path/api前后保持一致即可。我习惯在后端的RequestMapping类名上加前缀例如RequestMapping(/api/writer)这样接口路径从设计上就统一了。部署完成后记得开放服务器防火墙对应端口、配置安全组规则不然80端口外面访问不到又是一个让人怀疑人生的问题。5. 常见问题与排查技巧实录5.1 环境安装与构建阶段的坑Maven依赖下载慢倒还好解决更多的新手会卡在npm依赖安装上。npm install偶尔会因为网络波动报错解决办法是删除node_modules目录和package-lock.json重新执行安装命令也可以考虑用npmmirror的镜像源设置。安装完依赖后如果启动报“vite不是内部或外部命令”多半是node_modules/.bin下的软链没有生成重装依赖一般能解决。MySQL驱动版本不匹配也是一个高频问题。如果你用的MySQL 8.0后端pom里的mysql-connector版本别是5.x的老版本会出现认证方式不兼容的报错。确保依赖坐标里是8.0对应版本并且在连接URL上加上useSSLfalseserverTimezoneAsia/Shanghai。时区参数如果不加后面涉及时间的查询和写入很容易和本地时间相差8小时。5.2 前后端联调时的典型问题跨域报错是最常见的。详情看浏览器的Console提示如果是CORS相关错误检查后端是否开启了跨域配置或者Nginx是否配置了代理。另外要特别注意的是跨域错误有时候会表现为请求的OPTIONS预检请求失败后端需要正确响应预检请求。接口返回401还有一个常见原因是前端没有把登录凭证带过去。如果你用的是Token方式检查请求拦截器里是否把Authorization头统一加到请求上如果你用的是Session方式检查前端请求是否设置了withCredentials: true。这类问题描述起来很玄但其实多半就是一个配置属性没写对。联调时数据不一致的问题同样恼人。比如前端下拉框显示体裁列表但数据库中根本不存在的分类ID被存进去了那么列表页可能显示一个空名称或报错。解决方法是后端在保存数据时做一次外键校验或者直接用关联表查询来避免生成这种脏数据。后端接口的入参校验也不能省哪怕只是检查String字段是不是为空、日期格式对不对都要保证后端不被脏请求搞崩。5.3 上线运行后的稳定性问题后端进程跑一段时间挂掉在无图形界面的服务器上很常见。有可能是内存不够用了。JVM启动时可以加上内存参数限制比如java -Xms256m -Xmx512m -jar writer-system.jar限制内存上限是为了防止内存溢出时把整台服务器拖垮。同时要看日志里有没有OutOfMemoryError如果频繁出现就要检查代码中是否有列表查询不加分页、一次性查出全表数据的情况。作家列表这种接口是尤其容易出问题的只要表里数据一多全量查询必然变慢。后端分页查询一定要从接口设计上落实前端分页控件只是应用层面的一个展示而已。前端上线后刷新页面就404、静态资源找不到等常见问题90%以上都是Nginx配置的try_files没配好。另一个连续踩过几回坑的场景是Nginx缓存了旧文件每次发版后记得在Nginx配置里对index.html禁用强缓存但给js/css等带hash的资源开启长缓存。这样才能保证用户访问页面时加载的是最新版本而资源文件又能走缓存加载得快一些。这类配置细节不太起眼实际体验影响却非常大。5.4 问题速查表症状常见原因快速处理方案后端启动报端口被占用端口冲突换端口或杀掉占用进程页面请求接口报CORS错误跨域配置缺失检查Nginx反向代理或后端CorsConfig中文数据显示为???字符集不对统一库表字段为utf8mb4页面刷新后404history路由Nginx未回退配置try_files回退到index.html数据库时间比本地晚8小时连接URL未设置时区添加serverTimezoneAsia/Shanghaijar包运行后立刻退出配置错误或数据库连不上查看日志确认启动时的具体异常npm install卡住网络不稳定换镜像源并重装依赖6. 写在最后的经验心得从数据库设计到后端接口从Vue页面实现到Nginx上线这个作家信息管理系统的完整链路走下来基本就把一套主流的前后端分离项目的开发流程摸遍了。我个人的体会是这类管理系统最难的从来不是单个技术点而是把整条链路串起来的能力——你知道一张表的数据如何流动到页面上也明白一次请求从浏览器到后端再返回经历了哪些环节这才是做这个项目真正的收获。如果你还想在现有基础上继续扩展我会建议下一步尝试接入更完善的权限校验机制、给作家信息加上图片上传功能、或者增加导入导出的能力。每加一个功能都会带出一串新的知识点这也是这个领域持续进修的乐趣所在。希望这篇文章对你有实际的帮助。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑