☰
SSM+Vue灯饰交易平台毕设全解析:从数据模型到部署踩坑
2026/10/4 4:41:33 网站建设 项目流程

1. 项目全貌与选题判断:为什么是“灯饰+交易”这个组合

拿到这个题目第一反应是挺踏实的,SSM + Vue这个技术组合在近几年的毕业设计里属于“经典款”,而“灯饰线上交易平台”这个业务方向又比那些烂大街的“图书管理系统”“学生选课系统”要丰富不少,做出来的系统有商品、有购物车、有订单、有支付模拟,业务链条完整,既能体现后端的数据处理能力,也能展示前端的交互设计水平。对于2026届的毕业生来说,这个选题的性价比实实在在——技术上难度适中,业务上有足够的内容支撑论文的各个章节,答辩的时候也有东西可讲。

先把这个项目到底在做什么说清楚。力高灯饰是一个灯饰品牌,线上交易平台本质就是一个B2C电商网站,面向普通消费者展示和销售灯具类商品。系统分两端:前台是用户使用的,包含注册登录、商品分类浏览、关键词搜索、商品详情、购物车管理、订单提交与状态追踪、个人中心等;后台是管理员使用的,包含商品管理、分类管理、订单处理、用户管理、数据概览等。整个系统从用户浏览商品到最终下单形成一个完整闭环,这也是毕设答辩时最能体现你工作量的一条业务线。

说说选题思路。线上交易平台这个方向在毕设里属于“上限高、下限也高”的类型——做得简单可以只做CRUD,做得复杂可以加秒杀、加优惠券、加推荐系统。但作为本科生毕业设计,核心考量应该是“在规定时间内,用可控的技术栈,完成一个能稳定运行、有完整业务逻辑的系统”。SSM + Vue正好卡在这个平衡点上:SSM框架成熟稳定,网上资料多,遇到问题能查到解决方案;Vue生态完善,组件化开发效率高,做出来的页面观感比传统JSP强了不止一个档次。建议2026届的同学如果时间不是特别充裕,选这个组合是稳妥的。

2. 技术选型拆解:SSM + Vue这个组合的底气在哪

2.1 SSM三件套的真实定位

SSM指Spring、SpringMVC、MyBatis三个框架的组合,在Spring Boot普及之前,这是Java Web开发最主流的技术栈。虽然现在企业里新项目基本都用Spring Boot了,但很多高校的教学体系还停留在SSM阶段,毕业设计用SSM依然有现实的合理性:一是教学大纲覆盖的知识点能全部用上,二是论文的“相关技术介绍”章节有现成的内容可写,三是Spring Boot实际上也基于这些底层框架,把SSM吃透了后面学Spring Boot就是顺手的事。

三个框架各管一段:Spring负责对象管理和事务控制,SpringMVC负责接收前端请求和返回响应,MyBatis负责数据库操作。用生活化的比喻,Spring是整个公司的行政部,统一管理所有“员工对象”的创建和销毁;SpringMVC是前台接待,把所有来访请求根据“门牌号”(URL)分发给对应的处理部门;MyBatis是仓库管理员,把Java对象和数据库表记录之间做双向转换。理解了这层分工,后面写代码的时候就不会混淆哪个逻辑该放哪一层。

2.2 前端为什么选Vue而不是其他

Vue在毕设项目里受欢迎不是偶然的。它的学习曲线比React平滑,模板语法接近HTML,对于只学过JavaScript基础的学生来说更容易上手。在这个项目里,Vue主要干三件事:页面路由控制(Vue Router)、组件化复用(商品卡片、分页组件、表单组件)、状态管理(Vuex或Pinia存储用户信息和购物车数据)。

