第40次 · 资讯发布与素材关联
第40次 · 资讯发布与素材关联
第1/7页 · 先知道今天要做什么
先从一个熟悉的场景想一想:这节课的代码在帮我们解决什么问题?
先来一个生活里的画面
写校报不只是填标题:还有栏目、正文、图片和可阅读页面。像老师整理公告栏,文章卡、图片卡和最终展示页要互相对应。本课用一条自己的通知,沿 submitNews 的真实流程逐项核对。
你已经会的知识
用前面课的类、方法、参数和返回值来读本次例子。遇到新名字先看下一页;不用一开始读完整个工程。
为什么要学这一课
在同一完成工程中发布自己的通知。先看NewsDto实际字段与正文格式,再分别验证保存、素材关联和页面生成。
今天完成的事情
把一条通知换成自己的标题,在练习环境发布并核对记录。
这课在哪里做
| 要找什么 | 真实位置 |
|---|---|
| 下载后打开 | 04_源代码/chapter14/heima-leadnews/pom.xml |
| 本次先读 | src/main/java/com/itheima/service/impl/NewsServiceImpl.java |
| 运行或请求入口 | src/main/java/com/itheima/LeadNewsApplication.java |
看到什么才算完成一小步
- 教师验证过的完整发布请求:核对业务响应,再用唯一标题查真实资讯id。
- 素材或存储步骤失败:分别检查数据库和外部文件,数据库事务不自动撤回MinIO文件。
- 输入草稿状态:先查实际保存status与阅读结果,设计意图不等于原例已实现的行为。
阅读顺序
第2页查新词,第3页读这一份工程的代码,第4页先找文件和入口。第5页在 IDEA 按步骤修改;第6页对照效果和问题;第7页用自己的话复盘。
操作位置
下载、解压、打开、修改和运行在本机 IDEA;教学网站用于看讲义、下载资源、保存草稿和提交。请教师先准备本章练习数据库与测试账号,以及 application.yml 中需要的对象存储等服务。数据库初始化脚本在解压包的 05_课程素材/chapter14/sql脚本/leadnews.sql。仅在本地或教师指定练习环境操作;记录配置键与是否连通,提交材料中去掉密码和登录token。原包含完成工程和“初始工程”,本页操作的是 04_源代码 下的完成工程。
来源:第14章 综合实战-黑马头条 · 课件第66、71、73页(课件页码,不是教材印刷页码)
第2/7页 · 把新词说清楚
先把本课用得到的名字认清;看到名字时回到真实文件定位。
新词与本课含义
| 名字 | 在这个例子里是什么意思 |
|---|---|
| NewsDto | 接收 title、channelId、content、type、status、images 等字段。 |
| content | 本例是 JSON 数组的字符串,不能直接写纯文本。 |
| 素材关联 | 数据库记录资讯与已上传素材的联系。 |
| 事务范围 | 数据库回滚不自动撤回 MinIO 文件;还要分别检查。 |
把生活画面对应到教材代码
| 生活里的角色或动作 | 本课真正的代码 |
|---|---|
| 文章申请单 | NewsDto 的 title/channelId/content 等 |
| 把图片与文章挂在一起 | 素材关联保存 |
| 公告栏上可读的成品 | 生成页面并取得实际 staticUrl |
类比怎样用
先借这个画面记住分工,再回到本课文件逐项定位。生活里的角色只是类比,程序的实际行为以教材代码、配置和本机观察为准。
先对照文件名
src/main/java/com/itheima/service/impl/NewsServiceImpl.java 是本次主阅读文件,位置在 04_源代码/chapter14/heima-leadnews 内。目录、类、方法和对象登记名是四种不同名字,不要随意互相替换。
读代码时只问三个问题
- 它从哪里得到输入:方法参数、XML、请求还是数据库?
- 它调用哪个具体方法:到同一个工程中查这个名字。
- 结果从哪里看:Run 控制台、请求响应还是数据库?本课第1页检查表给出位置。
先不用背术语
先能找到文件、指出一行的动作并描述输出。术语用来给已经看过的动作命名,不用它替代操作过程。
来源:第14章 综合实战-黑马头条 · 课件第66、71、73页(课件页码,不是教材印刷页码)
第3/7页 · 先看一个小例子
下面的教材片段来自本课下载项目;新增练习代码会另外标明。不要把节选直接当完整文件覆盖。
先猜一猜,读完代码再回答
返回成功提示,就代表数据库、图片关系和页面都已逐项检查了吗?
三个具体例子:先给输入,再想结果
| 输入或改动 | 应该观察什么 | 为什么 |
|---|---|---|
| title 填自己的唯一通知名 | 列表可用该标题定位真实记录 | 接口不一定直接返回新 id。 |
| content 用 JSON 数组字符串 | 按本例正文结构供后续解析 | 纯文本与数组文本结构不同。 |
| 请求声称草稿 | 先核对实际保存状态和阅读结果 | 原例状态设置与比较有边界,不能只看输入值断言隐藏。 |
把例子用起来
这些是课堂推演,帮你看清“只改一个输入,结果怎样变化”。涉及数据库的编号、余额和数量是示意,动手时换成教师提供的真实练习数据;在 IDEA 写下自己的预测,再运行核对。
打开这一份文件
04_源代码/chapter14/heima-leadnews/src/main/java/com/itheima/service/impl/NewsServiceImpl.java。在 IDEA 双击打开;以下只是它的第59—90行,完整类、import 和配置仍保留在项目中。
NewsServiceImpl.java:先读这一段
04_源代码/chapter14/heima-leadnews/src/main/java/com/itheima/service/impl/NewsServiceImpl.java 第59—90行
public ResponseResult submitNews(NewsDto dto) {
//0.条件判断
if(dto == null || dto.getContent() == null){
return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
}
//1.保存或修改文章
News news = new News();
//属性拷贝 属性名词和类型相同才能拷贝
BeanUtils.copyProperties(dto,news);
//封面图片 list---> string
if(dto.getImages() != null && dto.getImages().size() > 0){
String imageStr = StringUtils.join(dto.getImages(), ",");
news.setImages(imageStr);
}
//如果当前封面类型为自动 -1
if(dto.getType().equals(WemediaConstants.WM_NEWS_TYPE_AUTO)){
news.setType(null);
}
saveOrUpdateNews(news);
//2.判断是否为草稿 如果为草稿结束当前方法
if(dto.getStatus().equals(0)){
return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
}
//3.不是草稿,保存文章内容图片与素材的关系
//获取到文章内容中的图片信息
List<String> materials = ectractUrlInfo(dto.getContent());
saveRelativeInfoForContent(materials,news.getId());
//4.不是草稿,保存文章封面图片与素材的关系,如果当前布局是自动,需要匹配封面图片
saveRelativeInfoForCover(dto,news,materials);
//异步调用 生成静态文件上传到MinIO中
newsFreeMarkerService.buildArticleToMinIO(news,news.getContent());
return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
先看第1个动作
submitNews先检查dto/content,复制属性到News。
先看第2个动作
content是JSON数组字符串;普通一段文字不符合后面的JSON.parseArray读取。
先看第3个动作
saveOrUpdateNews保存数据,saveRelativeInfo处理素材,buildArticleToMinIO生成页面。
先看第4个动作
教材将保存记录status设为9,且草稿判断要结合实际类型与分支;本章不要先承诺草稿请求一定不会公开。
先读再动手
先在 IDEA 找到以上几行,逐项说出它们做什么。第5页会明确告诉你改哪一行、加到哪个大括号里、运行哪个入口;今天只改那几处。
来源:第14章 综合实战-黑马头条 · 课件第66、71、73页(课件页码,不是教材印刷页码)
第4/7页 · 一步一步做出来
先认清项目、文件和运行入口;保持同一个例子,再去第5页做个人修改。
本课项目目录
04_源代码/chapter14/heima-leadnews/pom.xml;选择直接包含 pom.xml 和 src 的这一层。
把这条路线讲成一段小故事
- 提交真实 NewsDto
- 保存资讯记录
- 关联素材
- 生成并存储页面,分别核对
先完成打开项目这一步
- 在讲义顶部点“下载代码资源”。等 ZIP 下载完成,在电脑文件管理器找到它,右键选择“全部提取/解压”,先解压成普通文件夹。不要直接在 ZIP 预览窗口中打开 Java 文件。
- 把解压目录复制一份作为自己的本课练习副本,例如 lesson-课次-学号。保留原包不改,后续课需要同章工程时可继续自己的副本,也可从原包重新开始。
- 按本页列出的“本课项目目录”进入到直接含 pom.xml 和 src 的那一层。整个 ZIP 解压目录、04_源代码 外层都不是这次的 Maven 项目根目录。
- 打开 IntelliJ IDEA。欢迎页点 Open(打开);已打开别的项目则点 File → Open。选择本课 pom.xml,出现选项时选 Open as Project(作为项目打开),或直接选它所在目录。已有项目时用 New Window,避免混淆。
- 导入后选择已安装的 JDK17,打开 Maven 面板 Reload All Maven Projects;依赖完成、代码无编译错误后再运行。
沿这些真实文件找代码
| 工程内路径 | 本次作用 |
|---|---|
| src/main/java/com/itheima/LeadNewsApplication.java | 先双击定位,与第5页指定的修改步骤对照;原包已有。 |
| src/main/resources/application.yml | 先双击定位,与第5页指定的修改步骤对照;原包已有。 |
| src/main/java/com/itheima/controller/NewsController.java | 先双击定位,与第5页指定的修改步骤对照;原包已有。 |
| src/main/java/com/itheima/service/impl/NewsServiceImpl.java | 先双击定位,与第5页指定的修改步骤对照;原包已有。 |
| src/main/java/com/itheima/dto/NewsDto.java | 先双击定位,与第5页指定的修改步骤对照;原包已有。 |
不要急着执行
请教师先准备本章练习数据库与测试账号,以及 application.yml 中需要的对象存储等服务。数据库初始化脚本在解压包的 05_课程素材/chapter14/sql脚本/leadnews.sql。仅在本地或教师指定练习环境操作;记录配置键与是否连通,提交材料中去掉密码和登录token。原包含完成工程和“初始工程”,本页操作的是 04_源代码 下的完成工程。
本页先定位,第5页再修改运行
下面说明本课的运行方式,先找到对应按钮。到第5页完成指定配置、新建文件或修改代码后,再按这些步骤执行;还不存在的类或测试方法先不要运行。
本课怎样运行:启动 Spring Boot
- 按本页前置条件完成本地配置,再打开 src/main/java/com/itheima/LeadNewsApplication.java
- 点启动类 main 左侧绿色三角 → Run。看 Run 日志出现 Started 与实际服务端口后再请求;若只有前几行文字或错误堆栈,服务尚未启动。
- 默认用本机 http://localhost:日志显示端口;application.yml 若配置 context-path,要加实际前缀。不要用教学网站172.18.1.33的地址运行下载项目。
- 修改后 Save All,点红色 Stop 停止旧实例,再 Run。不要反复启动多个实例,避免端口冲突。停止以后网页或接口将不可访问,这是正常现象。
本课入口是否需要新增
运行入口已在下载包中;第5页先做必要的配置或改动,再执行这个入口。JUnit 只运行指定方法,避免其它实验一起改数据。
完成修改后检查
| 操作或输入 | 预期观察 |
|---|---|
| 教师验证过的完整发布请求 | 核对业务响应,再用唯一标题查真实资讯id。 |
| 素材或存储步骤失败 | 分别检查数据库和外部文件,数据库事务不自动撤回MinIO文件。 |
| 输入草稿状态 | 先查实际保存status与阅读结果,设计意图不等于原例已实现的行为。 |
记录一遍过程
在第5页按顺序改完,每次 Save All 再运行。写下本次实际入口、输入与结果,和表里的预期逐项对照;第一次未成功就按第6页定位。
来源:第14章 综合实战-黑马头条 · 课件第66、71、73页(课件页码,不是教材印刷页码)
第5/7页 · 换成自己的代码
下载项目后,在电脑的 IntelliJ IDEA 中一步一步修改、运行并检查;网站最后只接收你的作业。
本课在 IDEA 中完成什么
把一条通知换成自己的标题,在练习环境发布并核对记录。
今天就用这个具体版本练习
标题用“班级-姓名-练习通知”,正文写自己两句校园消息。按第5页教师已验证的字段组合发布,再用唯一标题查实际记录。
这七页使用同一个工程例子
前面的代码阅读和下面的练习都使用本课下载项目。表中列出的文件已在包中;写明“新建”的文件由你按步骤在 IDEA 创建。先保留本地正确包名和目录,再按真实文件名提交修改后的文本。
本课项目目录
04_源代码/chapter14/heima-leadnews;选择这一层的 pom.xml。运行入口:src/main/java/com/itheima/LeadNewsApplication.java。# 后面的文字表示要单独运行的测试方法。
第0步:下载、解压并在 IDEA 打开项目
- 在讲义顶部点“下载代码资源”。等 ZIP 下载完成,在电脑文件管理器找到它,右键选择“全部提取/解压”,先解压成普通文件夹。不要直接在 ZIP 预览窗口中打开 Java 文件。
- 把解压目录复制一份作为自己的本课练习副本,例如 lesson-课次-学号。保留原包不改,后续课需要同章工程时可继续自己的副本,也可从原包重新开始。
- 按本页列出的“本课项目目录”进入到直接含 pom.xml 和 src 的那一层。整个 ZIP 解压目录、04_源代码 外层都不是这次的 Maven 项目根目录。
- 打开 IntelliJ IDEA。欢迎页点 Open(打开);已打开别的项目则点 File → Open。选择本课 pom.xml,出现选项时选 Open as Project(作为项目打开),或直接选它所在目录。已有项目时用 New Window,避免混淆。
- 确认导入方式为 Maven。若出现信任提示,先核对这确实是本课程下载的工程再信任。等右下角索引与依赖下载结束,不在下载尚未完成时急着运行。
- 点 File → Project Structure → Project,将 SDK 设为已安装的 JDK 17。列表没有17就按教师安装包先安装,再 Add SDK/JDK 选择实际安装目录;不要把语言级别选17当作JDK已安装。
- 打开 View → Tool Windows → Maven,点击 Reload All Maven Projects(重新加载全部 Maven 项目)。若没有Maven面板,右键本课 pom.xml → Add as Maven Project。红色依赖仍存在时看下载错误,先解决网络/仓库和JDK配置。
- 回到左侧 Project,按本课文件表展开目录并双击文件。Java包可能合并显示为 com.itheima;表中的 src/main/java 表示主代码,src/test/java 表示测试。先核对包名与文件名,再修改。
先找到这些真实文件
| 项目根目录下的路径 | 怎么找到 |
|---|---|
| src/main/java/com/itheima/LeadNewsApplication.java | 在 IDEA 左侧 Project 按路径展开、双击;这份文件已在下载包中。 |
| src/main/resources/application.yml | 在 IDEA 左侧 Project 按路径展开、双击;这份文件已在下载包中。 |
| src/main/java/com/itheima/controller/NewsController.java | 在 IDEA 左侧 Project 按路径展开、双击;这份文件已在下载包中。 |
| src/main/java/com/itheima/service/impl/NewsServiceImpl.java | 在 IDEA 左侧 Project 按路径展开、双击;这份文件已在下载包中。 |
| src/main/java/com/itheima/dto/NewsDto.java | 在 IDEA 左侧 Project 按路径展开、双击;这份文件已在下载包中。 |
第1步前:准备运行依赖
请教师先准备本章练习数据库与测试账号,以及 application.yml 中需要的对象存储等服务。数据库初始化脚本在解压包的 05_课程素材/chapter14/sql脚本/leadnews.sql。仅在本地或教师指定练习环境操作;记录配置键与是否连通,提交材料中去掉密码和登录token。原包含完成工程和“初始工程”,本页操作的是 04_源代码 下的完成工程。 本章从 resources/application.yml 定位数据库与存储配置;SQL脚本导入到教师指定练习库。
本课怎样运行:启动 Spring Boot
- 按本页前置条件完成本地配置,再打开 src/main/java/com/itheima/LeadNewsApplication.java
- 点启动类 main 左侧绿色三角 → Run。看 Run 日志出现 Started 与实际服务端口后再请求;若只有前几行文字或错误堆栈,服务尚未启动。
- 默认用本机 http://localhost:日志显示端口;application.yml 若配置 context-path,要加实际前缀。不要用教学网站172.18.1.33的地址运行下载项目。
- 修改后 Save All,点红色 Stop 停止旧实例,再 Run。不要反复启动多个实例,避免端口冲突。停止以后网页或接口将不可访问,这是正常现象。
发送接口请求:GET 与 POST 分开操作
- GET 请求可在电脑浏览器地址栏输入本机完整地址,结果页面或 JSON 在浏览器看,服务器输出在 IDEA 的 Run/Tomcat 控制台看。
- POST/JSON 请求不能只在地址栏输入。IDEA 支持 HTTP Client 时,在项目根目录 New → File 建 lessonXX.http,按下方示例或教师已验证样例填方法、完整本机地址、Headers,空一行后写 JSON,再点请求左边运行图标。没有 HTTP Client 时,用教师提供的 Postman:New → HTTP Request → 选 POST → 填地址 → Body → raw → JSON → Send。
- 需要登录凭据时在请求 Headers 增加本项目实际使用的 token 键,值用刚登录得到的凭据。文件上传则在 Postman Body 选 form-data、指定键名并将类型由 Text 切到 File。
- 同时记录 HTTP 状态、业务返回码/提示、控制台和实际数据。HTTP200并不保证业务成功;请求示例中的中文占位值必须先替换,端口取启动日志。
第1步:在 IDEA 操作并核对
先用发布者账号登录。打开 NewsDto,找 title、channelId、content、type、status、images;栏目值必须用练习库中真实存在的 id。
第2步:在 IDEA 操作并核对
在 NewsServiceImpl.submitNews 的参数检查之后,加一行 println(“自己的学号:准备发布”),不打印token。保留所有保存、关联和事务代码,保存并重启 Boot。
第3步:在 IDEA 操作并核对
用教师确认过的发布请求做基础,只把 title 改成“自己的班级-练习通知”,正文改成自己的句子。content 是存放 JSON 数组的字符串,不能直接填普通纯文本;下方示例说明格式。type、status、images 使用教师已验证的组合。
第4步:在 IDEA 操作并核对
带发布者token POST /news/submit;记录 HTTP 状态和业务响应码。接口可能只返回成功状态,不返回新id,应在 /news/list 或教学库用唯一标题定位真实id。
第5步:在 IDEA 操作并核对
用 /news/list 查询自己的唯一标题,核对标题、栏目、正文与真实id。再跟到 submitNews 中保存素材关联与生成页面的实际调用,分别记结果;数据库事务不自动回滚对象存储的外部文件。
第6步:在 IDEA 操作并核对
不重复点击发布,不对别人记录改标题。失败时先记录停在参数、登录、素材还是存储步骤,不写“全部正常”。
NewsDto.content 的格式说明;只展示请求中的这一个字段
在 IDEA 中修改;不是网站运行代码
"content": "[{"type":"text","value":"我自己的通知正文"}]"
在本地写练习记录
- 在 IDEA 项目根目录右键 New → File,新建 练习说明.md。填写改过的完整文件路径、方法或行位置,别只写“改了代码”。
- 每组检查写输入/操作、预期、实际结果;文字输出从 Run 控制台抄,接口结果从本机请求抄,数据库结果写实际查到的值。未运行就写“未实测”,并说明卡在哪一步。
- 临时故意写错的对象名、请求或配置按本课要求恢复,Save All。关闭再打开修改文件,确认本地改动保留;最终效果用最后一次重新运行检查。
最后才回网站交作业
本课代码的打开、修改、运行和检查都在本机 IDEA 完成。网站只用来下载讲义/资源和提交结果,不能运行 Java。完成后点讲义顶部“打开代码任务”,将自己在 IDEA 改过的文本文件复制到任务对应文件中;名称与模板不同就“+ 添加文件”填写真实文件名,不为迁就网站模板改错本地包名。保留自己的旧草稿,只提交需要交的源码和练习说明。
保存与提交
添加练习说明.md 并核对本地运行记录 → 保存草稿 → 等显示已保存 → 正式提交并核对新增版本。草稿不计入正式提交次数。项目 ZIP 留在电脑,按教师指定方式另交;不要把 ZIP 二进制内容粘进文本编辑器。提交材料去掉真实密码与登录token。
来源:第14章 综合实战-黑马头条 · 课件第66、71、73页(课件页码,不是教材印刷页码)
第6/7页 · 出错时从哪里查
先保留现象,只检查这一课的同一条调用路线。一次改一处,再重跑确认。
常见现象
| 现象 | 先做什么 |
|---|---|
| IDEA 没有运行三角或依赖报红 | 先查已安装的 JDK17、Maven 导入与下载错误;不要给 DAO/Controller 硬加 main。 |
| 运行结果还是旧的 | 核对右上角入口与当前工程;main/JUnit重新 Run,Web修改后重新编译部署或重启。 |
| 连接或启动失败 | 按第一段关键错误定位数据库、配置、端口或存储;环境未就绪先请教师检查。 |
| 没有预期数据或文字 | 按下面的具体输入表查调用链,分开看控制台、响应和真实数据,不把无报错等同完成。 |
遇到问题,先演一遍这一条路线
提交真实 NewsDto → 保存资讯记录 → 关联素材 → 生成并存储页面,分别核对
用本课的输入复查
| 操作或输入 | 对照实际结果 |
|---|---|
| 教师验证过的完整发布请求 | 核对业务响应,再用唯一标题查真实资讯id。 |
| 素材或存储步骤失败 | 分别检查数据库和外部文件,数据库事务不自动撤回MinIO文件。 |
| 输入草稿状态 | 先查实际保存status与阅读结果,设计意图不等于原例已实现的行为。 |
按本课路线检查
- submitNews先检查dto/content,复制属性到News。
- content是JSON数组字符串;普通一段文字不符合后面的JSON.parseArray读取。
- saveOrUpdateNews保存数据,saveRelativeInfo处理素材,buildArticleToMinIO生成页面。
- 教材将保存记录status设为9,且草稿判断要结合实际类型与分支;本章不要先承诺草稿请求一定不会公开。
需要老师帮忙时交这些
工程名 chapter14/heima-leadnews;运行入口 src/main/java/com/itheima/LeadNewsApplication.java;你改的文件;输入或请求;第一段关键错误;本次预期与实际。截图之外保留错误文字,方便找到具体行。
把预测和实测分开
检查表是预期,不是替你运行过的证明。未在本机执行就写“未实测”;原教材配置或逻辑出现问题时记录原文件与现象,不写“系统判错”。
来源:第14章 综合实战-黑马头条 · 课件第66、71、73页(课件页码,不是教材印刷页码)
第7/7页 · 用自己的话讲一遍
用真实文件和本机结果说明你完成了什么;先说动作,再说术语。
回到第3页:你刚才猜对了吗?
返回成功提示,就代表数据库、图片关系和页面都已逐项检查了吗?
老师带你说清原因
没有。提示是一个证据,还要找到真实资讯 id、核对关联和实际页面。数据库事务也不自动撤回外部存储文件。
请换一个自己的例子
照着本课三个例子的写法,说清“我只改什么、预计哪一处变化、到哪里看结果”。不需要再发明一个陌生项目;用本课同一组文件和入口。
回答本课的两个问题
| 问题 | 参考解释 |
|---|---|
| 正文content是什么类型? | NewsDto里是String,内容按本章约定存放JSON数组文本。 |
| 原例一定实现草稿隐藏了吗? | 不能这样保证;保存状态与类型比较需要实际检查,第6页说明核对位置。 |
按这个顺序讲给同学听
- 我打开的工程是 chapter14/heima-leadnews,本次阅读文件是 src/main/java/com/itheima/service/impl/NewsServiceImpl.java。
- 我实际改了哪一行、加了哪个方法;指着 IDEA 的代码说明。
- 我运行或请求的入口是 src/main/java/com/itheima/LeadNewsApplication.java,输入是什么。
- 我在控制台、响应或数据库看到了什么,与第1页预期有什么差异。
- 我还有哪步没完成,保留了什么错误信息。
交作业前最后检查
文件与练习说明在 IDEA 已保存,正式提交的是自己的最终文本。下载包原样未改的部分标为参考;配置去掉真实密码和token。原有草稿不会被起始文件覆盖,需要时在代码任务查看本次起始文件对照。
课后再做一个小对照
只换本课检查表的一项输入,按同一入口重新执行,补一行预期和实际。没有环境时写明前置条件并停在实际完成的位置;不增加下一章的陌生功能。
来源:第14章 综合实战-黑马头条 · 课件第66、71、73页(课件页码,不是教材印刷页码)