SpringBoot+Vue汽车资讯网站管理系统实战开发全流程
做JavaWeb项目这些年SpringBootVue这对组合算是绕不开的搭配。前段时间刚完成一个汽车资讯网站管理系统从需求梳理、数据库设计到前后端联调最后打包部署整个流程走下来收获不少。这个项目用JavaMySQLMyBatis做后端数据层SpringBoot搭建接口服务Vue负责前端页面渲染覆盖了资讯发布、分类管理、内容检索、用户浏览这些核心场景。对于正在做毕业设计、或者想熟悉前后端分离开发全流程的同学来说是一个很完整的参考样本。我把这个项目的设计思路、核心细节和踩坑过程整理出来里面有完整的源码结构和数据库脚本照着做就能跑起来。1. 项目定位与技术选型为什么是SpringBootVue1.1 汽车资讯网站到底在解决什么问题汽车资讯网站不是一个简单的“文章展示页”。用户端需要按分类浏览新车评测、行业动态、用车技巧要能搜关键词、看详情、点赞评论管理端需要发布文章、管理分类、控制上下架状态、查看数据。这些需求背后其实就两个核心问题内容怎么管、内容怎么展现。传统的做法是JSPServlet页面和逻辑混在一起改一个小功能就要动整个页面尤其是后台管理界面维护成本极高。换成前后端分离之后前端只负责展示和交互后端只提供数据接口两边可以并行开发互不干扰。这个项目选型的时候我直接把技术栈定为SpringBootVueMyBatis一是这套组合在Java生态里最成熟二是网上资料多遇到问题容易找到解决方案。1.2 各层技术各自负责什么先明确一下每个框架在这个项目里的职责边界SpringBoot负责提供RESTful接口处理业务逻辑管理Bean的生命周期。内置Tomcat打包后一个jar直接跑部署非常省事。MyBatis负责数据库的增删改查。SQL由开发者自己控制复杂多表查询、动态条件拼接都比JPA灵活尤其适合资讯这种需要多条件筛选的场景。Vue负责页面渲染和用户交互。组件化开发让页面像搭积木一样组合数据驱动视图不用再手动操作DOM。MySQL存储所有业务数据文章、分类、用户、评论都落在这里。这四样配合起来有一个明显的好处任何一个环节有问题都能快速定位。比如前端页面显示不对打开控制台看接口返回再查后端日志最后看SQL语句问题在哪一层一目了然。2. 数据库设计与后端核心实现2.1 表结构设计从需求到建表数据库设计是整个项目的根基。我设计表的时候坚持一个原则先列需求再建表。所有功能点先写出来再拆成字段最后整合成表。这个项目一共设计了五张核心表管理员表admin_userid、username、password、role、create_time。密码必须加密存储这里用的是BCrypt千万不能明文存这是最基本的红线。用户表userid、nickname、avatar、phone、create_time。用户表的字段按需增减如果要做第三方登录后面可以加openid字段。分类表content_typeid、type_name、sort_order。为什么单独建一张分类表而不是直接写死在代码里因为分类需要后台动态维护今天叫“新能源”明天可能改叫“电动汽车”直接写死会导致每次改动都要重新发版。资讯文章表articleid、title、author、type_id、cover_image、summary、content、view_count、status、create_time、update_time。这是核心表status字段用于控制发布和下线状态type_id关联分类表。content字段类型用longtext或者mediumtext因为资讯正文可能很长varchar根本放不下。评论表commentid、article_id、user_id、content、comment_time。设计外键关系时我建议逻辑关联不要物理外键也就是在实体里维护articleId和userId但不建数据库级的外键约束。这样做的原因是后续分库分表或者数据迁移时物理外键会成为阻碍。2.2 SpringBoot三层架构怎么写后端代码严格按Controller-Service-Mapper三层切分。Controller只负责接收参数和封装返回结果不写任何业务逻辑Service负责业务处理Mapper负责SQL操作。以文章列表查询为例调用链路是这样的Controller层接收前端传过来的分页参数和筛选条件调用Service接口。RestController RequestMapping(/api/article) public class ArticleController { Resource private ArticleService articleService; GetMapping(/list) public Result getArticleList(RequestParam(defaultValue 1) Integer pageNum, RequestParam(defaultValue 10) Integer pageSize, String keyword, Integer typeId) { return Result.success(articleService.pageQuery(pageNum, pageSize, keyword, typeId)); } }Service层组装查询条件调用Mapper同时处理一些附加逻辑比如浏览量自增时先查后更避免并发写覆盖。Mapper层通过MyBatis的接口绑定直接操作数据库。这里我用了PageHelper插件做物理分页拦截器自动生成带LIMIT的SQL非常方便省去了手动拼分页参数的工作。2.3 MyBatis动态SQL和结果映射MyBatis在这个项目里最出彩的地方是动态SQL。资讯列表页的筛选条件经常变化——用户可能只按分类看可能搜标题可能同时带两个条件。用传统的JDBC拼SQL条件一多就得写一堆if判断而且还要小心SQL注入。用MyBatis的where标签加if标签问题迎刃而解。select idpageQuery resultTypecom.example.entity.Article SELECT * FROM article where if testkeyword ! null and keyword ! AND (title LIKE CONCAT(%, #{keyword}, %) OR summary LIKE CONCAT(%, #{keyword}, %)) /if if testtypeId ! null AND type_id #{typeId} /if AND status 1 /where ORDER BY create_time DESC /select注意两点一是#{keyword}预编译变量会自动转义防止SQL注入不能用${}直接拼接二是LIKE查询用CONCAT拼接通配符而不是写成%#{keyword}%后者在MyBatis里不会按预期解析。结果映射方面由于表字段名用下划线风格type_id、create_timeJava实体用驼峰风格typeId、createTime直接在application.yml里开一下驼峰映射开关就能自动转换mybatis: configuration: map-underscore-to-camel-case: true不用写一堆resultMap简洁很多。3. Vue前端与接口联调3.1 前端工程结构和路由设计前端用Vue CLI搭建的项目目录结构按模块拆分views放页面组件components放公共组件router集中管理路由api目录封装所有后端接口请求。路由设计上要注意权限控制。游客只能访问首页、资讯列表、详情页后台管理页面必须登录后才能进入。我用的是路由守卫router.beforeEach((to, from, next) { const token localStorage.getItem(token); if (to.path.startsWith(/admin) !token) { next(/login); } else { next(); } });这个逻辑简单直接后端接口也要做同样的校验不然光靠前端路由拦截等于没锁门。3.2 资讯列表和详情页的实现前端页面开发有一个非常实用的思路先把页面静态结构写出来再替换成真实数据。资讯列表页由三部分组成顶部分类导航栏、中部搜索框、下方文章卡片列表。分类导航的数据从后端/api/type/list接口获取点击分类触发路由跳转带typeId参数再调用文章列表接口重新拉数据。Axios请求封装在这类项目里很有必要。统一设置baseURL统一处理token附加统一拦截错误码const service axios.create({ baseURL: /api, timeout: 10000 }); service.interceptors.request.use(config { const token localStorage.getItem(token); if (token) { config.headers.Authorization token; } return config; });这里我把baseURL设成了/api而不是完整地址配合后端统一加/api前缀后续如果换域名或者调整端口只需改一处配置。详情页需要注意一个细节页面加载时先请求详情接口同时调用浏览量自增接口。浏览量自增我放在后端Service层处理当查询详情时在同一个事务里把view_count加一这样前端不用做额外的埋点操作。3.3 后台管理界面从零开始的增删改查后台管理界面是整个项目里工作量最重的部分因为管理功能本质上就是一堆增删改查页面但要做到好用并不简单。我实现了几个关键模块登录页输入用户名密码调登录接口拿到token存localStorage跳转到管理首页。文章管理表格展示所有文章支持按标题搜索、按分类筛选、上下架操作、编辑和删除。这里用到了Element UI的el-table组件配合分页组件体验很接近主流后台管理模板。分类管理增删改分类排序调整删除分类时要注意提醒用户该分类下还有文章需要先转移或者删除文章。编辑文章用的是富文本编辑器。我选了一个开源的轻量级编辑器将编辑器实例绑定到Vue组件的数据模型上。这里有个容易踩的坑富文本编辑器渲染出来的内容包含HTML标签详情页展示时vue的插值表达式{{ }}会转义所有标签导致内容变成一堆源码文本。解决办法是用v-html指令渲染同时后端接口返回时要注意别做HTML转义。4. 完整源码部署与复现4.1 环境准备与版本选型在动手跑项目之前先把环境准备好。我用的版本组合如下大家参考时尽量保持大版本一致减少兼容性问题组件版本说明JDK1.8稳定SpringBoot 2.x完美兼容Maven3.6依赖管理Node.js14前端构建需要MySQL5.7或8.08.0注意认证插件SpringBoot2.5.x不用追求新版稳定优先Vue CLI4.x工程化开发脚手架数据库导入我用的是Navicat执行SQL脚本也可以用命令行source。导入时务必注意字符集选择utf8mb4这个字符集能存emoji表情也兼容所有中文。4.2 配置文件里的几个关键点后端配置文件application.yml是整个项目能否跑通的关键我最关注的几个配置项server: port: 8080 spring: datasource: url: jdbc:mysql://localhost:3306/car_news?useUnicodetruecharacterEncodingutf8useSSLfalseserverTimezoneAsia/Shanghai username: root password: 123456 servlet: multipart: max-file-size: 10MB mybatis: mapper-locations: classpath:/mapper/*.xml configuration: map-underscore-to-camel-case: true数据库连接串里的serverTimezoneAsia/Shanghai必须要加否则MySQL驱动会报时区错误useSSLfalse是为了避免本地环境SSL握手警告useUnicodetruecharacterEncodingutf8保证中文不乱码。前端代理配置在vue.config.js里开发阶段把/api代理到后端地址module.exports { devServer: { proxy: { /api: { target: http://localhost:8080, changeOrigin: true } } } };这样前端所有/api开头的请求都会转发到后端既解决了跨域问题又不用每次CORS请求都额外处理。4.3 启动步骤与常见打包方式开发环境启动顺序启动MySQL导入数据库脚本。后端在IDEA中打开等Maven下载完依赖运行SpringBoot启动类。前端在项目根目录执行npm install安装依赖然后npm run serve启动开发服务器。浏览器访问http://localhost:8081看到前端页面接口自动代理到8080端口。生产环境部署我一般这样做后端执行mvn clean package打包成jar然后java -jar target/car-news-0.0.1.jar启动前端执行npm run build构建出dist目录丢到Nginx里托管。Nginx配置需要加一个反向代理让/api请求转发到后端jar的端口location /api/ { proxy_pass http://127.0.0.1:8080/; }这里注意proxy_pass后面是否带末尾斜杠带斜杠表示去掉/api/前缀再转发不带斜杠则原样转发两种行为截然不同踩过一次坑才明白。5. 常见问题与排查技巧实录5.1 跨域问题的三种表现和应对前后端分离开发中跨域问题几乎无法回避。我用过三种方案分别适用于不同阶段开发阶段用Vue CLI代理最省事不用动后端代码。流程就是上面提到的vue.config.js配置。后端加全局CORS配置适用于生产环境不由Nginx托管或者前端部署在其他域名的场景Configuration public class CorsConfig implements WebMvcConfigurer { Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping(/api/**) .allowedOriginPatterns(*) .allowedMethods(GET, POST, PUT, DELETE) .allowedHeaders(*); } }Nginx层统一处理最推荐的生产方案。利用add_header Access-Control-Allow-Origin *或者反代方式消除跨域。排查跨域问题最简单的判断方法打开浏览器控制台看到Access to XMLHttpRequest ... CORS policy相关报错基本就是跨域问题按上面三个维度定位。5.2 MySQL连接报错的坑用MySQL 8.0时最经典的报错是Public Key Retrieval is not allowed。原因是MySQL 8默认使用caching_sha2_password认证插件。解决方案有两个一是连接串里加allowPublicKeyRetrievaltrue二是创建用户时指定认证方式为mysql_native_password。我倾向于用第二种因为从规范性和安全性角度数据库的账号配置应该由DBA统筹规划不是每个应用都适合在连接串里放宽公钥检索限制。开发环境图省事可以加参数生产环境还是规规矩矩建专用账号。另外还有一个很诡异的坑MySQL 8.0以上版本时区配置如果缺失会直接拒绝连接提示The server time zone value Öйú±ê׼ʱ¼ä is unrecognized。看到一堆乱码别慌就是serverTimezone没设置或者设错了。5.3 前端白屏和接口数据对不上信息列表页白屏最常见的两种原因一是接口请求报404或500二是数据结构对不上导致渲染异常。我调试时会先看控制台的Network面板确认接口是否真的成功返回。数据对不上这类问题本质上就是前后端字段名不一致。举例来说后端Article实体里字段叫viewCount前端代码却写成views页面上浏览量就一直是空的。这种情况解决方案没有捷径前后端约定接口文档或者让后端直接返回前端要求的字段名。还有一个容易被忽略的问题后端返回的日期格式是2024-05-12T10:30:00这种带T的格式前端直接显示很难看。我一般在后端加一个全局配置统一格式化日期字段。6. 项目扩展与个人经验谈数据库表结构在设计初期就预留了扩展位所以后续加功能比较顺手。如果现在让我在这个项目基础上继续做我会优先考虑加三个模块数据统计模块统计每篇文章的阅读量、评论数按分类聚合展示做成简单的图表面板。后端用GROUP BY查询前端用开源图表库画折线图或者柱状图跟现有架构天然契合。标签系统一篇文章归属多个标签需要拆一张中间表article_tag。资讯网站的SEO优化和推荐算法都需要标签做支撑。用户评论优化目前评论是简单的单体回复。如果评论量上来需要改成父子关系结构用parent_id字段实现楼层式展示再考虑接入敏感词过滤。最后说一点个人体会。这类管理系统被很多人当成“玩具项目”觉得就是CRUD没什么技术含量。但真正做完一个完整的项目从建表到上线你会发现细节远比自己预想的多事务什么时候加、索引建在哪几个字段上、接口怎么设计才够优雅、前端组件怎么拆分才好维护每一个选择都在影响后续的开发效率。这套源码里有些地方的写法不一定是最优解但胜在结构清晰、功能完整跑通一遍再改动就心里有数了。拿它做二次开发的起点比从零开始闷头造轮子靠谱得多。

相关新闻

AnyPS5:将DualSense手柄打造成跨平台万能输入设备

AnyPS5:将DualSense手柄打造成跨平台万能输入设备

1. 项目缘起与核心定位AnyPS5 这个名字第一次出现在我视野里的时候,我正被一堆跨平台输入设备的适配问题折腾得够呛。简单来说,AnyPS5 是一个把 PlayStation 5 的 DualSense 手柄变成“万能输入设备”的软件方案——它能让这块原本只服务于游戏主机的手柄…

2026/10/15 23:46:00 阅读更多 →
Python工具链Rust化:五个提升开发效率的新库实战指南

Python工具链Rust化:五个提升开发效率的新库实战指南

这两年 Python 生态里的话题,绕不开一个词:Rust 化。从包管理到 lint 再到数据验证,一堆新库选择直接用 Rust 重写底层,把之前 Python 工具链里让人头疼的慢、复杂、配置繁琐的问题挨个收拾了一遍。我最近在几个项目里把工具链切到…

2026/10/15 23:45:00 阅读更多 →
Unity输入与屏幕设置实战笔记:从旧版Input到Input System

Unity输入与屏幕设置实战笔记:从旧版Input到Input System

我不太喜欢写那种截图铺满的入门教程,这篇更偏向我自己反复会翻的备忘录。主题就两个:一是Unity里的按键操作,二是屏幕设置。搞游戏开发或者做工具类应用的人应该都有同感,这两种需求几乎每个项目都会碰上,但每次写都还…

2026/10/15 23:45:00 阅读更多 →

最新新闻

微电网调度MATLAB工程实现:双时间尺度MILP优化与不确定性建模

微电网调度MATLAB工程实现:双时间尺度MILP优化与不确定性建模

简介:本资源是一套面向电力系统方向本科生、研究生及科研人员的智能微电网调度算法MATLAB实现方案,聚焦可再生能源接入背景下微电网的经济性调度与稳定性优化问题。压缩包共20个文件,含18个核心MATLAB函数(.m)、1个备份…

2026/10/16 0:34:22 阅读更多 →
Windows SDK中国象棋:从双缓冲到Alpha-Beta的完整课设实战

Windows SDK中国象棋:从双缓冲到Alpha-Beta的完整课设实战

简介:基于Windows SDK的象棋程序完整工程源码包,面向C/C初学者及桌面游戏开发入门者,重点演示如何使用Win32 API与GDI实现棋盘绘制、棋子拖放、走棋规则判断和人机对弈。压缩包共38个文件,主要包含C源文件(.cpp)、头文件(.h)、图标…

2026/10/16 0:34:22 阅读更多 →
NC附件上传的本地保存与OSS上传架构设计

NC附件上传的本地保存与OSS上传架构设计

1. 项目概述:为什么“NC传输附件的本地文件保存和文件上传”是企业级系统绕不开的硬需求在某高校实验室参与一个跨部门协同管理平台开发时,我第一次被业务方拉着开了个紧急会——他们刚上线的NC(用友NCCloud)系统里,所…

2026/10/16 0:34:22 阅读更多 →
离散周期信号频谱分析:DFS原理、混叠与泄露的工程实战

离散周期信号频谱分析:DFS原理、混叠与泄露的工程实战

1. 从“周期”二字说起:为什么离散周期信号的频谱值得单独拎出来讲很多人学数字信号处理,学到“离散周期信号的频谱”这一节时,第一反应是——公式好多,但好像跟前面学的离散时间傅里叶变换(DTFT)差不多&am…

2026/10/16 0:34:22 阅读更多 →
Python安装与环境配置全指南:Windows/macOS/Linux从零到跑通项目

Python安装与环境配置全指南:Windows/macOS/Linux从零到跑通项目

简介:一份面向Python零基础学习者的图文安装指南,通过步骤拆解与截图对照,围绕Python解释器与PyCharm集成开发环境的完整搭建流程展开,帮助读者从官网下载、安装选项勾选、命令行验证到创建并运行第一个Python程序,解决…

2026/10/16 0:34:22 阅读更多 →
脑电信号模拟发生系统:为脑机接口测试打造可复现的基准数据

脑电信号模拟发生系统:为脑机接口测试打造可复现的基准数据

简介:面向脑机接口测试的高精度脑电信号模拟发生系统设计文档,聚焦医疗设备制造商、科研工作者与脑机接口开发团队的测试需求。方案针对传统信号发生器系统复杂、体积庞大、精度不足等问题,提出含数模转换、同相比例放大与信号衰减电路的模拟…

2026/10/16 0:33:22 阅读更多 →

日新闻

个人 AI Agent 平台接入 TaoToken:统一 Key 与 API 通道的配置大纲

个人 AI Agent 平台接入 TaoToken:统一 Key 与 API 通道的配置大纲

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 0:00:05 阅读更多 →
信号与系统频域分析作业解题指南

信号与系统频域分析作业解题指南

1. 作业背景与核心要求解析信号与系统作为电子信息类专业的核心基础课,其作业设计往往直接关联课程的核心知识框架。2026年春季第六次作业的布置,通常对应着课程进展到频域分析的关键阶段。根据常规教学进度推测,本次作业可能涉及以下核心内容…

2026/10/16 0:00:05 阅读更多 →
Django MVT实战:从零构建图书借阅系统,彻底搞懂Model-View-Template分层

Django MVT实战:从零构建图书借阅系统,彻底搞懂Model-View-Template分层

1. 从一个"四不像"的练手项目说起如果你已经看完了Django的官方教程前几章,跟着敲完了投票应用,大概会有一种"我好像会了,又好像什么都不会"的割裂感。教程里每个知识点都是拆开的——这一章讲模型,下一章讲视…

2026/10/16 0:00:05 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/15 16:18:54 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/15 19:41:51 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/15 13:48:15 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 0:14:36 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 22:45:47 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 9:49:14 阅读更多 →