值得注意的是,毕设版的Vue一般建议用Vue 2 + Element UI的组合,而不是Vue 3 + Element Plus。原因很实际:Vue 2的教程数量最多,遇到问题搜解决方案最容易;Element UI的组件风格符合后台管理系统的审美,表格、表单、弹窗、消息提示都是现成的;更重要的是很多毕业设计论文的参考文献和模板代码都是基于Vue 2写的,你写论文的时候引用和比对的成本低很多。当然,如果你对Vue 3更熟悉,或者导师要求用新版本,Vue 3 + Element Plus也完全可以,只是要做好“网上搜到的资料不一定直接适用”的心理准备。

2.3 环境搭建与版本匹配(实操)

这个环节是很多同学第一个翻车的地方,我按照实测过的组合整理一份清单:

组件推荐版本说明
JDK1.8兼容性最好,SSM框架在老版本JDK下问题最少
Maven3.6.x依赖管理工具,3.6与IDEA集成最顺畅
MySQL5.7 或 8.05.7资料多,8.0功能新,注意驱动版本要匹配
Tomcat8.5 或 9.0Servlet版本和SpringMVC版本要匹配
Node.js14.x 或 16.xVue 2配合这两个版本编译最稳定
Vue CLI4.x 或 5.x脚手架工具,建议直接用vue create命令创建项目

这里有一个容易踩的坑:MySQL 8.0的驱动类名是com.mysql.cj.jdbc.Driver,而5.7时代用的是com.mysql.jdbc.Driver,如果你的配置文件和pom.xml之间版本不一致,数据库连接阶段就会报ClassNotFoundException。我建议直接统一用MySQL 5.7 + mysql-connector-java 5.1.47这个组合,少很多麻烦。

3. 数据模型设计:交易系统的地基

3.1 核心表结构设计

电商系统的数据库设计是整个项目的核心,表结构设计得好不好,直接决定后面写业务代码是顺手还是痛苦。力高灯饰交易平台至少需要以下数据表:

用户表(t_user)——用户ID、用户名、密码(MD5加密存储)、昵称、手机号、邮箱、头像、注册时间、状态。密码加密这一点在论文里值得单独写一段关于安全性的讨论,别用明文存密码,答辩老师大概率会问。

分类表(t_category)——分类ID、分类名称、父分类ID(支持两级分类)、排序号。灯饰的分类可以设置成:吸顶灯、吊灯、台灯、壁灯、筒灯射灯、LED光源等。

商品表(t_product)——商品ID、商品名称、分类ID、商品主图、详情图片、价格、原价、库存、销量、上架状态、描述、创建时间。电商项目的商品表字段比一般管理系统多,价格建议用DECIMAL(10,2)类型,避免浮点数精度问题。

购物车表(t_cart)——购物车ID、用户ID、商品ID、商品数量、加入时间。这里有个设计决策:购物车数据存数据库还是存浏览器本地存储。我实测下来,两种方案都能完成毕设,但存数据库在论文里更好写技术深度,而且可以实现用户换设备购物车不丢失。缺点是多两张表的读写和联查。

订单表(t_order)——订单ID、订单编号、用户ID、总金额、收货人、联系电话、收货地址、订单状态、下单时间、支付时间、发货时间。订单状态可以用数字枚举:0待付款、1待发货、2待收货、3已完成、4已取消。

订单明细表(t_order_item)——明细ID、订单ID(外键)、商品ID、商品名称快照、商品价格快照、购买数量、小计。注意“快照”这两个字,订单明细必须保存下单那一刻的商品名称和价格,否则后面商品改名改价会影响历史订单数据,这是电商系统设计的一个基础常识,也是论文里能拿分的点。

轮播图表(t_banner)和管理员表(t_admin)属于辅助表,有就更好,没有也不影响核心功能。

3.2 购物车与订单表的设计细节

购物车表推荐冗余一个商品价格字段还是只存商品ID?我的做法是只存用户ID和商品ID、数量,价格实时从商品表联查。因为购物车阶段的价格是“参考价”,不是最终成交价,最终成交价在创建订单时才算定死。这样设计的好处是,商品改价后购物车里展示的是最新价格,不会出现“加入购物车199元,下单时变成259元”的困惑。

