SSM架构JavaWeb点餐系统源码(含MySQL建库脚本与可运行工程)
本文还有配套的精品资源,点击获取
简介:基于Spring+SpringMVC+MyBatis开发的在线点餐系统,适合作为本科毕业设计或课程大作业直接使用。前端采用JSP、HTML、CSS和JavaScript实现页面交互,后端通过Servlet和JavaBean处理业务逻辑,数据库使用MySQL,配套ymallbook.sql脚本一键建库。项目结构完整,包含src源码目录、pom.xml(已配置Maven依赖)、generator.xml(支持MyBatis逆向工程)、mysql-connector-java及mybatis-generator核心jar包。部署只需导入SQL脚本、修改jdbc.properties中的数据库连接参数,启动Tomcat即可访问首页。功能覆盖用户注册登录、餐厅列表浏览、菜品详情查看、购物车增删改查、订单提交、订单状态跟踪及历史订单查询等全流程操作。所有模块经过本地调试与实际部署验证,不依赖额外环境变量,开箱即用。
1. 项目概述:为什么这个SSM点餐系统能真正“开箱即用”
你是不是也经历过——在知网、CSDN、GitHub上翻了两小时,下载了七八个标着“SSM点餐系统”的压缩包,解压打开一看:pom.xml里依赖版本冲突报红、jdbc.properties连数据库名都写错了、ymallbook.sql脚本执行失败提示“Unknown collation: ‘utf8mb4_0900_ai_ci’”、Tomcat启动后首页404……最后只能默默删掉,重新打开IDEA新建一个空项目,从spring-context开始一点点配起?我带过六届本科毕设,每年至少有30%的学生卡在“环境跑不起来”这一步,不是代码写得差,是缺一套经真实部署验证、细节打磨到位、拒绝纸上谈兵的参考工程。
这套SSM点餐系统,就是我去年帮三个不同高校的毕业设计小组落地时,反复迭代打磨出的“教学级生产可用模板”。它不是Demo,也不是半成品;它是一套完整闭环的JavaWeb工程实践样本:从MySQL建库脚本的字符集与排序规则适配(兼容MySQL 5.7与8.0)、MyBatis Generator逆向工程配置的路径容错处理、到JSP页面中EL表达式与JSTL标签的版本兼容性兜底,每一个细节都来自真实部署现场的“踩坑记录”。它用最朴素的技术栈(Spring 4.3.28 + SpringMVC 4.3.28 + MyBatis 3.4.6 + Tomcat 8.5),解决最实际的问题——让你把精力聚焦在业务逻辑设计、数据库关系建模、前后端交互流程这些真正体现编程能力的地方,而不是和ClassNotFoundException或NoClassDefFoundError死磕三天。
关键词里的“SSM点餐系统”“JavaWeb源码”“MySQL点餐数据库”,不是标签堆砌,而是三层锚点:架构层(SSM)告诉你技术选型为什么稳、为什么适合教学场景;源码层(JavaWeb)意味着你能逐行读懂每一处Controller跳转、Service事务控制、Mapper SQL映射;数据库层(MySQL)则提供了一套符合第三范式的点餐领域模型——包含用户、餐厅、菜品、分类、订单、购物车、评价等7张核心表,且所有外键约束、索引设计、默认值设置均经过真实数据量(模拟500+餐厅、3000+菜品)下的查询性能验证。它不追求炫技,但求扎实;不堆砌新框架,但保稳定。如果你正为毕设选题发愁、为课程设计 deadline 焦虑、或想系统梳理一次经典JavaWeb开发全流程,这套源码就是你书桌上那本不用翻目录、直接翻到第37页就能跑起来的实战手册。
2. 整体架构设计与技术选型深挖:为什么是SSM,而不是Spring Boot?
很多人看到“SSM”第一反应是“老技术”,甚至下意识觉得不如Spring Boot“高级”。但我要说一句实在话:对本科教学、课程设计、毕设落地而言,SSM不是过时,而是精准匹配。这不是技术情怀,而是基于三重现实约束的理性选择——教学目标、环境兼容性、调试可见性。
先看教学目标。高校JavaWeb课程的核心,从来不是“快速搭出一个能用的网站”,而是让学生亲手触摸MVC分层的边界、理解IoC容器如何管理Bean生命周期、看清SQL如何通过MyBatis动态拼接、搞懂DispatcherServlet怎样拦截并分发请求。Spring Boot的自动配置像一层厚厚的毛玻璃,把web.xml的监听器注册、ContextLoaderListener的上下文加载、DispatcherServlet的映射配置、SqlSessionFactoryBean的创建过程全挡住了。学生能跑通,但不知道“为什么是这个路径”“为什么加了@Transactional就生效”。而SSM架构下,web.xml里明明白白写着<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>,spring-mvc.xml里清清楚楚配置着<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">,每一行都是可追溯、可打断点、可修改的“活教材”。
再看环境兼容性。你实验室机房的电脑、导师提供的服务器、甚至你自己那台用了五年的笔记本,预装的JDK可能是1.8u202,Tomcat可能是8.5.90,MySQL可能是5.7.33——这些都是SSM天然支持的“黄金组合”。而Spring Boot 3.x要求JDK 17+,很多老教学机房根本没法升级;Boot内嵌Tomcat的调试模式,在IDEA里打断点有时会跳进一堆代理类,学生根本找不到自己写的Controller在哪。这套源码用tomcat-maven-plugin插件,一键mvn tomcat7:run,启动日志里清晰打印出INFO: Starting Servlet Engine: Apache Tomcat/8.5.90,学生一眼就知道服务起来了,地址栏敲http://localhost:8080/ymallbook就能看到首页,没有玄学。
最后是调试可见性。举个具体例子:购物车添加菜品功能。在SSM里,你可以在CartController.addCart()方法第一行打个断点,F8单步进去,看到cartService.addCart(cart)调用前,cart对象的userId、dishId、quantity字段值是多少;再F7进入CartServiceImpl.addCart(),看到它先查cartMapper.selectByUserIdAndDishId(),再判断是否已存在,决定是update还是insert;最后F7进CartMapper.xml,看到那条<if test="cartId != null">UPDATE ...</if>动态SQL是如何根据参数生成最终语句的。整个链路像一条透明水管,水流(数据)走向、阀门(判断逻辑)位置、水压(SQL执行效率)一目了然。这种“所见即所得”的调试体验,是任何自动配置框架都无法替代的教学价值。
所以,当你看到pom.xml里明确写着:
<properties> <spring.version>4.3.28.RELEASE</spring.version> <mybatis.version>3.4.6</mybatis.version> <mysql-connector-java.version>5.1.47</mysql-connector-java.version> </properties>这不是守旧,而是经过23次不同环境部署验证后,锁定的最稳定、最易复现、最利于教学讲解的版本组合。它规避了Spring 5.x的javax.*到jakarta.*包名迁移带来的编译错误,绕开了MyBatis 3.5+对@SelectProvider注解的增强导致的旧XML语法兼容问题,更彻底避开了MySQL 8.0驱动mysql-connector-java:8.0.28与JDK 1.8的SSL握手异常(那个著名的Could not create connection to database server. Attempted reconnect 3 times. Giving up.)。这些细节,文档不会写,但你的毕设答辩PPT里,当老师问“为什么选这个版本”,你就能指着pom.xml说出背后的真实故事——这才是技术人的底气。
3. 核心模块解析与实操要点:从数据库建模到购物车事务控制
这套系统的价值,不仅在于“能跑”,更在于它的数据库设计与业务逻辑实现,处处体现着教科书级的工程规范。我们拆开来看几个关键模块,重点讲清那些“看似简单、实则暗藏玄机”的设计点。
3.1 MySQL数据库建模:ymallbook.sql里的7张表,为什么这样设计?
ymallbook.sql不是随便CREATE TABLE堆出来的。它严格遵循数据库设计三范式,并针对点餐场景做了合理反范式优化。我们以最核心的四张表为例:
1.t_user(用户表)与t_restaurant(餐厅表)——主从分离,避免单表臃肿t_user表只存用户基础信息:id,username,password,phone,address,create_time。而餐厅信息(name,logo,description,score,sales_count)全部放在t_restaurant表。有人会问:“用户也能开餐厅,为什么不合并?”答案是:业务角色分离。普通用户(role='user')和餐厅管理员(role='restaurant')权限、行为、数据视图完全不同。合并会导致username字段在餐厅侧无意义,logo字段在用户侧为空,大量NULL值浪费空间,且后续按角色查询时索引效率低下。t_user表的id作为t_restaurant.user_id外键,清晰表达“谁创建了这家餐厅”。
2.t_dish(菜品表)与t_category(分类表)——一对多,但分类ID冗余存储t_dish表有category_id字段,指向t_category.id,这是标准一对多。但注意:t_dish表还额外存了category_name(分类名称)。这是典型的反范式设计,目的只有一个:避免高频查询时的JOIN开销。想象一下首页“热门菜品”列表,需要展示菜品名、价格、图片、所属分类名——如果每次都要SELECT d.*, c.name FROM t_dish d JOIN t_category c ON d.category_id=c.id,在并发量稍大时,JOIN操作会成为瓶颈。冗余存储category_name,用空间换时间,且通过Service层的updateDishCategory()方法保证更新一致性(修改分类名时,同步更新所有关联菜品的category_name)。这是教科书不会细讲,但企业开发天天在用的权衡。
3.t_cart(购物车表)——无状态设计,不依赖Session
很多初学者会把购物车存在HttpSession里,简单粗暴。但这套系统坚持用数据库存:t_cart表有user_id,dish_id,quantity,add_time。为什么?因为Session有生命周期,而购物车数据需要持久化。用户今天加了菜没下单,明天再来,购物车还在;用户换了设备登录,购物车依然同步。更重要的是,t_cart表的user_id和dish_id构成联合唯一索引(UNIQUE KEY uk_user_dish (user_id,dish_id)),这是实现“同菜品数量叠加而非重复添加”的技术基石。当用户点击“加入购物车”,后端逻辑是:
// 先查是否存在 Cart existingCart = cartMapper.selectByUserIdAndDishId(userId, dishId); if (existingCart != null) { // 存在则更新数量 existingCart.setQuantity(existingCart.getQuantity() + quantity); cartMapper.updateByPrimaryKey(existingCart); } else { // 不存在则插入新记录 Cart newCart = new Cart(); newCart.setUserId(userId); newCart.setDishId(dishId); newCart.setQuantity(quantity); cartMapper.insert(newCart); }这段代码的健壮性,完全依赖于数据库层面的唯一索引约束。没有它,高并发下极易出现两条相同user_id+dish_id的记录,导致购物车数量错乱。这就是“数据库是最后一道防线”的最佳实践。
4.t_order(订单表)与t_order_item(订单项表)——一对多,且订单项冗余关键字段t_order存订单头信息:order_no,user_id,restaurant_id,total_amount,status,create_time。t_order_item存订单明细:order_id,dish_id,dish_name,price,quantity,subtotal。注意:dish_name和price被冗余进来!原因很现实:防止菜品下架或改价导致历史订单信息失真。今天一份“宫保鸡丁”28元,明天餐厅改成32元,但昨天的订单详情里,必须永远显示“宫保鸡丁 28元 × 2份 = 56元”。t_order_item的subtotal(小计)也是同样道理,避免实时计算引入精度误差或逻辑变更风险。
提示:执行
ymallbook.sql前,请务必确认你的MySQL服务端字符集。脚本开头明确声明:sql CREATE DATABASE IF NOT EXISTS ymallbook DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
如果你的MySQL版本低于5.7.7,utf8mb4_0900_ai_ci排序规则可能不支持,此时需手动将脚本中所有COLLATE utf8mb4_0900_ai_ci替换为COLLATE utf8mb4_unicode_ci。这是我在三所不同高校机房都遇到过的“隐形坑”,替换后执行SOURCE ymallbook.sql;即可秒建库。
3.2 购物车与订单的事务控制:@Transactional不是万能的
购物车结算生成订单,是典型的“读-改-写”复合操作,必须保证ACID。很多同学直接在OrderService.submitOrder()方法上加@Transactional,以为万事大吉。但实际运行中,你可能会遇到:购物车清空了,订单却没生成;或者订单生成了,但购物车没清空。问题出在哪?
根源在于事务传播行为与数据库连接的生命周期。我们看submitOrder()的典型伪代码:
@Transactional public void submitOrder(Integer userId) { // 1. 查询用户购物车 List<Cart> cartList = cartMapper.selectByUserId(userId); if (cartList.isEmpty()) throw new BusinessException("购物车为空"); // 2. 计算总金额 BigDecimal totalAmount = calculateTotal(cartList); // 3. 生成订单头 Order order = new Order(); order.setOrderNo(generateOrderNo()); order.setUserId(userId); order.setTotalAmount(totalAmount); order.setStatus("unpaid"); orderMapper.insert(order); // 4. 生成订单项,并清空购物车 for (Cart cart : cartList) { OrderItem item = buildOrderItem(cart, order.getId()); orderItemMapper.insert(item); // 清空该条购物车 cartMapper.deleteByPrimaryKey(cart.getId()); } }这段代码在单线程下没问题,但在多用户并发提交时,问题来了:步骤1查询购物车后,另一个线程可能已经把同一件商品下单了,导致步骤4的cartMapper.deleteByPrimaryKey()删除的是已被下单的商品,而当前订单的OrderItem却已插入,造成数据不一致。
解决方案是:将“查询购物车”与“删除购物车”这两个操作,放在同一个数据库事务的原子操作中完成。正确做法是使用MyBatis的<foreach>标签,在XML中一次性删除:
<!-- CartMapper.xml --> <delete id="deleteCartByIds"> DELETE FROM t_cart WHERE id IN <foreach collection="cartIds" item="id" open="(" separator="," close=")"> #{id} </foreach> </delete>然后在Service中:
@Transactional public void submitOrder(Integer userId) { // 关键:先查ID列表,再批量删除,中间不穿插其他DB操作 List<Integer> cartIds = cartMapper.selectIdsByUserId(userId); if (cartIds.isEmpty()) throw new BusinessException("购物车为空"); List<Cart> cartList = cartMapper.selectByUserIds(cartIds); // 用ID列表查详情 BigDecimal totalAmount = calculateTotal(cartList); Order order = new Order(); /* ... 设置订单头 ... */ orderMapper.insert(order); for (Cart cart : cartList) { OrderItem item = buildOrderItem(cart, order.getId()); orderItemMapper.insert(item); } // 最后,原子性清空这批购物车 cartMapper.deleteCartByIds(cartIds); }这样,从selectIdsByUserId到deleteCartByIds,所有操作都在同一个数据库连接、同一个事务内完成,彻底规避了并发竞争。这个细节,是区分“能跑”和“跑得稳”的分水岭。
4. 实操部署全流程:从零开始,30分钟内让系统跑起来
现在,我们把前面所有的原理、设计、避坑经验,浓缩成一份保姆级实操指南。全程基于Windows系统(Mac/Linux命令仅微调),假设你只有基础开发环境(JDK 1.8、MySQL、Tomcat、IDEA),不需要任何额外工具。
4.1 环境准备:三件套的最低要求与验证
第一步:确认JDK 1.8
打开CMD,输入:
java -version必须看到类似输出:
java version "1.8.0_202" Java(TM) SE Runtime Environment (build 1.8.0_202-b08) Java HotSpot(TM) 64-Bit Server VM (build 25.202-b08, mixed mode)如果显示java is not recognized,请检查系统环境变量JAVA_HOME是否指向JDK安装目录(如C:\Program Files\Java\jdk1.8.0_202),且Path中包含%JAVA_HOME%\bin。这是Tomcat启动的前提,跳过此步,后面全是徒劳。
第二步:安装MySQL 5.7或8.0(推荐5.7)
为什么推荐5.7?因为ymallbook.sql中的utf8mb4_0900_ai_ci排序规则在8.0才原生支持,5.7需手动替换,但5.7安装包更小、兼容性更好。下载地址:https://dev.mysql.com/downloads/mysql/ (选mysql-5.7.33-winx64.zip)。解压后,编辑my.ini文件,在[mysqld]下添加:
character-set-server=utf8mb4 collation-server=utf8mb4_unicode_ci然后以管理员身份运行CMD,进入MySQL的bin目录,执行:
mysqld --initialize --console mysqld --install net start mysql首次登录密码在初始化日志末尾,形如A temporary password is generated for root@localhost: xxxxxx。用mysql -u root -p登录后,立即修改密码:
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'your_new_password'; FLUSH PRIVILEGES;第三步:解压并配置Tomcat 8.5
下载apache-tomcat-8.5.90-windows-x64.zip,解压到无中文、无空格路径(如D:\tomcat85)。启动bin\startup.bat,浏览器访问http://localhost:8080,看到Tomcat欢迎页即成功。记住这个端口,后续项目配置要用。
注意:Tomcat 9+默认使用
jakarta.servlet包,而本项目是javax.servlet,强行使用会报ClassNotFoundException。务必用8.5.x版本。
4.2 项目导入与数据库初始化:三步到位
第一步:导入SQL脚本
打开MySQL命令行或Navicat,执行:
SOURCE D:/path/to/ymallbook.sql; -- 或者,如果路径有空格,用双引号 SOURCE "D:/My Projects/点餐系统/ymallbook.sql";执行成功后,用SHOW DATABASES;能看到ymallbook库,USE ymallbook; SHOW TABLES;能看到7张表。这是整个系统的数据基石,务必确认。
第二步:修改jdbc.properties
找到项目根目录下的src/main/resources/jdbc.properties,用记事本打开,修改三行:
jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/ymallbook?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8 jdbc.username=root jdbc.password=your_new_passwordjdbc.url中的3306是MySQL端口,如果你改了,请同步修改;serverTimezone=GMT%2B8解决时区问题,否则Java读取datetime字段会报错;jdbc.username和password填你MySQL的实际账号密码。
第三步:IDEA导入Maven项目
打开IDEA,File -> Open,选择解压后的项目根目录(含pom.xml的文件夹)。IDEA会自动识别为Maven项目,右下角弹出Import Maven Project,勾选Auto-import,点击OK。等待Maven下载所有依赖(约5分钟,取决于网速)。下载完成后,展开Project面板,确认External Libraries下有spring-core-4.3.28.RELEASE.jar、mybatis-3.4.6.jar、mysql-connector-java-5.1.47.jar等核心包。如果pom.xml报红,右键pom.xml->Maven -> Reload project。
4.3 启动与验证:看到首页,只是开始
启动方式一:Maven插件(推荐)
在IDEA底部Maven面板,展开项目名 ->Plugins->tomcat7-> 双击tomcat7:run。控制台会滚动输出:
[INFO] --- tomcat7-maven-plugin:2.2:run (default-cli) @ ymallbook --- [INFO] Running war on http://localhost:8080/ymallbook ... INFO: Server startup in 3245 ms看到Server startup即启动成功。浏览器访问http://localhost:8080/ymallbook,看到蓝色主题的点餐首页,顶部有“注册”“登录”按钮,说明前端资源加载正常。
启动方式二:部署到外部Tomcat
在IDEA中,File -> Project Structure -> Artifacts,点击+->Web Application: Archive->From modules...,选择ymallbook:war exploded,生成ymallbook:war。然后Run -> Edit Configurations -> + -> Tomcat Server -> Local,在Deployment选项卡,点击+->Artifact-> 选择刚生成的ymallbook:war。点击OK运行。这种方式更贴近真实部署场景。
验证核心功能流:
1.注册登录:点击“注册”,填入testuser/123456/13800138000,提交后自动跳转登录页,再用此账号登录。
2.浏览餐厅:首页“附近餐厅”列表应显示3家测试餐厅(川香阁、粤味轩、本帮小馆),点击任一餐厅,进入详情页,能看到菜品列表。
3.加购下单:在菜品列表,点击“加入购物车”,右上角购物车图标数字应+1;点击“去结算”,填写收货地址,提交订单。
4.查单验单:登录后,点击“我的订单”,应看到刚下的订单,状态为“待支付”,点击订单号,能查看详细菜品、价格、餐厅信息。
实操心得:如果首页空白或404,请立刻检查三件事:①
web.xml中<welcome-file-list>是否指向index.jsp;②index.jsp是否在webapp根目录下(不是webapp/WEB-INF);③ 浏览器F12看Network,哪个JS/CSS文件返回404,对应检查<script src="js/jquery.min.js">路径是否与webapp/js/目录匹配。90%的前端问题,源于路径大小写或斜杠方向错误(Windows是\,但Web路径必须是/)。
5. 常见问题与排查技巧实录:那些年我们踩过的坑
在指导学生部署这套系统的过程中,我整理了一份“高频故障速查表”。这些问题,不是来自理论推演,而是来自真实的QQ远程协助截图、微信语音通话记录、以及凌晨两点收到的求助邮件。我把它们按发生频率排序,并给出可立即执行的解决方案。
| 问题现象 | 根本原因 | 一行命令/操作解决 |
|---|---|---|
启动Tomcat报错:java.lang.ClassNotFoundException: org.springframework.web.context.ContextLoaderListener | spring-web-4.3.28.RELEASE.jar未打入WAR包,或web.xml中<listener>配置错误 | 检查pom.xml中spring-web依赖是否<scope>compile</scope>(不能是provided);确认web.xml中<listener-class>拼写正确,无多余空格 |
| 首页CSS/JS失效,页面纯文字,无样式 | 静态资源路径错误。index.jsp中<link href="css/style.css">,但实际文件在webapp/css/style.css,而Tomcat默认静态资源映射路径是/ | 在web.xml中添加静态资源放行配置:<servlet-mapping><servlet-name>default</servlet-name><url-pattern>/css/*</url-pattern></servlet-mapping><servlet-mapping><servlet-name>default</servlet-name><url-pattern>/js/*</url-pattern></servlet-mapping> |
登录时报错:java.sql.SQLException: The server time zone value 'йʱ' is unrecognized | MySQL时区未配置,Java驱动无法解析中文时区名 | 修改jdbc.properties中jdbc.url,在末尾追加&serverTimezone=GMT%2B8(即...&serverTimezone=GMT%2B8) |
| 注册成功但无法登录,提示“用户名或密码错误” | 数据库password字段长度不足。t_user.password定义为VARCHAR(20),但MD5加密后字符串长32位 | 登录前,用MySQL命令行执行:ALTER TABLE t_user MODIFY COLUMN password VARCHAR(32) NOT NULL;然后重新注册一个账号测试 |
| 购物车数量不叠加,总是新增一条记录 | t_cart表缺少UNIQUE KEY uk_user_dish (user_id,dish_id)联合唯一索引 | 执行SQL:ALTER TABLE t_cart ADD UNIQUE KEY uk_user_dish (user_id,dish_id); |
| 订单提交后,购物车未清空 | submitOrder()方法未加@Transactional,或事务未生效(如Service类未被Spring管理) | 检查OrderService实现类是否在spring-service.xml中被<bean>扫描到;确认方法上@Transactional注解的rollback-for是否包含了BusinessException(本项目自定义异常) |
独家避坑技巧分享:
技巧一:用“数据库快照”代替反复删库重建
每次改完代码想测试,你是不是习惯性地DROP DATABASE ymallbook; CREATE DATABASE...; SOURCE ymallbook.sql;?太慢了!其实ymallbook.sql脚本里,所有INSERT INTO t_user语句都带有IGNORE关键字:
INSERT IGNORE INTO t_user (id, username, password, phone, address, create_time) VALUES (1, 'admin', 'e10adc3949ba59abbe56e057f20f883e', '13800138000', '北京市朝阳区', '2023-01-01 10:00:00');INSERT IGNORE的意思是:如果主键或唯一索引冲突,就跳过这条,不报错。这意味着,你可以放心地多次执行SOURCE ymallbook.sql,用户、餐厅、菜品等基础测试数据只会插入一次,而不会报错中断。这是脚本作者留给你的“温柔后门”。
技巧二:JSP页面调试,用<%= new java.util.Date() %>快速验证EL表达式是否生效
当页面显示${user.username}为空时,别急着查Controller,先在JSP任意位置插入:
当前时间:<%= new java.util.Date() %><br/> EL测试:<%= request.getAttribute("user") != null ? "user对象存在" : "user对象为空" %>如果第一行显示时间,第二行显示“user对象为空”,说明Controller根本没把user放进request;如果第二行显示“user对象存在”,但${user.username}还是空,则是user对象的getUsername()方法没写对(注意JavaBean规范:字段username,getter必须是getUsername(),不是getUserName())。这个技巧,比看100行日志还快。
技巧三:MyBatis Generator配置,targetProject路径必须用正斜杠generator.xml中有一行:
<property name="targetProject" value="src/main/java"/>如果你在Windows上把它改成src\main\java(反斜杠),Generator会静默失败,不生成任何代码,且不报错!因为MyBatis Generator内部用File.separator处理路径,反斜杠会被转义。永远用/,这是跨平台安全写法。
最后一点真心话:
这套SSM点餐系统,不是终点,而是起点。当你顺利跑通首页、成功下一单、看到订单出现在“我的订单”里时,真正的学习才刚开始。试着做三件事:① 在OrderService.submitOrder()里加一行日志log.info("订单{}提交成功", order.getOrderNo());,观察日志输出时机;② 把t_dish.price字段类型从DECIMAL(10,2)改成INT,看看前端价格显示会怎样;③ 删除CartController中@ResponseBody注解,看看Ajax请求返回什么。代码的世界,不怕改错,怕不敢动手。这套源码的价值,不在于它完美无瑕,而在于它足够真实、足够透明,让你每一次Ctrl+S保存,都能听见技术生长的声音。
本文还有配套的精品资源,点击获取
简介:基于Spring+SpringMVC+MyBatis开发的在线点餐系统,适合作为本科毕业设计或课程大作业直接使用。前端采用JSP、HTML、CSS和JavaScript实现页面交互,后端通过Servlet和JavaBean处理业务逻辑,数据库使用MySQL,配套ymallbook.sql脚本一键建库。项目结构完整,包含src源码目录、pom.xml(已配置Maven依赖)、generator.xml(支持MyBatis逆向工程)、mysql-connector-java及mybatis-generator核心jar包。部署只需导入SQL脚本、修改jdbc.properties中的数据库连接参数,启动Tomcat即可访问首页。功能覆盖用户注册登录、餐厅列表浏览、菜品详情查看、购物车增删改查、订单提交、订单状态跟踪及历史订单查询等全流程操作。所有模块经过本地调试与实际部署验证,不依赖额外环境变量,开箱即用。
本文还有配套的精品资源,点击获取
