news 2026/9/14 14:25:48

二手交易小程序全栈拆解:Spring Boot + 微信小程序毕设实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
二手交易小程序全栈拆解:Spring Boot + 微信小程序毕设实战

简介:微信小程序二手物品交易系统源码与数据库,面向高校毕业设计及Java课程设计场景,为需要完成类似选题的学生提供一套可直接运行学习的完整项目。源码经过本地编译验证,下载后配置JDK、MySQL及微信开发者工具环境即可运行,功能模块覆盖用户登录、商品发布、浏览、搜索、收藏、下单等二手交易核心流程,整体设计满足老师验收要求。资源包共1154个文件,包体约17MB,包含Java后端源码、微信小程序前端页面、SQL数据库脚本及配置文件,其中png/jpg/gif为界面与商品图片,js/wxml/wxss为小程序页面逻辑与样式,java/class为后端业务代码,xml/json为配置与数据交换。已有405人学习下载,适合毕业设计参考、项目复现或二次开发,借助完整目录结构可快速定位前后端代码与数据库脚本,节省环境搭建和编码时间。

1. 毕业设计里最常见的二手交易小程序,其实拆开看就三件事

二手物品交易在毕业设计和课程设计里属于出现频率最高的一类选题,功能链路完整,业务深度适中,既不会简单到没东西写,也不会复杂到一个人做不完。这套源码的价值不在于页面视觉效果,而在于它把前后端分离、登录态管理、订单状态机这些生产环境常见的结构,放进了一个能本地直接跑通的小工程里。项目包含微信小程序前端、Java后端和数据库脚本,核心围绕用户登录、商品发布、订单流转、收藏管理四个模块展开。适合正在做毕设或课设的人下载后先跑通再二次开发,也适合刚学完 Java 基础、想看看完整全栈项目怎么组织代码的开发者。拿到手先不要急着改功能,把数据库表和请求链路理清楚,后续所有改造都会顺很多。

2. 数据库表设计与订单状态机:先把业务模型拆清楚

2.1 技术选型:为什么是 Spring Boot + MyBatis-Plus + 微信原生小程序

这个量级的项目用微信原生小程序加 Spring Boot 的组合是最稳妥的。微信原生开发工具打开即编译,不需要像 uniapp 那样先配 HBuilderX 再做条件编译,在毕设答辩现场出问题的概率更低。后端 Spring Boot 生态成熟,MyBatis-Plus 提供分页查询和代码生成,能省掉大量重复的 SQL 编写工作。数据库用 MySQL 5.7 或 8.0 都可以,JDK 建议用 1.8 或 11,这套源码按本机编译环境打包,下载后先检查 JDK 和 Maven 版本是否一致再启动,能避开大部分「编译报错」的问题。

为什么不建议在这个项目里引入 Redis 做缓存?单体应用加缓存会引入缓存与数据库一致性维护的成本,毕设答辩时反而容易被追问「缓存穿透怎么办」。先用单库单表把业务跑通,把 JWT 鉴权和订单状态机这两个核心点讲清楚,已经足够支撑一篇合格的毕业设计论文。

2.2 核心表结构:用户、商品、订单、收藏、轮播图

打开数据库脚本后,重点关注前五张表:用户表、商品表、订单表、收藏表、轮播图表。商品表是整个业务的核心,字段设计直接影响买家端筛选和卖家端管理。核心建表语句如下:

CREATE TABLE `goods` ( `id` INT NOT NULL AUTO_INCREMENT, `user_id` INT NOT NULL COMMENT '卖家ID,关联user表', `title` VARCHAR(100) NOT NULL COMMENT '商品标题', `description` TEXT COMMENT '商品描述', `price` DECIMAL(10,2) NOT NULL COMMENT '售价', `original_price` DECIMAL(10,2) DEFAULT NULL COMMENT '原价,用于显示折扣', `cover_image` VARCHAR(255) DEFAULT NULL COMMENT '封面图URL', `images` TEXT COMMENT '多图URL,JSON数组格式存储', `status` TINYINT NOT NULL DEFAULT 0 COMMENT '0在售 1已下架 2已售出', `view_count` INT NOT NULL DEFAULT 0 COMMENT '浏览数,列表页直接展示', `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `idx_user_id` (`user_id`), KEY `idx_status_create` (`status`, `create_time`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='二手商品表';

价格字段必须用 DECIMAL 而不是 FLOAT。float 在比较运算时存在精度误差,订单金额出问题在答辩时很难解释。images 字段用 JSON 数组字符串存储多张图片路径,比如["/uploads/1.jpg","/uploads/2.jpg"],查询出来后在 Java 里用 Fastjson 转成 List 即可,不需要单独建一张商品图片表——毕设级别的图片数量用这种方式更简单。

订单表字段需要同时冗余商品标题、商品封面和交易价格,即使卖家后来删除了商品,订单详情页依然能正常显示。如果通过关联查询去拿商品信息,商品被删后订单页就空了。

表名职责关键约束与索引
user用户信息,含 openid、昵称、头像openid 加唯一索引,登录时按 openid 查
goods商品信息,含价格、图片、状态user_id 索引,status 与 create_time 组合索引
orders交易订单,含买卖双方、商品快照order_no 唯一索引,buyer_id 与 seller_id 分别建索引
favorite收藏关系,用户与商品的关联user_id + goods_id 联合唯一索引
banner首页轮播图status 字段控制是否展示

收藏表加联合唯一索引是有意义的,能防止用户对同一商品重复收藏。插入时用INSERT IGNORE或先查后插都可以,前者性能更好且代码更少。用户表不在登录时写入手机号,而是在用户主动填写个人资料时更新,避免微信授权弹窗过多导致注册流失。

2.3 订单状态流转:从「待付款」到「已完成」

订单状态是这个项目里最有含金量的设计。毕设场景不接入真实微信支付,所以付款动作通常是模拟的,但状态机本身要完整。定义如下状态:

public enum OrderStatus { PENDING_PAYMENT(0, "待付款"), PENDING_DELIVERY(1, "待发货"), PENDING_RECEIPT(2, "待收货"), COMPLETED(3, "已完成"), CANCELLED(4, "已取消"); private final int code; private final String desc; // 构造方法省略 }

流转规则是:买家下单创建订单,初始状态为待付款;买家点击「模拟支付」后变为待发货;卖家发货后变为待收货;买家确认收货后变为已完成。买家或卖家在待付款阶段可以取消订单,状态变为已取消。待发货之后买家不能单方面取消,必须走「申请退款」流程——这个边界条件在答辩时常被问到,代码里要处理。

防止商品被重复下单是另一个关键点。下单时不能只查商品状态,要用条件更新原子地完成「检查并修改」:

UPDATE goods SET status = 2 WHERE id = #{goodsId} AND status = 0

这条 SQL 影响行数为 1 说明抢购成功,为 0 说明商品已被买走或下架。用 UPDATE 的行数作为判定依据,避免了并发场景下的竞态条件,这是比先 SELECT 再 UPDATE 更规范的做法。

3. 后端接口:登录鉴权、商品发布与订单流程的 Java 实现

3.1 微信登录 code2Session 换取 openid 并签发 JWT

后端登录接口的逻辑是:小程序端调用wx.login()拿到临时 code,传给后端,后端用 code 去微信服务器换 openid 和 session_key。不要在客户端自行解析用户信息作为身份凭证,openid 才是用户在微信体系内的唯一标识,客户端传过来的任何 ID 都不可信。核心代码:

@RestController @RequestMapping("/api/auth") public class AuthController { @Resource private UserMapper userMapper; @Resource private JwtUtil jwtUtil; @PostMapping("/login") public Result login(@RequestBody LoginRequest request) { // 1. 用 code 换取 openid String url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + appId + "&secret=" + appSecret + "&js_code=" + request.getCode() + "&grant_type=authorization_code"; String response = HttpUtil.get(url); JSONObject json = JSON.parseObject(response); String openid = json.getString("openid"); // 2. 根据 openid 查找用户,不存在则注册 User user = userMapper.selectByOpenid(openid); if (user == null) { user = new User(); user.setOpenid(openid); user.setNickname("微信用户" + openid.substring(0, 6)); userMapper.insert(user); } // 3. 签发 JWT token String token = jwtUtil.generateToken(user.getId()); return Result.success(token); } }

逻辑说明:第一步用HttpUtil.get调用微信接口,实际项目中建议把 appId 和 appSecret 放到application.yml配置里,不要硬编码在 Java 类中。第二步查不到 openid 就自动注册新用户,这里不用先查再插是因为 openid 有唯一索引兜底,重复插入会抛异常,但正常流程下同一用户不会同时发起两次登录。第三步签发的 token 里只放 userId,不放 openid 和头像昵称,保持 token 体积小。

前端拿到 token 后存入wx.setStorageSync,后续所有请求在 header 里带Authorization: Bearer <token>。后端用拦截器统一校验 token 并解析出 userId,写入 ThreadLocal 供 Controller 直接使用。这样每个接口的代码里不需要重复写解析逻辑,拦截器代码如下:

public class JwtInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { String auth = request.getHeader("Authorization"); if (auth == null || !auth.startsWith("Bearer ")) { throw new BusinessException(401, "未登录"); } String token = auth.substring(7); Integer userId = jwtUtil.parseToken(token); if (userId == null) { throw new BusinessException(401, "登录已过期"); } UserContext.set(userId); return true; } }

拦截器要注册到 WebMvcConfigurer 中,并配置excludePathPatterns放行/api/auth/login。注意放行路径要写在排除列表里,否则登录接口也会被拦,导致小程序首次登录请求直接 401。

3.2 发布商品接口:参数校验与图片路径处理

发布商品是卖家端的核心操作。前端通过wx.uploadFile上传图片到后端,后端返回图片 URL,商品文字信息走 JSON 提交。图片上传和商品发布分开处理,上传失败时不会产生「商品信息已保存但图片缺失」的半成品数据。发布接口实现:

@PostMapping("/goods") public Result publish(@RequestBody Goods goods) { // 1. 基础参数校验 if (goods.getPrice() == null || goods.getPrice().compareTo(BigDecimal.ZERO) <= 0) { return Result.error("价格必须大于0"); } if (StringUtils.isBlank(goods.getTitle()) || goods.getTitle().length() > 50) { return Result.error("标题不能为空且不超过50字"); } // 2. 补充卖家信息 Integer userId = UserContext.get(); goods.setUserId(userId); goods.setStatus(0); // 3. 保存 goodsMapper.insert(goods); return Result.success(goods.getId()); }

参数说明:价格为 0 或负数直接拒绝,标题长度限制 50 字,这两个校验能挡住大部分异常请求。UserContext.get()从拦截器写入的 ThreadLocal 取当前登录用户,不需要前端传 userId,防止用户伪造他人身份发布商品。图片列表在Goods实体中是 String 类型,前端提交前把图片路径数组JSON.stringify后再放进请求体。

发布成功后在售列表的 SQL 查询要注意索引利用率。列表页筛选条件按 status 过滤在售商品,按 create_time 倒序排列,之前在 goods 表建的idx_status_create组合索引正好命中这两个字段。分页用 MyBatis-Plus 的Page对象:

Page<Goods> page = new Page<>(current, size, true); LambdaQueryWrapper<Goods> wrapper = new LambdaQueryWrapper<>(); wrapper.eq(Goods::getStatus, 0) .orderByDesc(Goods::getCreateTime); goodsMapper.selectPage(page, wrapper);

current是页码,size是每页条数,小程序端列表触底时current + 1继续请求。true表示自动查询总条数,用于前端判断是否还有更多数据可以加载。

3.3 下单与状态更新:事务控制

创建订单接口需要同时操作商品表和订单表,必须加@Transactional保证原子性。核心逻辑是:先条件更新商品状态,影响行数为 1 才创建订单,否则返回「商品已被购买」。创建订单时把商品标题、封面、价格冗余到订单表,生成唯一的订单号,规则可以用时间戳加用户 ID:

@Transactional(rollbackFor = Exception.class) public Order createOrder(Integer goodsId) { Integer buyerId = UserContext.get(); // 1. 原子更新商品状态,防止并发重复下单 Goods goods = goodsMapper.selectById(goodsId); if (goods == null || goods.getStatus() != 0) { throw new BusinessException("商品不存在或已下架"); } int rows = goodsMapper.updateStatus(goodsId, 2, 0); if (rows == 0) { throw new BusinessException("手慢了,商品已被别人买走"); } // 2. 创建订单,冗余商品快照 Order order = new Order(); order.setOrderNo(generateOrderNo(buyerId, goodsId)); order.setGoodsId(goodsId); order.setBuyerId(buyerId); order.setSellerId(goods.getUserId()); order.setTitle(goods.getTitle()); order.setCoverImage(goods.getCoverImage()); order.setPrice(goods.getPrice()); order.setStatus(0); // 待付款 orderMapper.insert(order); return order; }

部分代码省略了@Transactional注解的位置——注解要加在 public 方法上,且不能同类内自调用,否则事务不生效。updateStatus对应之前那条件更新 SQL,第三个参数0是期望的当前状态。可以加一个兜底:如果goods.getStatus() != 0提前做一次业务校验,避免无意义的 SQL 执行。

事务的一个思维陷阱是:很多人以为加@Transactional就能保证一切,但这个场景真正保证不超卖的是那条UPDATE ... WHERE status = 0条件更新语句,事务只是保证「扣库存」和「建订单」要么都成功要么都失败,两者职责不同。

4. 小程序端:token 管理、商品列表渲染与订单双视角

4.1 wx.request 封装与登录态生命周期

小程序端最核心的封装是一个统一的请求函数。所有页面不再直接调用wx.request,而是走这个封装,统一处理 token 注入、业务错误提示和登录过期跳转。代码如下:

const request = (url, method = 'GET', data = {}) => { return new Promise((resolve, reject) => { const token = wx.getStorageSync('token') wx.request({ url: `http://localhost:8080${url}`, method, data, header: { 'Content-Type': 'application/json', 'Authorization': token ? `Bearer ${token}` : '' }, success: (res) => { if (res.statusCode === 401) { // token 过期,清空并回登录页 wx.removeStorageSync('token') wx.navigateTo({ url: '/pages/login/login' }) reject(new Error('登录已过期')) return } if (res.data.code !== 200) { wx.showToast({ title: res.data.msg, icon: 'none' }) reject(new Error(res.data.msg)) return } resolve(res.data) }, fail: (err) => { wx.showToast({ title: '网络请求失败', icon: 'none' }) reject(err) } }) }) }

说明:baseURL 如果写死localhost会导致真机调试无法访问,因为真机上 localhost 指向手机自身。开发阶段用微信开发者工具的「不校验合法域名」选项可以绕过域名限制,真机调试时把localhost换成电脑的局域网 IP,例如http://192.168.1.100:8080,前后端在同一 Wi-Fi 下即可联调。

401 处理很关键。后端 token 过期返回 401 时,前端不能只在控制台打印,要清空本地 token 并跳转登录页。这里有个容易被忽略的细节:多个请求同时返回 401 时会触发多次navigateTo跳转,导致页面栈混乱。常见做法是用一个布尔变量控制跳转只执行一次,或者在跳转前检查当前页面是否已经是登录页。

4.2 首页商品列表与触底分页加载

首页列表的逻辑是:页面加载时请求第一页数据,下拉刷新时重置页码重新加载,触底时页码加一继续请求。代码:

Page({ data: { goodsList: [], page: 1, pageSize: 10, hasMore: true, loading: false }, onLoad() { this.loadGoods() }, onPullDownRefresh() { this.setData({ page: 1, hasMore: true }) this.loadGoods(() => wx.stopPullDownRefresh()) }, onReachBottom() { if (this.data.hasMore && !this.data.loading) { this.setData({ page: this.data.page + 1 }) this.loadGoods() } }, loadGoods(callback) { if (this.data.loading) return this.setData({ loading: true }) request(`/api/goods?current=${this.data.page}&size=${this.data.pageSize}`) .then((result) => { const list = result.data.records const newList = this.data.page === 1 ? list : this.data.goodsList.concat(list) this.setData({ goodsList: newList, hasMore: result.data.pages > this.data.page }) }) .finally(() => { this.setData({ loading: false }) if (callback) callback() }) } })

逻辑说明:请求参数current对应后端 MyBatis-Plus 的页码,size对应每页条数。pages是后端返回的总页数,当前页小于总页数时hasMore为 true,页面的onReachBottom才会继续触发请求。loading标记防止触底事件在请求未返回时重复触发多次请求,这个在高频滚动时很容易踩坑。

图片懒加载方面,image标签设置lazy-load属性,用户滚动到可视区域才加载图片。商品卡片组件里价格用红色加粗展示,原价用灰色删除线,点击卡片跳转详情页时带上id参数:

const goDetail = (e) => { const id = e.currentTarget.dataset.id wx.navigateTo({ url: `/pages/goods/detail?id=${id}` }) }

4.3 「我买到的」与「我发布的」订单双视角管理

订单模块是这个项目里页面结构最有特点的地方。同一个订单列表页,通过 URL 参数区分是买家视角还是卖家视角。买家看到的是「我买到的」,卖家看到的是「我发布的(含卖出记录)」。后端接口设计为同一个接口,根据是否传入 sellerId 走不同查询条件:

@GetMapping("/orders") public Result listOrders(Integer buyerId, Integer sellerId, Integer current, Integer size) { LambdaQueryWrapper<Order> wrapper = new LambdaQueryWrapper<>(); if (buyerId != null) { wrapper.eq(Order::getBuyerId, buyerId); } if (sellerId != null) { wrapper.eq(Order::getSellerId, sellerId); } wrapper.orderByDesc(Order::getCreateTime); Page<Order> page = orderMapper.selectPage(new Page<>(current, size), wrapper); return Result.success(page); }

前端页面通过wx.navigateTo跳转时传type=buytype=sell,页面获取到类型后决定调用哪个参数。订单卡片组件复用同一个模板,根据订单状态字段显示不同的操作按钮:

  • 待付款:买家看到「去支付」「取消订单」
  • 待发货:买家看到「提醒发货」,卖家看到「确认发货」
  • 待收货:买家看到「确认收货」
  • 已完成:买家看到「查看评价」,卖家看到「查看评价」

每个订单项都带一个倒计时或状态高亮,待付款订单超过 30 分钟自动关闭。这个功能在毕设里可以用「前端布局时判断创建时间」实现,不用专门写定时任务——真正定时任务涉及分布式锁,工作量超出毕设范围,答辩时能说清楚边界就行。

5. 本地复现与联调验证:把「能跑」变成「可验证」

5.1 启动顺序与配置核对

整套项目本地运行遵循严格的启动顺序:先导入数据库,再启动后端,最后打开微信开发者工具。顺序反了会出现「前端请求失败」「数据库连接池启动报错」这类难以定位的问题。数据库导入方式:

mysql -u root -p -e "CREATE DATABASE second_hand DEFAULT CHARACTER SET utf8mb4" mysql -u root -p second_hand < second_hand.sql

导入后打开本地数据库工具(Navicat 或其他),核对表数量和表名前缀是否与后端实体类一致。常见的坑是 SQL 文件里表名是goods,实体类注解写@TableName("goods")能对上,但如果 SQL 导入时带上了CREATE DATABASE语句导致导到了错误的库,后端一样能起来但列表全是空的。检查数据源配置:

spring: datasource: url: jdbc:mysql://localhost:3306/second_hand?useUnicode=true&characterEncoding=utf8mb4&serverTimezone=Asia/Shanghai username: root password: 123456

characterEncoding=utf8mb4参数必须有,否则中文商品标题在数据库中会变成乱码,前端展示出「???」时先查这里。后端起不来时看控制台报错,优先排查端口被占用和数据库账号密码不匹配。端口占用在本地很常见,换端口或杀掉占用进程即可,Java 工程改server.port在 application.yml 里改。

5.2 用开发者工具 Network 面板验证一条完整请求链路

验活不只看页面有没有渲染出来,要看请求链路上每一步是否真的发生了。微信开发者工具自带的 Network 面板能看小程序发出的所有请求,比后端打印日志更直接。这里给一个可执行的下单链路验证步骤:

  1. 在开发者工具点击「登录」,Network 面板出现POST /api/auth/login,点开看请求体里有code,响应里有token,同时 Storage 面板里能看到本地存上了同一个 token。
  2. 点击「发布」按钮,填入商品信息提交,Network 面板出现POST /api/goods,请求头里Authorization字段前缀是Bearer,响应返回新商品 ID。
  3. 打开 Navicat 执行SELECT id, title, status FROM goods ORDER BY id DESC LIMIT 5,能看到刚发布的商品记录,status 为 0。
  4. 用另一个账号(或退出重新登录)浏览该商品并下单,执行SELECT * FROM orders WHERE goods_id = 刚才的ID,确认买家 ID、卖家 ID、价格三个字段都正确。

这套验证能同时确认后端接口、数据库脚本、前端传参三块没有问题。如果某一步断掉,错误会指向明确的位置:请求没发出是前端问题,请求发出但报 500 是后端代码或 SQL 问题,请求 200 但数据库没数据是事务没提交或提交后回滚了。

5.3 真机调试与抓包对比:开发者工具正常但手机不行的排查思路

开发者工具里接口全部正常,但一上真机就请求失败,这个现象在毕设阶段出现频率出奇地高。原因基本都是「localhost」指向了自己:开发者工具里 localhost 是电脑,真机上 localhost 是手机。把request封装的 baseURL 换成电脑局域网 IP,比如http://192.168.31.45:8080,然后手机和电脑连同一个 Wi-Fi。

换完 IP 还不行,就用 Charles 对手机流量做代理抓包,对比开发者工具和真机发出的请求报文差异,重点看 Host 字段和实际连接的服务地址。真机调试时可以额外开一个后端日志终端窗口,观察请求是否真的到了服务端——如果日志没打印,说明请求被手机系统或网络环境拦截,问题在链路层面,不在项目代码里。按「清微信缓存、重启微信、确认后端启动参数」三个动作再走一遍,大多数环境类问题能直接定位到原因。微信开发者工具的「真机调试」功能配合 Network 面板,是定位这类前后端联调问题最高效的方式。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/14 14:25:31

开源摄影后期 darktable 入门:RAW 修图工作流与批量处理技巧

开源摄影后期 darktable 入门&#xff1a;RAW 修图工作流与批量处理技巧 拍 RAW 格式的摄影爱好者绕不开后期&#xff0c;而 darktable 是这个领域最成熟的开源答案&#xff08;GPL-3.0&#xff09;&#xff1a;RAW 解析、非破坏性编辑、镜头校正、降噪调色全内置&#xff0c;被…

作者头像 李华
网站建设 2026/9/14 14:24:55

Zookeeper在微服务中的服务注册与发现实践

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

作者头像 李华
网站建设 2026/9/14 14:24:20

基于Python和OpenCV的虹膜识别签到系统设计与实现

简介&#xff1a;这是一份面向高校计算机相关专业学生的毕业设计资源&#xff0c;基于虹膜特征识别实现简易签到系统&#xff0c;适合用作毕业设计、课程设计或项目初期演示。资源包含完整Python源码、项目部署说明和详细代码注释&#xff0c;涵盖虹膜采集、内圆与外圆检测、区…

作者头像 李华
网站建设 2026/9/14 14:23:53

MATLAB红眼消除实战:HSV阈值与形态学处理全解析

简介&#xff1a;面向图像处理初学者与MATLAB开发者&#xff0c;这份资源提供了一套完整可运行的自动去红眼程序&#xff0c;专门解决闪光灯拍摄下人像照片出现红眼的问题。压缩包共4个文件&#xff0c;包含3个M脚本与1张BMP示例图&#xff1a;redeye.m为主程序&#xff0c;rgb…

作者头像 李华
网站建设 2026/9/14 14:23:31

GRU模型交付物RAR压缩包管理:从解压到加载的完整实践

简介&#xff1a;GRU&#xff08;Gated Recurrent Unit&#xff09;是循环神经网络的重要变体&#xff0c;由门控机制解决长期依赖与梯度消失问题&#xff0c;在机器翻译、文本生成、情感分析等自然语言处理任务中应用广泛。这份资源提供GRU的C语言实现源码&#xff0c;面向希望…

作者头像 李华
网站建设 2026/9/14 14:22:06

ResNet每一层后接入CBAM:遥感土地利用分类的注意力机制实践

简介&#xff1a;这份资源是一套面向遥感卫星土地利用场景的 ResNet 系列图像分类改进实战代码包&#xff0c;适合有一定深度学习基础、希望将注意力机制融入主干网络做对比实验的研究者或开发者。工程完整覆盖 resnet18/34/50/101/152 五个系列&#xff0c;支持迁移学习或仅训…

作者头像 李华