订单表和订单明细表是典型的一对多关系。生成订单时要在同一个事务里完成三步:创建主订单记录、批量创建订单明细、扣减商品库存。这三步任何一步失败都要回滚,否则会出现“订单创建成功但库存没扣”或者“明细缺失”的数据不一致问题。事务控制在Spring里用@Transactional注解就能实现,但要注意这个注解只对public方法生效,而且不能是同类内部方法调用,这个细节在实操环节很容易被忽视。

3.3 库存与支付的边界处理

作为毕设项目,接入真实的支付宝或微信支付接口不是必须的,这里有两个可行方案:一是模拟支付,用户点击“立即支付”后直接跳转到支付成功页面并改变订单状态;二是接入沙箱环境,支付宝有沙箱支付接口,调试起来也不难。如果论文篇幅需要或者你想增加亮点,沙箱支付是个不错的选择,但这会占用不少联调时间。我建议大部分同学先做模拟支付,把订单状态机的流转逻辑跑通,有余力和时间再加沙箱支付作为“系统扩展”。

4. 后端实现:SSM框架下的核心流程

4.1 Maven项目结构与配置

标准的SSM后端项目结构一般这样组织:

pom.xml src/main/java ├── com.ligao.controller # Controller层:接收请求 ├── com.ligao.service # Service层:业务逻辑 ├── com.ligao.dao # Dao/Mapper层:数据库操作 ├── com.ligao.entity # 实体类 ├── com.ligao.utils # 工具类 └── com.ligao.interceptor # 拦截器(如登录拦截) src/main/resources ├── applicationContext.xml # Spring配置 ├── springmvc.xml # SpringMVC配置 ├── mybatis-config.xml # MyBatis配置 └── jdbc.properties # 数据库连接配置 src/main/webapp └── WEB-INF/web.xml # Web部署描述文件

pom.xml里需要引入的核心依赖包括:spring-context、spring-webmvc、spring-jdbc、mybatis、mybatis-spring、mysql-connector-java、druid(连接池)、jackson(JSON序列化)、jstl和standard标签库。有一个很多同学会漏掉的依赖是jackson-databind,如果不引入,SpringMVC的@ResponseBody返回JSON时会运行报错,报错信息看起来像内部服务器错误,查半天才发现是缺少JSON转换依赖。

数据库连接池推荐用阿里巴巴的Druid,配置简单,还能开启监控页面。连接配置放在jdbc.properties里,注意不要提交到公共仓库,虽然毕设无所谓,但养成习惯总是好的。

4.2 用户登录与权限控制

登录流程的核心是:前端把用户名密码提交到后端,后端查询用户表比对密码(存储的是MD5值,所以比对前先对输入密码做MD5加密),比对成功就生成一个用户标识存到Session,同时可以返回一个用户对象给前端存到Vuex里。后续请求通过拦截器校验Session中是否有用户信息,没有就重定向到登录页。

这里要重点说拦截器的设计。在SpringMVC里通过实现HandlerInterceptor接口完成登录验证:

