恒美微站 Logo 恒美微站
  • 首页
  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心
  • 联系我们

Java二手交易平台毕设课设实战:从技术选型到部署避坑

  • 首页
  • 资讯中心
  • /
  • Java二手交易平台毕设课设实战:从技术选型到部署避坑

相关资讯

极简自动化部署工具:轻量化CI/CD实践指南 2026/10/13 9:36:17
Markdown规范与高效写作全指南 2026/10/13 9:36:17
RISC-V IDE MRS使用笔记(十一):工程导出为CMake项目 2026/10/13 9:31:16

最新资讯

游戏关卡 CSV 少了列:先检查表头再读数据
BES 音频无线平台系统 API 详解:时钟、电源管理、多核通信与数据存储
Vue中后台表格组件选型与性能优化实战
Graph Engineering:用节点与边重构软件工程范式
一道难题【牛客tracker 每日一题】
35岁后端程序员转型Agent全攻略:收藏这份学习路线,一步步迈向大模型时代!

今日推荐

ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查
CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析
CAN总线错误处理机制深度解析:从位错误到Bus Off的硬件级调试

本周热门

UE动画修改实战:从资产编辑到重定向与蒙太奇驱动
统计随机数生成器攻击下的KLJN安全密钥交换协议Matlab仿真
政务API安全治理:资产测绘、低代码编排与行标对标实践

本月精选

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证
2026 大模型集体涨价:用 Python 做企业 Token 成本测算与选型避坑(附配置)

Java二手交易平台毕设课设实战:从技术选型到部署避坑

