简介:这是一套面向Java毕业设计与课程大作业场景的微信小程序完整项目源码,以“茉莉炒股”为主题,涵盖服务端、小程序端与爬虫端三大部分,适合需要一套可参考、可拆解的全栈案例来练手或完成课题的学生与开发者。压缩包共248个文件,约201KB,其中130个Java文件承载后端业务逻辑与消息处理,27个XML与9个YML负责配置与依赖管理,13个Python文件对应爬虫采集模块,另有14个WXSS、9个WXML与11个JS构成小程序页面与交互,辅以PNG图片、JSON数据及Git忽略配置等。已有190人学习关注。项目结构分层清晰,服务端包含用户、通知与消息交换等控制器与处理器,爬虫端基于Scrapy框架组织采集流程,小程序端则提供完整页面样式与逻辑,便于读者理解前后端联调、数据抓取与展示的完整链路,也可作为二次开发与功能扩展的起点。
1. 三端源码拆包:一份能跑通的「茉莉炒股」小程序到底长什么样
很多做 Java 毕业设计或课程大作业的同学,拿到手的资源要么只有小程序前端,要么后端是个空壳,爬虫端干脆没有。这份「茉莉炒股」源码包不太一样,它把 server 端、小程序端、爬虫端三块都放进来了,解压后能看到scrapy.cfg这种爬虫工程标志文件,也能看到UserServerController.java、SpiderExchangeMessageHandler.java这类后端控制器和消息处理器,说明它不是一个纯演示壳子,而是有真实数据流转的完整链路。适合谁?适合正在找 Java 课程设计案例源码、需要一套能讲清楚「数据从哪来、怎么存、怎么展示」的微信小程序项目实例的人。它解决的核心问题是:让你不用从零搭架子,直接在一个有爬虫采集、有后端接口、有前端展示的闭环里改需求、写论文、做答辩演示。下面我按实际拆包和复现的顺序,把三端怎么串起来、参数怎么配、哪里容易翻车讲清楚。
2. 爬虫端:Scrapy 工程结构与数据采集链路
2.1 从 scrapy.cfg 看工程组织方式
解压后根目录出现scrapy.cfg,这是 Scrapy 项目的标准入口配置文件,说明爬虫端不是零散脚本,而是一个可部署的爬虫工程。常见做法是把它放在项目根,内容里指定 settings 模块和部署配置。我一般会先确认它指向的 settings 文件路径,因为很多打包资源会把爬虫代码塞进一个子目录,但scrapy.cfg还留在外层,导致直接运行scrapy crawl xxx时报找不到配置。
# scrapy.cfg 典型结构 [settings] default = stock_spider.settings [deploy] project = stock_spider逻辑说明:[settings]段告诉 Scrapy 去哪个模块加载配置,default后面的值必须和实际 Python 包名一致。参数说明:project是部署时用的项目名,本地调试不影响,但如果你要挂到 scrapyd 上就必须对齐。改的时候只动等号右边,别动段名。
2.2 爬虫数据怎么落到后端能读的存储里
项目正文里给了爬虫的通用工作流程:URL 收集、请求网页、解析内容、数据存储、遵守规则、应对反爬。这份源码的爬虫端大概率是按这个链路写的,但打包资源不会把目标网站写死给你看,所以你要自己确认它把数据存哪了。常见做法是存 MySQL 或 SQLite,字段对应股票代码、名称、价格、涨跌幅。你需要在settings.py里找ITEM_PIPELINES和数据库连接串。
# settings.py 中需要重点检查的几项 ITEM_PIPELINES = { 'stock_spider.pipelines.StockSpiderPipeline': 300, } DOWNLOAD_DELAY = 1 # 单位秒,控制访问频率 USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'逻辑说明:ITEM_PIPELINES决定爬到的数据走哪个管道入库,数字 300 是优先级,越小越先执行。DOWNLOAD_DELAY是血泪经验参数,设成 0 很容易被目标站封,设 1 到 2 秒比较稳。USER_AGENT不设的话,很多站点直接返回 403,这是最常见的翻车点。参数怎么改:如果你只是本地跑通,DOWNLOAD_DELAY可以降到 0.5,但别长期这么干。
2.3 反爬应对与 robots.txt 的边界
项目正文明确提到要遵守 robots.txt、限制访问频率和深度、模拟人类访问行为。这份源码里如果有SpiderExchangeMessageHandler.java这种后端消息处理器,说明爬虫抓完数据后可能通过消息队列或 HTTP 接口通知 server 端。你复现时要注意:爬虫端不要对着真实生产站点高频抓,本地跑通逻辑用测试页面或公开数据源就行。常见做法是把目标 URL 抽到配置文件里,方便替换。
提示:爬虫端跑之前先单独执行一次
scrapy parse或scrapy shell,确认选择器能取到值,别直接上crawl,否则报错信息会淹没在日志里。
3. server 端:Java 控制器与消息处理器的职责划分
3.1 UserServerController.java 暴露了哪些接口
UserServerController.java从命名看是用户服务控制器,通常负责登录、注册、用户信息查询、自选股列表这类接口。Spring Boot 项目里,这类控制器会带@RestController和@RequestMapping。你拿到源码后第一件事是找它映射的路径前缀,然后对照小程序端的请求地址,确认两边能对上。
// UserServerController.java 常见结构示意 @RestController @RequestMapping("/api/user") public class UserServerController { @Autowired private UserService userService; @PostMapping("/login") public Result login(@RequestBody LoginDTO dto) { // 校验账号密码,返回 token return userService.login(dto); } }逻辑说明:@RequestMapping("/api/user")是类级别前缀,@PostMapping("/login")是方法级别路径,最终访问地址是/api/user/login。参数说明:@RequestBody表示接收 JSON 体,小程序端wx.request的data要序列化成 JSON,header里content-type设为application/json。如果你改包名或类名,记得同步改小程序端的baseUrl,否则 404 是必然的。
3.2 SpiderExchangeMessageHandler.java 在链路中的位置
这个类名里带SpiderExchange和MessageHandler,大概率是处理爬虫端与 server 端之间数据交换的消息处理器。可能是 WebSocket 消息处理,也可能是消息队列的消费者。它的存在说明这份源码不是「爬虫直接写库、后端直接读库」的简单模式,而是有中间层做数据交换。你复现时要确认它监听的端口或队列名,以及消息格式。
// 消息处理器结构示意 @Component public class SpiderExchangeMessageHandler { @Autowired private StockDataService stockDataService; public void handleMessage(String payload) { // 解析爬虫推送的数据 StockDTO dto = JSON.parseObject(payload, StockDTO.class); stockDataService.saveOrUpdate(dto); } }逻辑说明:handleMessage是入口,payload是爬虫端发来的字符串,通常为 JSON。参数说明:JSON.parseObject的第二个参数是目标类,字段名要和爬虫端输出的 key 一致,大小写敏感。常见坑是爬虫端用下划线命名、Java 端用驼峰,导致解析出来全是 null,解决办法是在 DTO 上加@JSONField(name = "stock_code")这类注解做映射。
3.3 数据库与配置文件的对应关系
server 端要跑起来,必须配数据库。找application.yml或application.properties,确认spring.datasource.url、username、password。这份源码如果爬虫端也写同一个库,那两边表结构必须一致。我一般会先把建表 SQL 找出来执行一遍,再启动后端,否则启动时报Table 'xxx' doesn't exist会浪费很多时间。
| 配置项 | 作用 | 常见值 |
|---|---|---|
| spring.datasource.url | 数据库连接地址 | jdbc:mysql://localhost:3306/stock_db |
| spring.datasource.username | 数据库账号 | root |
| spring.datasource.password | 数据库密码 | 你本地设置的 |
| server.port | 后端服务端口 | 8080 |
注意:如果爬虫端和 server 端不在同一台机器,数据库地址不能写 localhost,要写实际 IP,并且确认防火墙放行。
4. 小程序端:请求封装、页面结构与联调要点
4.1 请求封装与 baseUrl 配置
微信小程序端通常会把wx.request封装一层,统一处理 baseUrl、token、错误提示。这份源码的小程序端你要先找到封装文件,一般在utils/request.js或api/index.js。把 baseUrl 改成你本地 server 端的地址,比如http://127.0.0.1:8080。但注意,微信开发者工具里可以勾选「不校验合法域名」,真机预览时必须用 HTTPS 且域名已备案,这是新手最容易卡住的地方。
// utils/request.js 封装示意 const BASE_URL = 'http://127.0.0.1:8080'; function request(options) { return new Promise((resolve, reject) => { wx.request({ url: BASE_URL + options.url, method: options.method || 'GET', data: options.data || {}, header: { 'content-type': 'application/json' }, success: (res) => { if (res.statusCode === 200) resolve(res.data); else reject(res); }, fail: reject }); }); }逻辑说明:BASE_URL是唯一需要改的地址,所有接口都拼在它后面。参数说明:header里的content-type要和后端@RequestBody匹配,否则后端收不到参数。success里判断statusCode,不要只看res.data,因为 404 时res.data可能是 HTML 错误页,直接解析会报错。
4.2 页面结构与股票列表渲染
小程序端的页面一般在pages目录下,股票列表页会用wx:for渲染数组。你要确认它请求的接口路径和 server 端UserServerController或股票控制器暴露的路径一致。常见做法是列表页onLoad时调接口,拿到数据后setData。如果页面空白,先看控制台有没有报错,再看 Network 里请求是否 200。
// pages/stock/list.js 示意 Page({ data: { stockList: [] }, onLoad() { request({ url: '/api/stock/list' }).then(res => { this.setData({ stockList: res.data }); }).catch(err => { console.error('请求失败', err); }); } });逻辑说明:onLoad是页面生命周期,只执行一次。setData是唯一能更新视图的方法,直接改this.data.stockList不会触发渲染。参数说明:res.data的结构要和后端返回的Result对象对齐,如果后端包了一层{ code, msg, data },这里要取res.data.data。
4.3 三端联调的启动顺序
正确的启动顺序是:先启动数据库,再启动 server 端,然后跑爬虫端灌数据,最后打开小程序端。顺序错了会出现小程序请求超时或列表为空。我一般会先用 Postman 调一次后端接口,确认后端通了,再开小程序。如果后端接口返回 500,看后端控制台堆栈;如果返回 401,检查 token 有没有带。
提示:微信开发者工具的「不校验合法域名」只在开发阶段有效,答辩演示时如果老师让你用真机,提前准备好 HTTPS 环境,别到现场才发现请求被拦。
5. 避坑与排查:三端联调中最容易翻车的五个点
5.1 现象:爬虫跑完数据库没数据
原因:ITEM_PIPELINES没启用,或者管道里数据库连接失败但异常被吞了。解决:在settings.py里确认管道已注册,并在管道process_item里加日志,把open_spider和close_spider也打上,看看到底走到哪一步。
5.2 现象:小程序请求后端返回 404
原因:baseUrl 拼出来的路径和后端@RequestMapping不一致,常见的是多了或少了/api前缀。解决:把小程序请求的完整 URL 和后端控制器注解逐字对比,包括大小写。用浏览器直接访问后端接口,能通再查小程序。
5.3 现象:后端启动报数据库连接失败
原因:application.yml里的账号密码不对,或者 MySQL 没启动,或者时区参数没加。解决:先命令行mysql -u root -p能登进去,再检查配置。连接串后面加?useSSL=false&serverTimezone=Asia/Shanghai,这两个参数不加经常出玄学问题。
5.4 现象:爬虫被目标站封 IP
原因:DOWNLOAD_DELAY设太小,或者USER_AGENT没设,或者并发数太高。解决:把DOWNLOAD_DELAY调到 2 秒以上,CONCURRENT_REQUESTS降到 1,加上AUTOTHROTTLE_ENABLED = True。本地复现尽量用测试数据,别对着真实站点猛抓。
5.5 现象:消息处理器收不到爬虫数据
原因:SpiderExchangeMessageHandler监听的端口或队列名和爬虫端发送的不一致,或者消息格式对不上。解决:在handleMessage第一行打日志,把payload原样输出,确认爬虫端到底发没发、发的是什么。如果 payload 是空,查爬虫端的发送逻辑;如果有内容但解析失败,查字段映射。
6. 进阶用法:把三端拆成可独立演示的模块
这套源码最大的价值不是直接跑起来,而是你可以按答辩或论文的需要,把它拆成三个独立可讲的模块。爬虫端单独跑,展示数据采集流程;server 端单独跑,用 Postman 展示接口;小程序端单独跑,展示前端交互。这样即使某一端现场出问题,另外两端还能撑住场面。
具体做法是:给爬虫端加一个--output参数,把数据同时写一份 JSON 文件,这样不依赖数据库也能演示。server 端加一个mockprofile,用内存数据返回,不依赖 MySQL。小程序端加一个开关,在request.js里判断如果USE_MOCK为 true,直接返回本地 JSON。
// request.js 增加 mock 开关 const USE_MOCK = false; function request(options) { if (USE_MOCK) { return Promise.resolve(require('../mock' + options.url + '.json')); } // 原有请求逻辑 }逻辑说明:USE_MOCK为 true 时直接读本地 mock 文件,路径按接口名组织。参数说明:mock 文件的目录结构要和接口路径对应,比如/api/stock/list对应mock/api/stock/list.json。这样你在没有后端的环境下也能演示小程序页面。
验证方法:先关掉 MySQL 和后端,把USE_MOCK设为 true,重新编译小程序,看列表页能不能渲染出数据。能渲染说明前端逻辑没问题,问题只可能在后端或数据库。这个排查习惯我每次联调都强制走一遍,能省掉大量来回猜的时间。希望帮到你。
本文还有配套的精品资源,点击获取