public class LoginInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { HttpSession session = request.getSession(); Object user = session.getAttribute("user"); String uri = request.getRequestURI(); // 放行登录、注册、首页展示等不需要登录的接口 if (uri.contains("/login") || uri.contains("/register") || uri.contains("/product")) { return true; } if (user != null) { return true; } // 未登录,返回状态码,前端根据状态码跳转登录页 response.setStatus(401); return false; } }

在springmvc.xml里注册这个拦截器,设置拦截路径为/**,放行路径为登录注册相关的controller。这个逻辑是答辩时的高频考点,建议把“哪些路径需要登录才能访问”这个列表在答辩前想清楚:浏览商品可以不需要登录,但加入购物车、提交订单、查看个人中心必须登录。

4.3 商品列表与条件检索

商品列表页是用户看到的第一屏,后端接口的设计直接影响前端渲染效率。建议设计一个统一的商品查询接口,接收以下可选参数:页码pageNum、每页条数pageSize、分类ID categoryId、商品名称keyword、排序字段及方式sort/order。

对应的Controller层接收参数后,在Service层组装一个动态条件,传到MyBatis的Mapper里通过 标签实现动态SQL:

<select id="selectProductList" parameterType="map" resultType="com.ligao.entity.Product"> SELECT * FROM t_product <where> 1 = 1 <if test="categoryId != null"> AND category_id = #{categoryId} </if> <if test="keyword != null and keyword != ''"> AND product_name LIKE CONCAT('%', #{keyword}, '%') </if> <if test="status != null"> AND status = #{status} </if> </where> <if test="sort != null and sort != ''"> ORDER BY ${sort} ${order} </if> </select>

这里要特别提醒:ORDER BY后的字段用${}拼接而不是#{},因为MyBatis的#{}会为参数自动加引号,用在ORDER BY的位置会报SQL语法错误。但${}存在SQL注入风险,如果排序字段是从前端传来的,一定要做白名单校验,只允许传入白名单内的字段名,这是安全考点,论文里如果能写一句“对排序字段做了白名单校验”是很加分的。

分页建议用PageHelper插件,配置一个拦截器就能自动在SQL后面拼接limit,使用方式也很简单:先调用PageHelper.startPage(pageNum, pageSize),紧接着的查询就会被分页,返回结果通过PageInfo包装后还能拿到总记录数。另外要记得这句PageHelper.startPage必须写在紧接着要分页的查询语句之前,中间不能插入其他SQL操作,否则分页会作用在错误的查询上。

4.4 下单流程的核心代码逻辑

下单是整个系统业务逻辑最集中的地方,流程是:前端提交订单数据(商品ID列表、数量、收货信息)→ 后端校验用户登录状态 → 计算总金额 → 生成订单主记录 → 批量生成订单明细 → 扣减库存 → 清空购物车对应商品 → 返回订单号。

核心的Service方法是这样:

@Transactional(rollbackFor = Exception.class) public Order createOrder(Integer userId, List<CartItem> cartItems, Address address) { // 1. 计算总金额 BigDecimal total = new BigDecimal(0); List<OrderItem> orderItems = new ArrayList<>(); for (CartItem item : cartItems) { Product product = productMapper.selectById(item.getProductId()); if (product == null || product.getStock() < item.getQuantity()) { throw new RuntimeException("商品库存不足:" + product.getProductName()); } OrderItem orderItem = new OrderItem(); orderItem.setProductId(product.getId()); orderItem.setProductName(product.getProductName()); // 快照 orderItem.setPrice(product.getPrice()); // 快照 orderItem.setQuantity(item.getQuantity()); orderItems.add(orderItem); total = total.add(product.getPrice().multiply(new BigDecimal(item.getQuantity()))); // 扣减库存 productMapper.decreaseStock(product.getId(), item.getQuantity()); } // 2. 创建订单主记录 Order order = new Order(); order.setOrderNo(generateOrderNo()); order.setUserId(userId); order.setTotalAmount(total); order.setStatus(0); // 待付款 order.setReceiverName(address.getReceiverName()); order.setReceiverPhone(address.getReceiverPhone()); order.setReceiverAddress(address.getReceiverAddress()); orderMapper.insert(order); // 3. 创建订单明细 for (OrderItem item : orderItems) { item.setOrderId(order.getId()); orderItemMapper.insert(item); } // 4. 清空购物车 cartMapper.deleteByUserIdAndProductIds(userId, productIds); return order; }

这段逻辑里有两个点值得展开说:一是事务,@Transactional保证整个方法要么全部成功要么全部回滚;二是库存检查,先检查再扣减存在并发场景下有可能超卖,不过毕设项目一般不会遇到高并发,在论文里提一句“通过数据库乐观锁或者SELECT ... FOR UPDATE可以进一步保证并发下库存准确”就足够展示思考深度了,不必真的去实现分布式锁。

订单编号生成不要用自增ID,要生成一个业务上唯一的订单号,常见做法是时间戳+随机数,或者用年月日时分秒+用户ID后四位。我之前用过SimpleDateFormat配合UUID片段来拼接,实测生成速度很快且重复率几乎为零。

5. 前端实现:Vue端到端的页面与交互

5.1 项目初始化与路由规划

前端用Vue CLI创建项目后,先规划路由。路由分两级:商城前台和后台管理。

商城前台路由:

/ # 首页,展示轮播图和推荐商品 /product/list # 商品列表(支持分类筛选和关键词搜索) /product/detail/:id # 商品详情 /cart # 购物车 /order/confirm # 确认订单页 /order/list # 我的订单 /order/detail/:id # 订单详情 /login # 登录 /register # 注册 /personal # 个人中心

后台管理路由:

/admin/dashboard # 数据概览 /admin/product # 商品管理 /admin/category # 分类管理 /admin/order # 订单管理 /admin/user # 用户管理

路由守卫在Vue 2里有两种方式:全局前置守卫router.beforeEach和路由元信息。推荐在路由配置的meta字段里标注requiresAuth: true,然后在全局守卫里判断用户登录状态:

router.beforeEach((to, from, next) => { const user = store.state.user if (to.matched.some(record => record.meta.requiresAuth)) { if (!user) { next({ path: '/login', query: { redirect: to.fullPath } }) return } } next() })

这个写法比在每个页面里手动判断要优雅得多,代码也少。注意登录后要处理redirect参数,让用户登录后能回到之前想去的页面,这个小细节在答辩演示的时候很加分。

5.2 商品展示与购物车状态管理

商品列表页用Element UI的Card组件和Row/Col栅格布局做成网格样式,每个商品卡片展示主图、名称、价格、销量和“加入购物车”按钮。图片加载失败的情况一定要处理,在img标签的error事件里替换成默认占位图,否则页面会出现破图图标,演示的时候很尴尬。

购物车的数据流要讲清楚:用户把商品加入购物车后,前端把购物车数据存到Vuex,同时调用后端接口写入购物车表。页面加载时通过接口拉取购物车列表。Vuex里的state、getter、mutation、action四个概念在这个模块正好能完整的用上——state存购物车数组,getter计算总价,mutation修改商品数量,action调用后端接口同步数据。答辩时候如果老师问“Vuex在你项目里怎么用的”,你就可以把这个购物车的完整数据流讲出来,这比背概念生动得多。

还要处理的一个小问题是加入购物车时同一商品的重复添加。前端的逻辑是:如果购物车里已经有了这个商品,就数量加1而不是新增一行;如果没有才新增。这个判断放在mutation里完成,代码简洁:

addToCart(state, product) { const existing = state.cartItems.find(item => item.productId === product.id) if (existing) { existing.quantity++ } else { state.cartItems.push({ productId: product.id, productName: product.name, price: product.price, image: product.image, quantity: 1 }) } }

5.3 与管理端联调的关键点

前端接口请求统一封装一个request.js模块,基于axios实例,设置baseURL指向后端项目的访问路径,配置请求拦截器自动带上Session或token,响应拦截器统一处理错误状态码。一个常见的坑是前后端分离部署时的跨域问题。毕设项目一般有两种部署方式:一种是把Vue打包后的dist目录放到SSM项目的webapp下面统一部署,这样同源,不需要处理跨域;另一种是前后端分开部署,前端开发服务器用proxy代理解决跨域。

我强烈建议第一种方式。因为SSM项目本身就跑在Tomcat上,把Vue打包好的静态资源放进Tomcat同一个webapp里,SpringMVC配置一个视图解析器或者直接把dist目录复制到webapp目录下,就能用同一个端口访问前后端,省去跨域配置的麻烦。具体操作是把vue项目的dist内容复制到web项目的webapp根目录(注意如果webapp下有WEB-INF,保留这个目录),Tomcat启动后访问http://localhost:8080/就能看到首页。这也是热搜词“vue打包放进springboot中”类似问题的通用解法,在SSM里原理一样,都是把前端构建产物交给Java后端容器托管。

6. 论文撰写:结构框架与答辩准备

6.1 论文章节怎么搭

毕设论文和项目代码是两套东西,代码是工程能力的证明,论文是研究思考和表达能力的证明。一篇合格的SSM+Vue电商平台论文,推荐按下面这个结构写:

第一章绪论:研究背景与意义、国内外研究现状、研究内容与目标。这一章的“项目背景”部分,就可以叙述灯饰行业的线上销售趋势、传统门店的局限性、线上平台对灯饰销售的促进作用,这部分内容不需要技术含量,但能体现你对行业背景的调研能力。

第二章相关技术介绍:Java语言、Spring、SpringMVC、MyBatis、Vue、MySQL、Maven等。这章最容易复制粘贴,但要警惕查重,建议用通俗的、自己的话重写一遍每个技术的核心特性和在本项目中的用途,不要抄培训机构的介绍段落。

第三章需求分析:功能性需求(前台用户模块、后台管理员模块)、非功能需求(性能、安全性、易用性)、可行性分析(技术可行性、经济可行性、操作可行性)。需求分析这部分建议画用例图,画出用户和管理员各自的用例,这是软件工程课程的内容,用在这里非常合适。

第四章系统设计:总体架构设计、功能模块设计、数据库设计(重点写ER图和表结构说明)。数据库设计要至少画出核心ER图,对每张表的字段做详细的注释说明,这部分内容是论文的技术含量所在,要仔细写。

第五章系统实现:按模块逐个描述实现过程,配合关键代码片段和界面截图。截图很关键,从昨晚跑通的系统里多截几张清晰的图,首页、商品列表、详情、购物车、订单、后台管理界面都要有,保证界面干净整齐再截图,别把后台调试的乱数据留在截图里。

第六章系统测试:测试环境、功能测试用例和结果、性能测试。功能测试表格化,列出测试用例编号、测试步骤、预期结果、实际结果。常见的一个错误是测试用例写得像用户手册,正确的写法是一行一个具体的操作和对应的预期。

第七章总结与展望:总结项目完成的工作和不足,展望系统后续可以加什么功能。总结合理收个尾就行,不用长篇大论,但“展望”部分建议认真写两个你有把握的点——比如接入真实支付、增加商品评价功能、引入Redis缓存热门商品——答辩老师如果追问“还能怎么优化”,你就能从容接上。

6.2 答辩时容易被追问的高频问题

答辩的套路我摸过好几年,围绕SSM+Vue电商平台,老师最爱问的问题集中在下面几类:

框架理解类:Spring的AOP和IOC在项目哪里用到了?MyBatis和Hibernate有什么区别?为什么选择SSM而不是Spring Boot或者MyBatis-Plus?

解决方案类:如果用户下单时库存只剩1件,但两个用户同时下单怎么办?我的回答思路是承认毕设阶段没有做并发控制,然后补充说生产环境可以加乐观锁版本号字段或者Redis预减库存,你以一开始提到订单代码里那段库存扣减逻辑为引子,说“我们通过事务保证了单个请求内的数据一致性,并发场景可以在库存扣减SQL中使用库存数大于0的条件作为兜底”,这个回答既能自圆其说又能展示思考。

权限控制类:前端路由守卫和后端拦截器有什么区别?为什么需要双端校验?前端防的是用户不经意的误操作,后端防的是恶意请求,两个都做,安全才有保障,同时这也体现了开发规范。

数据库设计类:订单明细为什么要存商品名称和价格快照?这个问题问出来基本是送分题,把“历史数据一致性”的逻辑讲清楚就够了。

前端交互类:Vue的生命周期在项目里哪些地方用到了?created里拉取数据列表、mounted里初始化第三方组件、beforeDestroy里清理定时器,每个都配上实物例子就行。

7. 常见问题与排查经验:实测踩坑记录

7.1 后端典型疑难杂症

先说一个几乎每个人都会遇到的事:SpringMVC接收前端JSON数据时,Controller方法形参不加@RequestBody注解,前端传的JSON体解析不出来,所有字段都是null。因为标准的POST请求有两种传参格式——form表单格式和JSON体格式,SpringMVC默认把请求按表单格式解析,只有加了@RequestBody才告诉它去读取请求体并按JSON解析。这个问题定位起来很快,因为你只要看控制器方法参数上有没有那行注解就行了。

第二个常见问题是IDEA里项目跑起来报ClassNotFoundException。排查思路按顺序走:检查pom.xml里有没有引入对应依赖;检查依赖是否成功下载到本地仓库,可在右侧Maven面板点刷新;检查jar包是否部署到Tomcat的WEB-INF/lib目录。这一条网关我讲过很多次,IDEA的Artifacts配置如果不包含“lib/”目录,所有依赖都不会打包到运行环境里,本地编译通过但启动报错,十有八九是这个原因。

第三个是HTTP 404,Controller里明明写了@Controller和@RequestMapping,启动也不报错,但一访问就404。先看Tomcat控制台启动日志里有没有打印出RequestMapping映射的路径列表,如果打印了说明SpringMVC配置正常,问题出在访问路径上;如果根本没打印,检查springmvc.xml里component-scan扫描的包路径是不是Controller所在的包路径,拼写错误或者层级不对都会导致扫描不到。

7.2 前端常见疑难杂症

Vue项目npm install的时候,会遇到的最恶心的错误是node-sass安装失败。原因绝大多数是Node版本和node-sass版本不兼容。有一个大致对照关系:Node 14对应node-sass 4.14,Node 16对应node-sass 6.0或7.0。如果你用的Node版本太高,老项目装node-sass必挂。两个解决办法:一是改用dart-sass(即sass包),它和node-sass兼容性更好;二是锁Node版本,用nvm管理切换。项目是毕设用途,我建议直接用sass包替换node-sass,一步到位,官网还说以后的趋势就是dart-sass。

第二个高频问题是接口请求跨域或请求路径404。前端请求路径不区分大小写?实际上区分。如果你在接口里写的是/api/product/list,前端发的是/api/Product/list,那一定404。建议前后端约定接口路径全小写,联调前先对着接口文档核对一遍所有路径。

第三个:页面刷新后登录状态丢失。原因通常是Session存储期限设置,或者前端只把用户信息存到了Vuex没有持久化到localStorage。根因是最常见的组合也不是Vuex有没有localStorage,而是你在路由守卫里判断的是Vuex里的状态,刷新后Vuex数据重置为空,自然就跳登录页了。解决办法是用localStorage或sessionStorage持久化用户信息,store初始化时先从本地读取。我在项目里用的方式是把用户信息的JSON字符串存到sessionStorage,每次刷新后store初始化时重新解析。

7.3 部署与联调问题

前端打包后部署到Tomcat里,如果刷新某个页面出现404,这是因为Vue Router默认使用history模式,刷新时浏览器直接请求了这个路径,但Tomcat没有对应的映射,于是返回404。解决方法是改用hash模式(URL带#号),或在web.xml里配置Tomcat的rewrite规则。毕设项目直接用hash模式最简单,把Vue Router的mode改成hash就行,刷新不会出问题。URL里带#号不影响功能和演示,大多数评委老师不会在意这个细节。

另一个部署期问题是前端请求的后端接口地址写死成了localhost。如果你把前端打包交给别人布置,或者换了一台电脑运行,接口地址不一致就全盘404。建议把所有接口的前缀统一提取到一个常量配置文件(比如src/config/env.js),部署时只改这一个文件的内容,代码其他地方全部引用常量。“vue项目源码怎么发给别人”这个问题从这个角度来理解:不仅要发源码,还要附带环境说明和配置修改指引,否则接收方跑不起来就要反复来回同步。

7.4 避坑速查表

我把上面所有问题整理成一张速查表,方便你开发时对照排查:

现象常见原因快速解决办法
前端传JSON后端全nullController缺@RequestBody在参数前添加@RequestBody注解
项目启动ClassNotFoundExceptionTomcat部署包不含lib目录IDEA Artifacts中添加lib/目录
访问Controller返回404component-scan扫描路径不对核对springmvc.xml扫描包路径
npm install报node-gyp错误Node版本与node-sass不兼容用sass包替代node-sass
刷新页面404Vue Router history模式改为hash模式
MySQL连接超时数据库连接配置未加时区在URL追加useTimezone=true
列表接口慢SQL没走索引为category_id、product_name加索引
请求进入拦截器直接401拦截器未放行对应路径在放行列表中明确添加白名单路径

其中最容易被忽略的是MySQL连接URL加时区参数。如果MySQL 8.0的JDBC URL不写serverTimezone参数,启动时会直接报“The server time zone value is unrecognized”错误,解决方案是在JDBC URL后追加?useSSL=false&serverTimezone=Asia/Shanghai,顺手把useSSL也关掉,因为是本地开发环境,SSL反而会拖慢连接速度。

8. 个人经验与扩展建议

这个项目我从搭建骨架到完整跑通,累计花了三周左右的业余时间。回头复盘,关键的经验可以浓缩成三条:第一,先把数据库表设计好再动手写代码,表结构前松后紧的话,改表等于改半套系统,得不偿失;第二,前后端联调前先约定接口返回格式,统一封装成{code, msg, data}的结构,任何接口都按这个格式返回,前端解析逻辑写一遍就能复用;第三,每个功能模块写好一个就测试一个,不要拖到最后一次性联调,否则错误堆在一起定位成本极高。

写代码的过程中我最有感触的是一个细节:分页组件。前端商品列表、订单列表、后台管理表格全都要用分页,所以我干脆封装了一个通用的Pagination组件,接收total和currentPage参数,事件回传页码变化,所有列表页直接复用。这个组件在论文的“系统实现”章节里作为复用性设计案例来写,效果很好,答辩的时候也可以主动提这个设计亮点。

关于后续扩展方向,我实测想一想就有三个能落地的点:一是给商品加评价功能,用户下单并收货后才能评价,评论数据再倒灌到商品详情页展示,这个业务闭环很自然;二是引入Redis做热点商品的缓存并演示缓存穿透和击穿的解决方案,论文亮点直接拉满;三是把后台的数据概览页用ECharts做成柱状图和折线图,展示近一周的订单量和销售额变化趋势,实现成本不高,但对系统档次的提升立竿见影。

如果你时间充裕,建议在完成基础功能后挑其中一个方向做深做实。毕设的及格线是把系统跑通、论文写完,但高分往往就藏在这些主动做的扩展点里。

当初我给这个项目定的完成标准是:用户能在三分钟内完成从注册到下单的全流程操作,管理员能在后台十分钟内完成商品上下架和一单发货处理。现在这个目标已经稳定实现了,整个系统跑起来流畅顺手。各位2026届的同学,如果你们也在做类似的SSM+Vue电商项目,按这篇帖子的思路把数据模型捋清楚,把下单事务和权限拦截写扎实,再给前端页面配上趁手的Element UI组件,这样的一套组合拳下来,拿个不错的毕设成绩是很有把握的。祝顺利。

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

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

立即咨询