ARTICLE DETAIL

资讯详情

深耕商务建站与企业官网运营的一线实战洞察。

SpringBoot+Vue无人智慧超市项目实战:从MySQL数据库到前后端分离部署

SpringBoot+Vue无人智慧超市项目实战:从MySQL数据库到前后端分离部署 之前整理过一个SpringBootVue的无人智慧超市项目被好几个准备做毕设的同学追着问干脆把完整的实现思路和坑点都写出来。这套系统后端是SpringBootMyBatis-Plus前端是VueElement UI数据库用MySQL逻辑并不复杂但覆盖了一个小型管理系统的完整闭环商品管理、会员管理、自助购物车、订单结算、门禁模拟、数据统计拿去应付本科毕设或者课程设计完全够用更重要的是每个模块都能讲清楚为什么这么做。如果你正处在选型阶段最关心的无非是三件事好不好跑起来、代码量大不大、答辩能不能讲明白。先说结论这套项目属于中等体量后端大概十几个核心接口前端七八个页面一个人一周左右能啃完而且因为业务贴近日常生活功能解释起来非常直观。1. 项目整体定位与设计思路1.1 这个系统到底解决了什么问题无人智慧超市核心就是把传统超市的人工收银、人工盘货、人工门禁这些环节自动化。放在毕设场景里不需要你真的接入人脸识别硬件或重力感应货架而是用软件模拟这套流程用户扫码或注册会员后进店选择商品加入虚拟购物车结算时系统自动计算金额并扣除账户余额或模拟支付出门时校验订单状态。管理端则负责商品上下架、库存调整、订单查询、会员管理、销售统计。这个业务模型的价值在于它天然包含了一个管理信息系统该有的所有要素数据建模、前后端交互、权限控制、状态流转、统计报表。老师问你这个系统做了什么你可以顺着用户一条完整的购物链路讲下来老师问你用了什么技术前后端分离、RESTful接口、JWT鉴权、MyBatis-Plus条件构造器都能排得上用场。1.2 为什么选SpringBootVue这套组合而不是其他方案每年毕设选型都会被问这个问题我的建议很直接如果你是Java方向这就是最稳的组合。SpringBoot把Spring的配置简化到了极致内嵌Tomcat打成一个Jar包就能跑不需要折腾Tomcat部署。MyBatis-Plus又在MyBatis基础上把单表CRUD写成了现成的方法省掉大量重复的Mapper XML。前端Vue配合Element UI表格、表单、弹窗、分页这些后台管理页面最常见的组件都有现成的不需要自己手搓UI。对比一下其他方案你就明白了如果用JSPServlet代码写得再规范答辩时也容易被质疑技术陈旧如果后端用Python的Django又和你Java课程的主线不一致面试时不好解释。SpringBootVue是当前企业里中小型管理系统的主流搭档学完写在简历上不亏。还有一个实际原因网上这套组合的参考资料最多遇到报错基本都能搜到解决方案。我见过太多同学选了冷门框架最后卡在一个莫名其妙的依赖冲突上连问都没处问。选热门技术栈本身就是降低风险的手段。1.3 无人超市的完整业务流程梳理把业务流程理清楚后面建模就顺了。一个用户从进店到离店大致经历这样几步进店用户扫码或者输入会员手机号系统校验身份生成一个会话记录标记在店状态。选购用户浏览商品列表把商品加入购物车。这里不需要真实扫码枪前端页面加个按钮就行。结算用户提交购物车后端计算总金额调用模拟支付接口扣减余额生成订单扣减库存。离店系统根据订单状态更新会话记录为已离店后端返回一个放行标识前端展示模拟门禁放行动画。管理端的流程就简单了管理员登录维护商品分类和商品信息处理库存预警查看订单列表和销售额统计。整个系统就是这两条主线的交织数据库表也是围绕这两条线设计的。2. 技术栈与项目结构2.1 后端分层结构与Maven依赖后端我用标准的四层结构Controller接收前端请求Service写业务逻辑Mapper操作数据库Entity映射表结构。有人觉得分层麻烦但毕设答辩时这就是加分项你可以明确告诉老师我遵循了单一职责原则。pom.xml里的核心依赖就这么几个dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-boot-starter/artifactId version3.5.5/version /dependency dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId version8.0.33/version /dependency dependency groupIdio.jsonwebtoken/groupId artifactIdjjwt-api/artifactId version0.11.5/version /dependency dependency groupIdcn.hutool/groupId artifactIdhutool-all/artifactId version5.8.25/version /dependencyHutool是个小工具库生成随机订单号、日期处理、加密都用得上。依赖别一股脑全加够用就好加多了版本冲突反而麻烦。JWT用来做登录鉴权比传统的Session更适合前后端分离的场景。2.2 SpringBoot版本与JDK版本怎么选这里需要重点提醒SpringBoot版本不是越高越好。我一开始用了SpringBoot 3.2.x结果它要求JDK 17而且部分老版本的MyBatis-Plus、Druid和它有兼容问题。如果你只是做毕设没必要追新推荐用SpringBoot 2.7.18配合JDK 8这个组合经过大量项目验证网上报错解决方案也最全。# application.yml 核心配置 server: port: 8080 spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/smart_mart?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai username: root password: 123456 jackson: date-format: yyyy-MM-dd HH:mm:ss time-zone: Asia/Shanghai mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl global-config: db-config: logic-delete-field: deleted logic-delete-value: 1 logic-not-delete-value: 0注意url里的serverTimezoneAsia/Shanghai不加上MySQL 8连接时会报时区错误。log-impl配置成StdOutImpl可以在控制台打印SQL排查问题时非常有用答辩演示时也方便展示。我见过不少同学卡在这些基础配置上其实都是经验问题。2.3 前端Vue项目的搭建方式前端我用的是Vue 2不是Vue 3。不是说Vue 3不好而是Element UI对Vue 2的支持最成熟网上的示例代码90%都是Vue 2写法照着抄不容易翻车。如果你非要用Vue 3那配合Element Plus也行但很多细节写法有差异调试成本会高一些。创建项目用Vue CLInpm install -g vue/cli vue create smart-mart-web # 选择 Manually select features勾选 Router cd smart-mart-web npm install element-ui axios安装依赖的过程经常出问题尤其是网络不稳定的时候node_modules装一半失败了。国内环境建议先设置npm镜像源再安装npm config set registry https://registry.npmmirror.com装完依赖后在main.js里注册Element UI和Router然后按页面拆组件。我的页面结构是登录页、用户端首页、商品列表页、购物车页、订单确认页、管理端布局、商品管理页、订单管理页、会员管理页、统计页。每个页面一个文件夹组件按需拆分。3. 数据库设计与核心功能模块3.1 数据库表设计五张表串起整个系统数据库是这套项目的地基表设计得好后面的代码能少写一半。我设计了五张核心表用户表、商品表、订单表、订单明细表、购物车表。下面给出建表SQL的核心片段。CREATE TABLE user ( id bigint NOT NULL AUTO_INCREMENT, phone varchar(20) NOT NULL, password varchar(100) NOT NULL, nickname varchar(50) DEFAULT NULL, balance decimal(10,2) DEFAULT 0.00, role tinyint DEFAULT 1, status tinyint DEFAULT 1, create_time datetime DEFAULT NULL, PRIMARY KEY (id), UNIQUE KEY uk_phone (phone) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;role字段区分管理员和普通用户balance存账户余额这是模拟支付的账户来源。手机号加唯一索引这是登录账号。CREATE TABLE product ( id bigint NOT NULL AUTO_INCREMENT, name varchar(100) NOT NULL, category_id bigint DEFAULT NULL, price decimal(10,2) NOT NULL, stock int NOT NULL, image varchar(255) DEFAULT NULL, status tinyint DEFAULT 1, PRIMARY KEY (id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;商品表加了category_id字段预留分类扩展status字段控制上下架下架的商品用户端不展示。CREATE TABLE orders ( id bigint NOT NULL AUTO_INCREMENT, order_no varchar(32) NOT NULL, user_id bigint NOT NULL, total_amount decimal(10,2) NOT NULL, status tinyint DEFAULT 0, create_time datetime DEFAULT NULL, pay_time datetime DEFAULT NULL, PRIMARY KEY (id), UNIQUE KEY uk_order_no (order_no) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;订单表里status是整个系统最关键的状态字段0代表待支付1代表已支付2代表已离店。字段注释必须写清楚答辩时老师一定会问状态怎么流转的。CREATE TABLE order_item ( id bigint NOT NULL AUTO_INCREMENT, order_id bigint NOT NULL, product_id bigint NOT NULL, product_name varchar(100) DEFAULT NULL, price decimal(10,2) NOT NULL, quantity int NOT NULL, PRIMARY KEY (id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;为什么要有订单明细表因为一个订单可能包含多个商品而订单表只保存总额。到时候你要查某个订单里买了哪些东西没有明细表根本查不了。还有一点下单时要把商品名称和价格冗余存一份这样即使日后商品改名或者删除订单的历史记录仍然完整。这是电商系统的常规做法讲出来显得专业。3.2 用户端功能模块从登录到购物车用户端核心接口就四个注册登录、商品列表、购物车操作、提交订单。登录用手机号密码密码存在数据库里用MD5加盐处理。我知道MD5不算安全但毕设项目里够用而且你可以主动跟老师说生产环境应该用BCrypt这反而成了加分项。购物车我采用了后端存储而不是前端存储的方案。有人认为购物车存前端localStorage简单但那样用户换设备数据就丢了。我用一张购物车表关联用户和商品后端提供添加、修改数量、删除、查询四个接口。数据结构很简单操作逻辑都在Service层。Service public class CartServiceImpl implements CartService { Override public Result addCart(CartDTO dto) { // 先查询该用户购物车里是否已有这个商品 LambdaQueryWrapperCart wrapper new LambdaQueryWrapper(); wrapper.eq(Cart::getUserId, dto.getUserId()) .eq(Cart::getProductId, dto.getProductId()); Cart exist cartMapper.selectOne(wrapper); if (exist ! null) { exist.setQuantity(exist.getQuantity() dto.getQuantity()); cartMapper.updateById(exist); } else { Cart cart new Cart(); cart.setUserId(dto.getUserId()); cart.setProductId(dto.getProductId()); cart.setQuantity(dto.getQuantity()); cartMapper.insert(cart); } return Result.success(加入成功); } }这里用MyBatis-Plus的LambdaQueryWrapper构造条件比写XML简洁很多而且类型安全字段名写错了编译期就能发现。3.3 管理端功能模块商品、订单、会员、统计管理端的商品管理就是常规的增删改查分页MyBatis-Plus自带Page对象配合selectPage方法几行代码搞定Override public PageProduct pageProducts(int pageNum, int pageSize, String keyword) { PageProduct page new Page(pageNum, pageSize); LambdaQueryWrapperProduct wrapper new LambdaQueryWrapper(); if (StringUtils.hasText(keyword)) { wrapper.like(Product::getName, keyword); } wrapper.orderByDesc(Product::getCreateTime); return productMapper.selectPage(page, wrapper); }订单管理就是按状态筛选订单列表也可以查看订单的明细。这里有个小技巧查询订单列表时如果每条订单都要单独查一次明细会产生N1查询问题。简单项目可以不那么较真但如果想展示自己的水平可以在Service层先把订单ID列表查出来再一次性批量查询明细然后按订单ID分组组装。这个优化讲出来能让老师觉得你不是在背代码。会员管理做得简单就是一个用户列表可以看到每个用户的余额和消费统计。统计模块我用ECharts画了两个图表近七天销售额折线图、商品分类销量占比饼图。数据来源是SQL的聚合查询。这里千万别用循环查数据库再在Java里计算效率低而且代码丑直接让MySQL分组求和查出来什么就展示什么。SELECT DATE_FORMAT(create_time, %Y-%m-%d) AS day, SUM(total_amount) AS amount FROM orders WHERE status 1 AND create_time DATE_SUB(CURDATE(), INTERVAL 7 DAY) GROUP BY day ORDER BY day;4. 关键代码实现与实操细节4.1 模拟门禁与结算的核心逻辑无人超市系统最需要讲故事的地方就是结算后如何放行。真实场景是硬件联动这里用软件模拟。我在后端设计了这样一套逻辑用户在购物车页面点击结算前端把购物车ID列表和用户ID传给后端。后端先校验所有商品库存是否充足如果不够就返回明确提示。库存充足的情况下在一个方法里完成三件事计算总金额、生成订单和订单明细、扣减库存和用户余额。这三件事必须放在同一个事务里要么全部成功要么全部回滚。这一步一定要讲清楚事务是保证数据一致性的关键。Transactional(rollbackFor Exception.class) public Result checkout(CheckoutDTO dto) { ListCart carts cartMapper.selectBatchIds(dto.getCartIds()); BigDecimal total BigDecimal.ZERO; for (Cart cart : carts) { Product product productMapper.selectById(cart.getProductId()); if (product.getStock() cart.getQuantity()) { return Result.error(商品【 product.getName() 】库存不足); } total total.add(product.getPrice().multiply(BigDecimal.valueOf(cart.getQuantity()))); } // 生成订单号 String orderNo SM DateUtil.format(new Date(), yyyyMMddHHmmss) RandomUtil.randomNumbers(4); Orders order new Orders(); order.setOrderNo(orderNo); order.setUserId(dto.getUserId()); order.setTotalAmount(total); order.setStatus(1); order.setPayTime(new Date()); ordersMapper.insert(order); // 插入订单明细、扣减库存、扣减余额、清空购物车 return Result.success(orderNo); }事务注解Transactional放在这里的作用是如果插入订单成功后扣库存失败整个方法回滚不会出现订单生成了但库存没扣的脏数据。你可以把这句话原封不动写进论文里。4.2 JWT登录鉴权的实现细节前后端分离项目里登录状态通常用JWT而不是Session。JWT就是一个包含用户信息的加密字符串服务器不保存状态客户端每次请求带上服务器验证签名后解析出用户ID。实现分三步第一步登录成功后签发TokenString token Jwts.builder() .setSubject(user.getId().toString()) .claim(phone, user.getPhone()) .claim(role, user.getRole()) .setExpiration(new Date(System.currentTimeMillis() 86400000)) .signWith(secretKey, SignatureAlgorithm.HS256) .compact();第二步写一个拦截器拦截需要登录的接口public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { String token request.getHeader(Authorization); if (token null || !token.startsWith(Bearer )) { // 返回401状态码 response.setStatus(401); return false; } try { Claims claims Jwts.parserBuilder() .setSigningKey(secretKey) .build() .parseClaimsJws(token.substring(7)) .getBody(); request.setAttribute(userId, claims.getSubject()); return true; } catch (JwtException e) { response.setStatus(401); return false; } }第三步在WebMvcConfigurer里注册拦截器配置哪些路径需要拦截。登录接口和商品列表接口不需要拦截购物车、订单、管理端接口全部拦截。前端拿到401响应就跳回登录页。这里要注意一个坑拦截器注册路径如果写错你会发现某些接口没拦截、某些接口明明应该拦截却放行了。我习惯把接口路径统一用/api/**开头然后根据需要排除/api/user/login、/api/product/list这些公开接口。4.3 Vue端的路由守卫与Axios封装前端要做的事情是在Axios请求拦截器里自动带上Token在响应拦截器里统一处理401跳转。这个属于固定套路直接贴代码说明。// request.js axios.interceptors.request.use(config { const token localStorage.getItem(token); if (token) { config.headers[Authorization] Bearer token; } return config; }); axios.interceptors.response.use( response response.data, error { if (error.response error.response.status 401) { localStorage.removeItem(token); router.push(/login); } return Promise.reject(error); } );路由守卫控制页面访问权限。比如管理端页面只有role0的用户能访问普通用户跳进去要弹提示router.beforeEach((to, from, next) { const token localStorage.getItem(token); if (to.path /login) { next(); return; } if (!token) { next(/login); return; } const role localStorage.getItem(role); if (to.meta.requiresAdmin role ! 0) { next(/); return; } next(); });我见过有些同学的毕设前端页面能直接通过URL访问后台接口这就是没做路由守卫答辩时被问如何防止未授权访问就答不上来。这一段属于安全要点值得单独准备一下。4.4 模拟支付与订单状态流转支付模块不用接真实支付接口做一个模拟余额支付就行。用户可以事先在个人中心给账户充值也是模拟的管理员直接改余额。结算时后端判断余额是否足够不够就返回余额不足请充值够就扣减余额并生成支付记录。订单状态从0流转到1再在用户点击确认离店时流转到2。如果你想让系统看起来更完整还可以加一层虚拟的门外设备检测用户订单状态为2之后前端门禁页显示门锁已开启请通过。这个效果用Vue的过渡动画就能实现成本低演示效果好。5. 本地部署与运行环境搭建5.1 开发环境准备清单我把整套环境版本列成一个清单照着装就不会出兼容性问题组件版本说明JDK1.8别用17兼容问题太多MySQL5.7 或 8.08.0需要配置时区Node.js16.xVue2项目对Node版本要求宽松Maven3.8.xIDEA自带也可IDEA2023.x社区版够用MySQL安装时有个细节安装到Windows上的时候如果之前装过其他版本端口3306可能被占用用netstat -ano查一下端口占用或者直接改端口3307并在连接串里同步修改。我遇到过一个同学装完MySQLNavicat连接不上折腾半天发现服务根本没启动Windows服务列表里把MySQL服务启动就好了。5.2 数据库初始化的两种方式第一种是用Navicat手工导入SQL文件适合看不懂命令行的人。新建数据库smart_mart字符集选utf8mb4右键运行SQL文件把建表语句和初始数据一起导入。第二种是用命令行mysql -u root -p smart_mart.sql初始数据里我预置了几个测试账号一个管理员账号admin/123456一个普通用户13800000000/123456还有十来个商品数据。有初始数据的好处是系统一跑起来就能看到效果不用一个个手动录入。答辩前务必检查演示账号还能不能用我见过有人把数据库密码改了现场登录不进去非常尴尬。5.3 SpringBoot与Vue的启动顺序后端启动很简单IDEA里直接运行SmartMartApplication的main方法。启动后访问http://localhost:8080如果看到SpringBoot默认的错误页说明端口正常。前端启动分两步npm install npm run serveDevServer默认跑在8080端口而后端也在8080必然冲突。解决办法是在vue.config.js里配置前端端口和代理module.exports { devServer: { port: 3000, proxy: { /api: { target: http://localhost:8080, changeOrigin: true } } } }配置代理之后前端请求/api/product/list会转发到后端的http://localhost:8080/api/product/list跨域问题由DevServer解决浏览器里看不到跨域报错。启动顺序没有严格要求但先启动后端再启动前端能保证前端代理的调试信息里不至于报连接被拒绝。5.4 生产环境打包前后端怎么合到一起毕设如果需要部署演示最省事的方式是把前端的build产物放到SpringBoot的static目录下最后只发布一个Jar包。操作流程是npm run build生成dist目录把dist下的所有文件复制到后端项目的src/main/resources/static目录下再用Maven打包mvn clean package -DskipTests生成的target/smart-mart.jar用java -jar smart-mart.jar运行浏览器直接访问http://localhost:8080SpringBoot会把前端页面和接口请求放在同一个端口处理。注意此时前端的接口请求路径必须是相对路径也就是/api/xxx不能写死成localhost:3000否则页面加载了但接口全部403。6. 常见问题与避坑记录6.1 SpringBoot版本太高引发的连环报错这是这一届学生里最常见的坑。SpringBoot 3.x强制要求JDK 17而很多人本机装的是JDK 8启动直接报UnsupportedClassVersionError。就算你临时改了JDK版本MyBatis-Plus老版本里的Jsoup等依赖也会出现ClassNotFoundException因为SpringBoot 3用了Jakarta命名空间不再兼容javax.*。我的建议是统一用SpringBoot 2.7.18 JDK 8。如果你的团队或者老师要求必须用新版本也不要硬扛直接换MyBatis-Plus 3.5.5以上版本并在pom.xml里排查所有用到javax.servlet的依赖。这类问题排查耗时很长而且越查越乱不如一开始就选稳定版本。6.2 MySQL连接失败时区、驱动、密码三个坎连接MySQL 8时第一个坎是时区不配置serverTimezoneAsia/Shanghai会报The server time zone value Öйú±ê׼ʱ¼ä is unrecognized解决办法就是在连接串里加上时区参数。第二个坎是驱动类名MySQL 8要写com.mysql.cj.jdbc.Driver写旧的com.mysql.jdbc.Driver虽然也能跑但会报警告。第三个坎是密码验证方式MySQL 8默认用的caching_sha2_password和旧版JDBC驱动不兼容要么升级驱动版本要么在MySQL里执行ALTER USER rootlocalhost IDENTIFIED WITH mysql_native_password BY 密码。新手最容易在这里丧失信心其实这些报错信息都很直白把英文翻译一下就知道缺什么了。排查原则先看MySQL服务有没有启动再用命令行工具连接测试最后才去检查Java代码和配置。6.3 Vue项目启动报错与依赖安装问题vue create过程可能卡在chromedriver这个依赖上这个是网络问题居多。装依赖时看到卡住不要直接CtrlC先等一会儿实在不行就换成npmmirror镜像源再试。有些同学从前端拿到别人项目压缩包后直接扔进IDEA这东西不是Java项目要先用命令行进入目录执行npm installIDEA只能帮你打开文件装依赖还得靠npm。还有一类问题是Vue CLI版本太高要求Node.js版本过低的环境会报Digital Envelope routines::unsupported错误。常见的临时解决办法是执行export NODE_OPTIONS--openssl-legacy-provider但这是权宜之计最好还是把Node.js升级到16或18的稳定版本。总之前端环境问题大多出在版本不匹配上和写代码的关系不大但确实很消磨耐心。6.4 前后端联调时常见的跨域与接口对接问题跨域问题是必考题。如果前端直接请求后端地址而没有走代理浏览器会报CORS错误。解决方式有两个一个是在SpringBoot里配置全局CORS另一个是像前面那样在vue.config.js里配代理。我推荐后者因为生产环境打包后是同源部署配置代理能顺带模拟出这个效果。接口对接时的另一个坑是字段名对不上。前端约定用productName后端实体类写的是name结果列表里商品名称一列全是空的。这种问题排查起来很烦建议开发时打开浏览器F12看网络请求的响应体先确定后端返回了哪些字段再去前端模板里核对。关键接口直接用Polyline图的思路调通一个再看下一个不要攒了一堆问题再一起调试。6.5 答辩演示时的三个稳定性建议现场演示翻车是毕设答辩的重灾区我总结三个经验。第一演示前一天必须跑一遍完整流程不要侥幸小改动不影响。第二手机热点和现场WiFi都不要压上把学生证、身份证等无关页面关掉省得切换页面时卡顿。第三数据库里要准备好演示数据商品别太少订单要有不同状态的这样展示列表筛选功能时才有内容。还有一个容易被忽略的点答辩时老师喜欢反问你觉得这个系统哪里还可以改进。提前准备几个合理的优化方向比如引入Redis做购物车缓存、用RabbitMQ处理订单异步通知、接入真实人脸识别SDK都会让回答更从容。7. 后端的扩展与学习建议7.1 这个项目还能怎么扩展成创新点毕设如果只是把基本功能做完很多学校只给中等分。想让系统更有竞争力可以从三个方向扩展。第一个方向是把静态的商品列表升级成分页条件搜索比如按价格区间、分类、热度排序这涉及MyBatis-Plus的多条件组合查询论文里也好写。第二个方向是加一个简单的推荐模块根据用户购买记录推荐同类商品不需要上机器学习算法用一个简单规则统计就行。第三个方向是接入WebSocket做实时库存展示前端页面每两秒刷新一次库存管理员能看到哪些商品快卖完了。我个人觉得最划算的扩展是导入导出用EasyExcel实现商品数据的Excel批量导入和订单导出。这个功能企业里用得极多而且演示效果直观先把Excel模板下载出来填几条数据再导入前后端都有交互答辩时可以让老师亲眼看到数据从Excel流进了数据库比纯口头描述有说服力得多。7.2 学完这套项目你真正会收获什么把这个项目完整撸一遍你收获的不只是一堆代码。你会真正理解一个管理系统的请求怎么从前端页面发起经过拦截器校验、Controller参数接收、Service业务处理、Mapper数据查询最后再返回到页面上完整走通。这个链路是书本里很难讲透的只有亲手连起来才有感觉。很多人学新项目喜欢通篇复制跑通了就觉得自己会了。我的建议是跑通之后从一个小功能开始独立重写比如单独把提交订单逻辑自己写一遍不参考原代码。能写出来说明你真正掌握了写不出来就对着原代码一行行比对找出你卡住的地方那正是你需要补的知识点。7.3 最后补充一个调试的小技巧在项目开发过程中我强烈建议后端保持log-impl: org.apache.ibatis.logging.stdout.StdOutImpl这条配置能让控制台打印出每条SQL执行语句和参数值。当你的列表数据不对时先看SQL有没有按预期拼接条件当更新操作没生效时先看SQL影响行数是0还是1。大部分数据问题都能靠这一步定位比在Java代码里打断点还高效。调试工具上前端打开F12的Network面板看接口响应后端看IDEA控制台的日志两边对照着调效率会高很多。不要碰到问题就甩给系统报错四个字先把报错信息完整读三遍你会发现大部分问题其实描述得已经很清楚了。
返回列表
PREV
查看更多资讯
NEXT
返回资讯列表