发布时间:2026/10/13 9:36:17
Java二手交易平台毕设课设实战:从技术选型到部署避坑 简介这是一套面向高校计算机相关专业学生的Java二手交易平台项目源码适用于毕业设计、课程设计及个人练手场景帮助解决从选题到落地实现完整业务系统的需求。项目基于JDK1.8与Spring Boot框架搭建采用Maven管理依赖数据库选用MySQL 5.7/8并配合Navicat进行管理开发工具兼容Eclipse与IntelliJ IDEA整体技术栈贴近企业级开发实践。压缩包共809个文件约16.84MB涵盖130个Java源文件、48个Vue组件、44个HTML与44个CSS样式文件以及153个JavaScript脚本、162个SVG图标和79个GIF素材另含SQL脚本、配置文件与构建脚本前后端资源齐备。系统覆盖用户注册登录、商品发布浏览、搜索、在线交流、订单管理、支付与物流跟踪等模块并配有单元测试与集成测试思路。已有41人学习适合需要完整项目结构、可运行源码与模块化参考的开发者快速上手与二次开发。1. 从零到一为什么“二手交易平台”是毕设课设里最稳的选题之一如果你正在为毕业设计或课程设计发愁想找一个技术栈主流、业务逻辑完整、能体现工程能力、答辩时又不容易被问倒的题目那“Java 二手交易平台”大概率是性价比最高的选择之一。它不像推荐系统那样依赖数据集和算法调参也不像高并发秒杀那样对硬件和压测环境有硬性要求但它天然覆盖了用户体系、商品管理、订单流转、支付模拟、权限控制、文件上传、搜索筛选等一整套后端工程师必须掌握的核心模块。换句话说你写的是一个平台练的是一整条 Web 开发链路。我带过几届学生的课设和毕设发现一个规律选二手交易平台的同学最后答辩时能讲的东西特别多——从数据库表怎么设计到订单状态怎么流转再到图片存本地还是对象存储每个点都能展开聊十分钟。而选某些“看起来高大上”题目的同学往往讲完算法公式就冷场了。所以这篇笔记我会按真实开发顺序把 Java 二手交易平台从技术选型、库表设计、核心接口实现到部署排错、避坑经验完整拆一遍。你照着做至少能跑通一个可演示、可答辩、可写进简历的系统。2. 技术选型与工程骨架别一上来就微服务2.1 为什么我建议 Spring Boot MyBatis-Plus MySQL 这套组合很多同学一听到“平台”两个字第一反应是上 Spring Cloud、Redis 集群、消息队列。这是毕设课设里最大的翻车点之一。你的机器可能只有 8G 内存答辩环境不一定有网络老师也不会因为你用了 Nacos 就多给二十分。相反如果因为微服务导致启动报错、服务注册不上演示直接崩盘那才是血亏。我一般会推荐这套“稳如老狗”的组合层次选型理由后端框架Spring Boot 2.7.x生态成熟资料多启动快ORMMyBatis-Plus单表 CRUD 不用写 SQL分页插件开箱即用数据库MySQL 5.7 / 8.0学校环境普遍支持语法稳定前端Vue 3 Element Plus 或 Thymeleaf前者适合想练前后端分离的后者适合只专注后端的文件存储本地磁盘 静态资源映射毕设够用不依赖云服务鉴权JWT 拦截器比 Spring Security 轻容易讲清楚这套组合的核心优势是可控所有组件你都能在本地跑起来出问题能调试答辩时能画清楚调用链路。如果时间充裕可以加 Redis 做商品缓存但不要把它作为主流程依赖否则 Redis 一挂整个系统就白屏。2.2 用 Spring Initializr 生成骨架并跑通第一个接口不要手动建 Maven 工程直接用 IDEA 的 Spring Initializr 或者 start.spring.io 生成。依赖勾选Spring Web、MyBatis-Plus、MySQL Driver、Lombok。生成后先别急着写业务先确保能启动、能连上数据库、能返回一个 JSON。// 启动类放在根包下 SpringBootApplication MapperScan(com.example.trade.mapper) // 扫描 Mapper 接口 public class TradeApplication { public static void main(String[] args) { SpringApplication.run(TradeApplication.class, args); } }# application.yml 最小配置 server: port: 8080 spring: datasource: url: jdbc:mysql://localhost:3306/second_hand?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai username: root password: 你的密码 driver-class-name: com.mysql.cj.jdbc.Driver mybatis-plus: configuration: map-underscore-to-camel-case: true # 数据库下划线转Java驼峰 global-config: db-config: logic-delete-field: deleted # 逻辑删除字段 logic-delete-value: 1 logic-not-delete-value: 0// 一个最简 Controller用来验证环境 RestController RequestMapping(/api/test) public class TestController { GetMapping(/ping) public MapString, Object ping() { MapString, Object res new HashMap(); res.put(code, 200); res.put(msg, pong); return res; } }逻辑说明启动类上的MapperScan必须指向你存放 Mapper 接口的包否则 MyBatis-Plus 注入不进来启动就报NoSuchBeanDefinitionException。application.yml里的serverTimezone一定要加MySQL 8 不加会报时区错误。map-underscore-to-camel-case开启后数据库的create_time会自动映射到 Java 的createTime省掉大量Results注解。参数说明logic-delete-field是 MyBatis-Plus 的逻辑删除配置指定实体类中哪个字段表示删除状态。这样调用removeById时不会真删数据而是更新deleted1对毕设来说既安全又能体现“数据保护”意识。跑通/api/test/ping返回{code:200,msg:pong}之后再开始设计表。这一步没跑通就去写业务等于地基没打就砌墙。2.3 包结构怎么分才不会被导师挑刺我见过太多同学把所有 Controller 堆在一个包里答辩时老师翻代码直接皱眉。推荐按职责分包com.example.trade ├── controller // 接口层只做参数校验和调用 Service ├── service │ ├── impl // 业务逻辑实现 ├── mapper // 数据库访问接口 ├── entity // 数据库实体和表一一对应 ├── dto // 前端传过来的参数对象 ├── vo // 返回给前端的视图对象 ├── config // 拦截器、跨域、静态资源映射 ├── common // 统一返回结果、常量、工具类 └── exception // 全局异常处理这样分的好处是答辩时你能指着包说“这是分层架构Controller 不碰数据库Service 不碰 HttpServletRequest”老师一听就知道你懂规矩。另外dto和vo分开很重要——不要直接用entity接收前端参数否则别人传个id就能改你数据库主键这是常见的安全漏洞。3. 数据库设计与核心表六张表撑起一个平台3.1 用户表、商品表、订单表的最小字段集二手交易平台的核心关系是用户发布商品买家下单订单关联买卖双方和商品。围绕这个关系最少需要六张表表名作用关键字段user用户信息id, username, password, nickname, avatar, phone, credit_scorecategory商品分类id, name, sortproduct商品id, user_id, category_id, title, description, price, images, status, create_timeorders订单id, order_no, product_id, buyer_id, seller_id, amount, status, create_timeaddress收货地址id, user_id, receiver, phone, detail, is_defaultfavorite收藏id, user_id, product_id, create_time注意product表里的images字段我一般存 JSON 字符串或逗号分隔的路径而不是单独建图片表。毕设阶段没必要过度设计但你要能解释“如果图片很多会拆成 product_image 表用 product_id 关联”。CREATE TABLE product ( id bigint NOT NULL AUTO_INCREMENT, user_id bigint NOT NULL COMMENT 发布者, category_id int DEFAULT NULL, title varchar(100) NOT NULL, description text, price decimal(10,2) NOT NULL, images varchar(1000) DEFAULT COMMENT 逗号分隔的图片路径, status tinyint DEFAULT 1 COMMENT 1在售 2已售 3下架, deleted tinyint DEFAULT 0, create_time datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), KEY idx_user (user_id), KEY idx_category (category_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;逻辑说明status用 tinyint 而不是 varchar是为了查询效率也方便前端用枚举映射。deleted配合 MyBatis-Plus 的逻辑删除用户“删除”商品时只是标记管理员还能恢复。idx_user和idx_category两个索引能让你在“我的发布”和“分类筛选”场景下查询快很多答辩时也能讲“我做了索引优化”。参数说明decimal(10,2)表示最多 10 位数其中 2 位小数足够表示价格。不要用 float否则会出现0.10.20.30000000000000004的经典问题订单金额对不上就麻烦了。3.2 订单状态流转用枚举而不是魔法数字订单状态是二手交易平台最容易写乱的地方。我见过有人用 0 表示待付款、1 表示已付款、2 表示已发货、3 表示已完成、4 表示已取消结果代码里到处是if (status 2)过两天自己都忘了 2 是啥。正确做法是定义枚举public enum OrderStatus { WAIT_PAY(0, 待付款), PAID(1, 已付款), SHIPPED(2, 已发货), COMPLETED(3, 已完成), CANCELLED(4, 已取消); private final int code; private final String desc; OrderStatus(int code, String desc) { this.code code; this.desc desc; } // getter 省略 }逻辑说明枚举把“数字”和“含义”绑定在一起代码里写OrderStatus.PAID.getCode()比写1可读性高得多。前端传状态时也用这个 code后端校验时遍历枚举值避免非法状态。参数说明状态流转必须单向比如待付款只能变成已付款或已取消不能从已完成跳回待付款。你可以在 Service 层加一个MapInteger, ListInteger来限制合法流转答辩时这就是“状态机”思想的体现。3.3 用 MyBatis-Plus 代码生成器省掉半天体力活六张表的 Entity、Mapper、Service、ServiceImpl 如果手写至少半天。用 MyBatis-Plus 的代码生成器十分钟搞定public class CodeGenerator { public static void main(String[] args) { FastAutoGenerator.create( jdbc:mysql://localhost:3306/second_hand?serverTimezoneAsia/Shanghai, root, 你的密码) .globalConfig(builder - builder .author(你的名字) .outputDir(System.getProperty(user.dir) /src/main/java) .disableOpenDir()) .packageConfig(builder - builder .parent(com.example.trade) .entity(entity) .mapper(mapper) .service(service) .serviceImpl(service.impl) .controller(controller)) .strategyConfig(builder - builder .addInclude(user, product, orders, category, address, favorite) .entityBuilder() .enableLombok() .logicDeleteColumnName(deleted) .addTableFills(new Column(create_time, FieldFill.INSERT)) .controllerBuilder() .enableRestStyle()) .execute(); } }逻辑说明addInclude指定要生成哪些表避免把sys_log之类的也生成出来。enableLombok()让实体类用Data代替 getter/setter。logicDeleteColumnName指定逻辑删除字段和 yml 里的配置对应。addTableFills让插入时自动填充create_time不用手动 set。参数说明outputDir建议用System.getProperty(user.dir)动态获取项目根路径避免换电脑后路径不对。生成后检查一下实体类字段类型特别是decimal对应BigDecimaldatetime对应LocalDateTime如果不对就手动改。4. 核心业务接口实现商品发布、下单、订单查询4.1 商品发布接口图片上传与参数校验商品发布是平台最核心的写操作涉及文件上传和表单提交。我一般把图片上传和商品信息提交分成两个接口先传图拿到路径再提交商品信息。这样前端可以预览后端也简单。RestController RequestMapping(/api/product) public class ProductController { Autowired private ProductService productService; // 图片上传 PostMapping(/upload) public ResultString upload(RequestParam(file) MultipartFile file) { if (file.isEmpty()) { return Result.fail(文件为空); } String original file.getOriginalFilename(); String suffix original.substring(original.lastIndexOf(.)); // 用 UUID 防止重名覆盖 String fileName UUID.randomUUID().toString() suffix; File dest new File(D:/upload/ fileName); if (!dest.getParentFile().exists()) { dest.getParentFile().mkdirs(); } try { file.transferTo(dest); return Result.success(/upload/ fileName); } catch (IOException e) { return Result.fail(上传失败); } } // 发布商品 PostMapping(/publish) public ResultLong publish(RequestBody ProductDTO dto, HttpServletRequest request) { Long userId (Long) request.getAttribute(userId); // 拦截器里放的 if (dto.getTitle() null || dto.getTitle().trim().isEmpty()) { return Result.fail(标题不能为空); } if (dto.getPrice() null || dto.getPrice().compareTo(BigDecimal.ZERO) 0) { return Result.fail(价格必须大于0); } Long productId productService.publish(dto, userId); return Result.success(productId); } }逻辑说明上传接口用UUID重命名文件避免用户传同名文件互相覆盖。dest.getParentFile().mkdirs()确保目录存在否则transferTo会报FileNotFoundException。发布接口从request里取userId这个值是在 JWT 拦截器里解析后放进去的不要相信前端传的 userId否则别人可以冒充发布者。参数说明ProductDTO里包含title、description、price、categoryId、images逗号分隔的路径。price用BigDecimal接收前端传字符串或数字都行Spring 会自动转换。校验逻辑放在 Controller 而不是 Service是为了快速失败减少无效的数据库操作。4.2 下单接口库存扣减与订单号生成二手商品和普通电商不同每件商品通常只有一件所以下单时要判断商品是否还在售。这里涉及一个并发问题两个人同时点“立即购买”不能都下单成功。Service public class OrderServiceImpl implements OrderService { Autowired private ProductMapper productMapper; Autowired private OrderMapper orderMapper; Override Transactional(rollbackFor Exception.class) public String createOrder(Long productId, Long buyerId) { // 1. 查询商品加行锁悲观锁 Product product productMapper.selectForUpdate(productId); if (product null) { throw new BizException(商品不存在); } if (product.getStatus() ! 1) { throw new BizException(商品已售出或已下架); } if (product.getUserId().equals(buyerId)) { throw new BizException(不能购买自己的商品); } // 2. 更新商品状态为已售 product.setStatus(2); productMapper.updateById(product); // 3. 生成订单 Orders order new Orders(); order.setOrderNo(generateOrderNo()); order.setProductId(productId); order.setBuyerId(buyerId); order.setSellerId(product.getUserId()); order.setAmount(product.getPrice()); order.setStatus(OrderStatus.WAIT_PAY.getCode()); orderMapper.insert(order); return order.getOrderNo(); } private String generateOrderNo() { // 时间戳 随机数保证唯一 return System.currentTimeMillis() String.format(%04d, new Random().nextInt(10000)); } }!-- ProductMapper.xml 里的悲观锁查询 -- select idselectForUpdate resultTypecom.example.trade.entity.Product SELECT * FROM product WHERE id #{id} AND deleted 0 FOR UPDATE /select逻辑说明FOR UPDATE是 MySQL 的悲观锁在事务中锁定这一行第二个请求会等待第一个事务提交后才能读到最新状态。这样就能防止超卖。Transactional保证商品状态更新和订单插入在同一个事务里任何一步失败都回滚。订单号用“时间戳随机数”生成简单且够用毕设不需要分布式 ID 生成器。参数说明rollbackFor Exception.class确保所有异常都触发回滚默认只回滚RuntimeException如果抛出受检异常就不会回滚这是常见坑。selectForUpdate必须放在事务里才生效如果 Service 没加Transactional锁会立即释放等于没锁。4.3 订单列表与详情分页查询和权限校验订单查询要区分“我买到的”和“我卖出的”并且只能看自己的订单。这里用 MyBatis-Plus 的分页插件GetMapping(/my) public ResultPageOrderVO myOrders( RequestParam(defaultValue 1) Integer page, RequestParam(defaultValue 10) Integer size, RequestParam String type, // buy 或 sell HttpServletRequest request) { Long userId (Long) request.getAttribute(userId); PageOrderVO result orderService.pageMyOrders(page, size, type, userId); return Result.success(result); }Override public PageOrderVO pageMyOrders(Integer page, Integer size, String type, Long userId) { PageOrders pageParam new Page(page, size); LambdaQueryWrapperOrders wrapper new LambdaQueryWrapper(); if (buy.equals(type)) { wrapper.eq(Orders::getBuyerId, userId); } else { wrapper.eq(Orders::getSellerId, userId); } wrapper.orderByDesc(Orders::getCreateTime); PageOrders ordersPage orderMapper.selectPage(pageParam, wrapper); // 转换成 VO补充商品标题和图片 return ordersPage.convert(this::toVO); }逻辑说明LambdaQueryWrapper用方法引用代替字符串字段名编译期就能发现拼写错误。orderByDesc按创建时间倒序最新的订单在前。convert把Orders转成OrderVO在 VO 里补充商品标题、图片、对方昵称前端一次请求就能渲染列表不用再查商品表。参数说明page和size要做边界校验比如size最大 50防止前端传size10000把数据库拖垮。type只允许buy或sell其他值默认按sell处理或者直接返回参数错误。5. 避坑与排查那些让我熬夜到凌晨三点的坑5.1 跨域问题前端 8081 调后端 8080 被浏览器拦截现象前端用 Vue 跑在 8081 端口调后端 8080 的接口浏览器控制台报Access-Control-Allow-Origin错误请求发不出去。原因浏览器的同源策略限制协议、域名、端口任一不同就算跨域。后端没返回 CORS 响应头浏览器就拦截。解决加一个全局跨域配置不要在每个 Controller 上写CrossOrigin。Configuration public class CorsConfig implements WebMvcConfigurer { Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping(/**) .allowedOriginPatterns(*) // 允许所有来源生产环境要指定 .allowedMethods(GET, POST, PUT, DELETE, OPTIONS) .allowedHeaders(*) .allowCredentials(true) .maxAge(3600); } }注意allowedOriginPatterns和allowedOrigins的区别当allowCredentials(true)时allowedOrigins(*)会报错必须用allowedOriginPatterns。这是 Spring Boot 2.4 之后的改动很多老教程还在用allowedOrigins照抄就翻车。5.2 图片上传后访问 404静态资源映射没配现象图片上传成功数据库里也存了路径但前端img src/upload/xxx.jpg显示裂图浏览器 404。原因Spring Boot 默认只映射classpath:/static/下的静态资源你存在D:/upload/的文件不在默认路径里。解决在配置类里加静态资源映射。Configuration public class WebConfig implements WebMvcConfigurer { Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler(/upload/**) .addResourceLocations(file:D:/upload/); } }addResourceLocations最后必须带斜杠否则拼接路径会出错。Windows 下用file:D:/upload/Linux 下用file:/home/upload/。如果部署到服务器路径要改成服务器上的实际路径。5.3 事务不生效方法内部调用导致代理失效现象在 Service 的 A 方法里直接调用本类的 B 方法B 方法上加了Transactional但 B 方法抛异常后数据没回滚。原因Spring 的事务是基于 AOP 代理的外部调用走代理对象事务生效但类内部this.B()调用的是原始对象不经过代理事务注解形同虚设。解决三种方式——把 B 方法移到另一个 Service 里用AopContext.currentProxy()获取代理对象再调用或者把 B 方法的事务逻辑合并到 A 方法。我一般推荐第一种职责也更清晰。5.4 逻辑删除后唯一索引冲突现象用户删除了一个商品想重新发布一个同名商品结果报Duplicate entry错误。原因你在title上建了唯一索引逻辑删除只是把deleted改成 1记录还在表里唯一索引依然生效。解决要么去掉唯一索引用业务代码校验要么把唯一索引改成(title, deleted)联合索引但这样只能删一次。更常见的做法是不加唯一索引在 Service 层用count查询判断是否重复把deleted0作为条件。5.5 前端传的时间格式后端解析失败现象前端用new Date()传2024-01-01T12:00:00.000Z后端用LocalDateTime接收报JSON parse error。原因Jackson 默认不支持 ISO 8601 带时区的格式转LocalDateTime。解决在实体类字段上加JsonFormat或者全局配置。JsonFormat(pattern yyyy-MM-dd HH:mm:ss, timezone GMT8) private LocalDateTime createTime;更省事的做法是在application.yml里配spring: jackson: date-format: yyyy-MM-dd HH:mm:ss time-zone: GMT8但LocalDateTime不受date-format控制还是得加JsonFormat。这是血泪经验别问我是怎么知道的。6. 进阶技巧让答辩老师眼前一亮的三个细节6.1 用 AOP 记录操作日志答辩时能演示“谁在什么时候改了什么”毕设系统通常没有日志但如果你加一个简单的 AOP 切面记录每个增删改操作的执行人、方法、参数和耗时答辩时就能展示“系统可审计”。实现很简单Aspect Component public class LogAspect { Autowired private LogMapper logMapper; Around(annotation(com.example.trade.common.LogRecord)) public Object around(ProceedingJoinPoint point) throws Throwable { long start System.currentTimeMillis(); Object result point.proceed(); long cost System.currentTimeMillis() - start; // 从请求上下文拿 userId ServletRequestAttributes attrs (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); Long userId (Long) attrs.getRequest().getAttribute(userId); SysLog log new SysLog(); log.setUserId(userId); log.setMethod(point.getSignature().toShortString()); log.setCost(cost); log.setCreateTime(LocalDateTime.now()); logMapper.insert(log); return result; } }然后在需要记录的方法上加LogRecord注解即可。注意日志插入不要和业务在同一个事务里否则业务回滚日志也没了。可以加Transactional(propagation Propagation.REQUIRES_NEW)或者直接异步。6.2 商品搜索用 LIKE 还是全文索引数据量决定方案毕设数据量通常几百到几千条LIKE %关键词%完全够用而且实现简单wrapper.like(StringUtils.hasText(keyword), Product::getTitle, keyword) .or() .like(StringUtils.hasText(keyword), Product::getDescription, keyword);但如果答辩老师问“数据量大了怎么办”你要能答上来数据量到十万级以上LIKE 前置模糊会全表扫描这时候可以上 Elasticsearch 或者 MySQL 的全文索引ngram 分词器。毕设不要求你真做但你要知道边界在哪。我一般会在论文的“展望”部分写一句“后续可引入全文检索引擎优化搜索体验”老师就知道你有思考。6.3 部署时用 Nginx 反向代理避免前端 404 和后端端口暴露最后一步是把项目部署到服务器。不要直接用java -jar跑在 80 端口也不要把前端打包后丢到 Spring Boot 的 static 目录里虽然能跑但不优雅。推荐 Nginx 反代server { listen 80; server_name your_domain; location / { root /var/www/trade/dist; # 前端打包目录 try_files $uri $uri/ /index.html; # Vue history 模式必须加 } location /api/ { proxy_pass http://127.0.0.1:8080/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } location /upload/ { alias /home/upload/; # 图片实际存储目录 } }try_files那行是 Vue Router history 模式的关键不加的话刷新页面就 404。proxy_pass最后的斜杠要注意http://127.0.0.1:8080/会把/api/product转成/product如果后端接口本身带/api前缀就不要加最后的斜杠。这个细节坑过很多人。6.4 我的习惯每次改完代码先跑一遍“下单-支付-完成”全流程最后说一个我自己的习惯。不管改了什么哪怕只是改了一个字段名我都会在本地把“注册-登录-发布商品-下单-模拟支付-确认收货”这条主流程手动跑一遍。因为二手交易平台的核心价值就在这条链路上任何一个环节断了演示就砸了。不要只跑单元测试单元测试测不出前端传参格式不对、拦截器没放行、静态资源 404 这些问题。手动跑一遍五分钟能省掉答辩前夜的通宵。希望帮到你。本文还有配套的精品资源点击获取

关于恒美微站

恒美微站专注于为个体商户、工作室提供极简自助建站服务,让每个人都能轻松拥有专业网站。

快速链接

  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心

服务项目

  • 可视化建站
  • 拖拽编辑
  • 主题定制
  • SEO 优化
  • 网站托管

联系方式

  • 📍 地址:北京市朝阳区建国路 88 号
  • 📞 电话:400-888-8888
  • ✉️ 邮箱:info@hmyw.cn
  • 🕐 时间:周一至周日 9:00-18:00

© 2024 恒美微站 hmyw.cn 版权所有 | 京 ICP 备 12345678 号