java 黑马头条 day4 自媒体文章发布 自媒体文章列表查询 频道列表展示 自媒体文章-发布、修改、保存草稿 自媒体文章-根据id查询 自媒体文章-删除
1 自媒体文章列表查询
1.1 需求分析
1.2 表结构和实体类
wm_news 自媒体文章表
需求:
如果有文章标题,按照文章标题模糊查询
如果有频道信息,按照频道ID查询
如果有文章状态,按照状态信息进行查询
如果开始时间,结束时间不为空按照时间区间查询
按照登录用户ID去查询
按照创建时间降序
分页查询,返回结果设置host 地址 为图片访问前缀
自媒体文章实体类
package com.heima.model.wemedia.pojos; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; import org.apache.ibatis.type.Alias; import java.io.Serializable; import java.util.Date; /*** <p>* 自媒体图文内容信息表* </p>** @author itheima*/ @Data @TableName("wm_news") public class WmNews implements Serializable { private static final long serialVersionUID = 1L; /*** 主键*/@TableId(value = "id", type = IdType.AUTO)private Integer id; /*** 自媒体用户ID*/@TableField("user_id")private Integer userId; /*** 标题*/@TableField("title")private String title; /*** 图文内容*/@TableField("content")private String content; /*** 文章布局0 无图文章1 单图文章3 多图文章*/@TableField("type")private Short type; /*** 图文频道ID*/@TableField("channel_id")private Integer channelId; @TableField("labels")private String labels; /*** 创建时间*/@TableField("created_time")private Date createdTime; /*** 提交时间*/@TableField("submited_time")private Date submitedTime; /*** 当前状态0 草稿1 提交(待审核)2 审核失败3 人工审核4 人工审核通过8 审核通过(待发布)9 已发布*/@TableField("status")private Short status; /*** 定时发布时间,不定时则为空*/@TableField("publish_time")private Date publishTime; /*** 拒绝理由*/@TableField("reason")private String reason; /*** 发布库文章ID*/@TableField("article_id")private Long articleId; /*** //图片用逗号分隔*/@TableField("images")private String images; @TableField("enable")private Short enable;//状态枚举类***@Alias("WmNewsStatus")public enum Status{NORMAL((short)0),SUBMIT((short)1),FAIL((short)2),ADMIN_AUTH((short)3),ADMIN_SUCCESS((short)4),SUCCESS((short)8),PUBLISHED((short)9);short code;Status(short code){this.code = code;}public short getCode(){return this.code;}} }
2 频道列表展示
2.1需求分析
文章展示列表页面打开的时候,默认自动加载频道列表数据进行展示,就是查询所有频道数据
2.2 接口定义
接口描述: 查询所有频道的数据
接口地址:/api/v1/channel/channels
请求方式:GET
请求数据类型:*
响应数据类型:application/json
请求参数: 暂无
2.3 功能实现
在admin-service 端,修改AdChannelController类,添加如下方法,mapper和service在之前已经定义
@ApiOperation("查询全部频道")
@GetMapping("/channels")
public ResponseResult findAll() {
List<AdChannel> list = channelService.list();
return ResponseResult.okResult(list);
}
2.4 修改自媒体网关
在配置中心 修改 wemedia-gateway 自媒体网关的yml配置文件中添加如下配置
- id: admin
uri: lb://leadnews-admin
predicates:
- Path=/admin/**
filters:
- StripPrefix= 1
3 自媒体文章-发布、修改、保存草稿
3.1 需求分析
保存文章,除了需要wm_news表以外,还需要另外两张表
3.2 思路分析
参数校验
保存或修改文章
该功能为保存、修改(是否有id)、保存草稿的共用方法
如果有id修改文章,先删除所有素材关联关系
如果没有id,保存文章
关联文章和素材关系表
关联内容中的图片与素材的关系
关联封面中的图片与素材的关系
封面图片如果选择是自动需要从内容中截图图片做为封面图片
截取规则为:
内容图片的个数小于等于2 则为单图截图一张图
内容图片大于2,则为多图,截图三张图
内容中没有图片,则为无图
封装返回成功结果
前端给后端传递的参数格式:
{
"title":"传智教育于2021年1月12日在深交所上市",
"type":"1", # 0:无图 1:单图 3:多图 -1:自动
"labels":"黑马头条",
"publishTime":"2021-01-14T11:35:49.000Z",
"channelId":1,
"images":[ # 文章封面 集合
"https://heimaleadnewsoss.oss-cn-shanghai.aliyuncs.com/material/2021/1/20210113/20214312094300211.jpg"
],
"status":1,
# 文章内容 字符串
"content":"[
{
"type":"text",
"value":"传智教育于2021年1月12日在深交所上市"
},
{
"type":"image",
"value":"https://heimaleadnewsoss.oss-cn-shanghai.aliyuncs.com/material/2021/1/20210113/20210112100045327.jpg"
}
]"
}
3.3 接口定义
接口描述: 自媒体文章-发布、修改、保存草稿
接口地址:/api/v1/news/submit
请求方式:POST
请求数据类型:application/json
响应数据类型:application/json
请求示例:
{
"channelId": 0,
"content": "",
"enable": 0,
"id": 0,
"images": [],
"labels": "",
"publishTime": "",
"reason": "",
"status": 0,
"submitedTime": "",
"title": "",
"type": 0
}
请求参数:
参数名称 | 参数说明 | in | 是否必须 | 数据类型 | schema |
---|---|---|---|---|---|
wmNews | wmNews | body | true | WmNewsDto | WmNewsDto |
channelId | 频道id | true | integer(int32) | ||
content | 文章内容 | true | string | ||
enable | 是否上架 | false | integer(int32) | ||
id | 文章id | true | integer(int32) | 修改存在 | |
images | 图片列表 | false | array | string | |
labels | 标签 | true | string | ||
publishTime | 定时发布时间 | true | string(date-time) | ||
reason | 原因 | false | string | ||
status | 文章状态 | true | integer(int32) | 提交为1 草稿为0 | |
submitedTime | 提交时间 | false | string(date-time) | ||
title | 文章标题 | true | string | ||
type | 文章类型 | false | integer(int32) | 0 无图 1 单图 3 多图 -1 自动 |
WmNewsDto用于接收前端传递参数
package com.heima.model.media.dtos;
import lombok.Data;
import java.util.Date;
import java.util.List;
@Data
public class WmNewsDTO {
// 文章ID
private Integer id;
/**
* 标题
*/
private String title;
/**
* 频道id
*/
private Integer channelId;
/**
* 标签
*/
private String labels;
/**
* 发布时间
*/
private Date publishTime;
/**
* 文章内容
*/
private String content;
/**
* 文章封面类型 0 无图 1 单图 3 多图 -1 自动
*/
private Short type;
/**
* 是否上架 0 下架 1 上架
*/
private Short enable;
/**
* 提交时间
*/
private Date submitedTime;
/**
* 状态 提交为1 草稿为0
*/
private Short status;
/**
* 拒绝理由
*/
private String reason;
/**
* 封面图片列表
*/
private List<String> images;
}
3.4 mapper定义
修改WmNewsMaterialMapper,添加一个方法,用来批量添加数据,用于素材与文章关系做关联
public interface WmNewsMaterialMapper extends BaseMapper<WmNewsMaterial> {
/**
* 保存文章和素材的关联关系
* @param wmMaterialIds 素材id集合
* @param newsId 文章ID
* @param type 文章封面类型 0 内容引用 1 封面引用
*/
public void saveRelations(@Param("wmMaterialIds") List<Integer> wmMaterialIds,
@Param("newsId") Integer newsId,
@Param("type") Short type);
}
新建resources\mapper\WmNewsMaterialMapper.xml文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.heima.wemedia.mapper.WmNewsMaterialMapper">
<insert id="saveRelations">
insert into wm_news_material (material_id, news_id, type, ord)
values
<foreach collection="wmMaterialIds" item="materialId" index="ord" separator=",">
(#{materialId}, #{newsId}, #{type}, #{ord})
</foreach>
</insert>
</mapper>
素材mapper 新增 根据素材列表查询 相关素材id方法
public interface WmMaterialMapper extends BaseMapper<WmMaterial> {
/**
* 根据素材资源路径,查询相关素材id
* @param urls 素材路径
* @param userId
* @return
*/
public List<Integer> selectRelationsIds(@Param("urls") List<String> urls,
@Param("userId") Integer userId);
}
定义mapper.WmMaterialMapper.xml
实现查询方法
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.heima.wemedia.mapper.WmMaterialMapper">
<select id="selectRelationsIds" resultType="Integer">
select id from wm_material
<where>
url IN
<foreach item="url" collection="urls" open="(" close=")" separator=",">
#{url}
</foreach>
and user_id = #{userId}
</where>
</select>
</mapper>
3.5 业务层代码
常量类准备:com.heima.common.constants.wemedia.WmMediaConstans
package com.heima.common.constants.wemedia; /*** @Description: 素材常量* @Version: V1.0*/ public class WemediaConstants {// 是否收藏public static final Short COLLECT_MATERIAL = 1;//收藏public static final Short CANCEL_COLLECT_MATERIAL = 0;//取消收藏// 文章类型public static final String WM_NEWS_TYPE_IMAGE = "image";// 文章状态public static final Short WM_NEWS_DRAFT_STATUS = 0; //草稿public static final Short WM_NEWS_SUMMIT_STATUS = 1; //提交public static final Short WM_NEWS_AUTHED_STATUS = 8; //审核通过public static final Short WM_NEWS_PUBLISH_STATUS = 9; //已发布// 文章封面选图public static final Short WM_NEWS_NONE_IMAGE = 0; //无图public static final Short WM_NEWS_SINGLE_IMAGE = 1; //单图public static final Short WM_NEWS_MANY_IMAGE = 3; //多图public static final Short WM_NEWS_TYPE_AUTO = -1; //图文类型自动// 文章图片引用public static final Short WM_CONTENT_REFERENCE = 0;public static final Short WM_IMAGE_REFERENCE = 1;// 文章上下架状态public static final Short WM_NEWS_UP = 1; // 上架public static final Short WM_NEWS_DOWN = 0; // 下架 }
在WmNewsService类中新增方法
/*** 自媒体文章发布* @param wmNewsDto* @return*/ResponseResult submitNews(WmNewsDTO dto);
3.5.1 保存或修改文章
该功能为保存、修改(是否有id)、保存草稿的共用方法
如果有id修改文章,先删除所有素材关联关系
如果没有id,保存文章
@Overridepublic ResponseResult submitNews(WmNewsDTO dto) {// 1 参数校验if (StringUtils.isBlank(dto.getContent())) {CustException.cust(AppHttpCodeEnum.PARAM_INVALID);}// 校验是否登陆WmUser user = WmThreadLocalUtils.getUser();if (user == null){CustException.cust(AppHttpCodeEnum.NEED_LOGIN);}// 2 保存或修改文章WmNews wmNews = new WmNews();// 将dto参数里面的值设置到wmNewsBeanUtils.copyProperties(dto, wmNews);//如果文章布局是自动,需要设置为nullif (dto.getType().equals(WemediaConstants.WM_NEWS_TYPE_AUTO)) {wmNews.setType(null);}// 处理dto参数 images封面集合 转换成 字符串String images = imageListToStr(dto.getImages());wmNews.setImages(images);wmNews.setUserId(user.getId());saveWmNews(wmNews);// 如果是草稿 直接返回if (WemediaConstants.WM_NEWS_DRAFT_STATUS.equals(dto.getStatus())){return ResponseResult.okResult();}// TODO 3.1 抽取文章中关联的图片路径// TODO 3.2 关联文章内容中的图片和素材关系// TODO 3.3 关联文章封面中的图片和素材关系 封面可能是选择自动或者是无图return ResponseResult.okResult();}
图片集合转字符串
/*** 图片列表转字符串,并去除图片前缀* @param images 图片列表* @param webSite 图片前缀*/ private String imageListToStr(List<String> images, String webSite) {return images.stream() // 获取流.map((url) -> url.replace(webSite, "")) // 对流数据的中间操作.collect(Collectors.joining(",")); }
保存文章
@AutowiredWmNewsMaterialMapper wmNewsMaterialMapper;/*** 保存或修改文章* @param wmNews 文章对象(前端传递)*/private void saveWmNews(WmNews wmNews) {wmNews.setCreatedTime(new Date());wmNews.setUserId(WmThreadLocalUtils.getUser().getId());wmNews.setSubmitedTime(new Date());wmNews.setEnable(WemediaConstants.WM_NEWS_UP); // 上架if (wmNews.getId()==null) { // 保存操作save(wmNews);}else { // 修改// 当前文章 和 素材关系表数据删除wmNewsMaterialMapper.delete(Wrappers.<WmNewsMaterial>lambdaQuery().eq(WmNewsMaterial::getNewsId, wmNews.getId()));updateById(wmNews);}}
小知识点:
3.5.2 解析内容中图片列表
/*** 自媒体文章发布* @param wmNewsDto* @param isSubmit 是否为提交 1 为提交 0为草稿* @return*/ @Override public ResponseResult saveNews(WmNewsDto wmNewsDto, Short isSubmit) { // 上面代码略 ..........................//3.1 抽取文章中关联的图片路径List<String> materials = parseContentImages(dto.getContent());// 下面代码略 .......................... } /*** 抽取文章内容中 所引用的所有图片* @param content 文章内容* @return*/private List<String> parseContentImages(String content) {List<Map> contents = JSON.parseArray(content, Map.class);// 遍历文章内容 将所有 type为image的 value获取出来 去除前缀路径return contents.stream()// 过滤type=image所有的集合.filter( map -> map.get("type").equals(WemediaConstants.WM_NEWS_TYPE_IMAGE))// 获取到image下的value 图片url.map(x -> (String)x.get("value"))// 图片url去除前缀.map(url-> url.replace(webSite,"").replace(" ",""))// 去除重复的路径.distinct()// stream 转成list集合.collect(Collectors.toList());}
参考前端传递参数数据格式解析即可
3.5.3 关联文章内容中的图片和素材关系
/*** 自媒体文章发布* @param wmNewsDto* @param isSubmit 是否为提交 1 为提交 0为草稿* @return*/ @Override public ResponseResult saveNews(WmNewsDto wmNewsDto, Short isSubmit) {// 上面代码略 .......................... // 3.2 关联文章内容中的图片和素材关系if (!CollectionUtils.isEmpty(materials)) {saveRelativeInfo(materials, wmNews.getId(),WemediaConstants.WM_CONTENT_REFERENCE);}// 下面代码略 .......................... }@AutowiredWmMaterialMapper wmMaterialMapper;/*** 保存素材和文章关系* @param urls 素材列表* @param newsId 文章ID* @param type 类型 0:内容素材 1:封面素材*/private void saveRelativeInfo(List<String> urls, Integer newsId, Short type) {//1 查询文章内容中的图片对应的素材IDList<Integer> ids = wmMaterialMapper.selectRelationsIds(urls,WmThreadLocalUtils.getUser().getId());//2 判断素材是否缺失if(CollectionUtils.isEmpty(ids) || ids.size() < urls.size()){CustException.cust(AppHttpCodeEnum.DATA_NOT_EXIST,"相关素材缺失,保存文章失败");}//3 保存素材关系wmNewsMaterialMapper.saveRelations(ids,newsId,type);}
启动服务测试
admin-service
wemedia-service
wemedia-gateway
前端自媒体服务
注意当前登录人下需要上传几张图片
3.5.4 关联文章封面中的图片和素材关系
/*** 自媒体文章发布* @param wmNewsDto* @param isSubmit 是否为提交 1 为提交 0为草稿* @return*/ @Override public ResponseResult submitNews(WmNewsDto wmNewsDto) {// 上面代码略 ..........................// 3.3 关联文章封面中的图片和素材关系 封面可能是选择自动或者是无图saveRelativeInfoForCover(dto,materials, wmNews);return ResponseResult.okResult(); } /*** 【3.3】 关联文章封面中的图片和素材关系* @param dto 前端用户选择封面信息数据* @param materials 从内容中解析的图片列表* @param wmNews 文章ID */private void saveRelativeInfoForCover(WmNewsDTO dto, List<String> materials, WmNews wmNews) {// 前端用户选择的图List<String> images = dto.getImages();// 自动获取封面 ****if (WemediaConstants.WM_NEWS_TYPE_AUTO.equals(dto.getType())) {int materialSize = materials.size();if (materialSize > 0 && materialSize <= 2) { // 单图images = materials.stream().limit(1).collect(Collectors.toList());wmNews.setType(WemediaConstants.WM_NEWS_SINGLE_IMAGE);} else if (materialSize > 2) { // 多图images = materials.stream().limit(3).collect(Collectors.toList());wmNews.setType(WemediaConstants.WM_NEWS_MANY_IMAGE);} else { // 无图wmNews.setType(WemediaConstants.WM_NEWS_NONE_IMAGE);}if (images != null && images.size() > 0) {// 将图片集合 转为字符串 url1,url2,url3wmNews.setImages(imageListToStr(images));}updateById(wmNews);}// 保存图片列表和素材的关系if (images != null && images.size() > 0) {images = images.stream().map(x->x.replace(webSite,"").replace(" ","")).collect(Collectors.toList());saveRelativeInfo(images, wmNews.getId(), WemediaConstants.WM_IMAGE_REFERENCE);}}
3.6 控制层
在WmNewsController类中新增方法
@ApiOperation(value = "发表文章",notes = "发表文章,保存草稿,修改文章 共用的方法")@PostMapping("/submit")public ResponseResult submitNews(@RequestBody WmNewsDTO dto) {return wmNewsService.submitNews(dto);}
3.7 测试
postman工具测试
4 自媒体文章-根据id查询
4.1 需求分析
4.2 接口定义
接口描述: 根据id查询文章
接口地址:/api/v1/news/one/{id}
请求方式:GET
请求数据类型:*
响应数据类型:application/json
请求参数:
参数名称 | 参数说明 | in | 是否必须 | 数据类型 | schema |
---|---|---|---|---|---|
id | 文章主键id | path | true | integer(int32) |
4.3 业务层代码编写
在WmNewsService接口中新增方法 根据id查询文章的方法
/*** 根据文章id查询文章* @return*/ ResponseResult findWmNewsById(Integer id);
实现类:
@Overridepublic ResponseResult findWmNewsById(Integer id) {//1 参数检查if (id == null) {CustException.cust(AppHttpCodeEnum.PARAM_INVALID);}//2 执行查询WmNews wmNews = getById(id);if (wmNews == null) {CustException.cust(AppHttpCodeEnum.DATA_NOT_EXIST);}//3 返回结果ResponseResult result = ResponseResult.okResult(wmNews);result.setHost(webSite);return result;}
4.4 控制层
在WmNewsController新增方法 查询文章
@ApiOperation(value = "根据id查询自媒体文章")@GetMapping("/one/{id}")public ResponseResult findWmNewsById(@PathVariable("id") Integer id) {return wmNewsService.findWmNewsById(id);}
4.5 测试
java 黑马头条 day4 自媒体文章发布 自媒体文章列表查询 频道列表展示 自媒体文章-发布、修改、保存草稿 自媒体文章-根据id查询 自媒体文章-删除相关推荐
- 在linux中如何修改保存gun文件_Linux下文件重命名、创建、删除、修改及保存文件...
一.重命名(更名) linux 给文件改名的命令是mv命令 mv命令来为文件或目录改名或将文件由一个目录移入另一个目录中.该命令等同于DOS系统下的ren和move命令的组合.它的使用权限是所有用户. ...
- Python黑马头条推荐系统第三天 实时计算和召回业务、推荐业务流实现与ABTest
实时计算业务 4.1 实时计算业务介绍 学习目标 目标 了解实时计算的业务需求 知道实时计算的作用 应用 无 4.1.1 实时计算业务需求 实时(在线)计算: 解决用户冷启动问题 实时计算能够根据用户 ...
- std::list 修改某个值_在WordPress首页不显示某个分类文章的做法
WordPress作为博客站点很好用,但可惜的是没有微博/twitter之类快速短文的功能,如果设置一个分类来放置这类短文,首页又会显得杂乱而没有章法,按照网络上的教程,这个问题有几种解决办法,自己采 ...
- 前端基础第五天项目 社交媒体黑马头条项目-文章模块和评论
七.文章详情 创建组件并配置路由 1.创建 views/article/index.vue 组件 <template><div class="article-contain ...
- 黑马头条项目总结之文章发布
文章发布功能 /*** 新增文章** @param dto 参数* @return 响应信息*/@Overridepublic ResponseResult submitNews(WmNewsDto ...
- 前端基础第四天项目 社交媒体黑马头条项目-登录注册和个人中心
一.项目初始化 目标 能使用 Vue CLI 创建项目 了解 Vant 组件库的导入方式 掌握制作使用字体图标的方式 掌握如何在 Vue 项目中处理 REM 适配 理解 axios 请求模块的封装 使 ...
- Java在线教育项目 第九天黑马头条爬虫
day09_爬虫文档解析整合&数据保存准备 目标 能够完成爬虫初始化url的解析代码 能够完成个人空间页的解析 能够完成文章目标页的解析 能够进行整合测试 能够编写频道的保存及查询 1 文档解 ...
- 新黑马头条项目经验(黑马)
swagger (1)简介 Swagger 是一个规范和完整的框架,用于生成.描述.调用和可视化 RESTful 风格的 Web 服务(API Documentation & Design ...
- 《黑马头条》 ElectricSearch 分词器 联想词 MangoDB day08-平台管理[实战]作业
07 app端文章搜索 1) 今日内容介绍 1.1)App端搜索-效果图 1.2)今日内容 2) 搭建ElasticSearch环境 2.1) 拉取镜像 docker pull elasticsear ...
最新文章
- BZOJ 3132 上帝造题的七分钟(二维树状数组)
- oracle 创建触发器_oracle创建触发器
- java重入锁,再探JAVA重入锁
- redis——客户端
- 属性子集选择的基本启发方法_一文看懂数据预处理最重要的3种思想和方法
- 【复杂网络分析】motif、cluster、clique、community 的介绍和比较
- 10_Shell语言———I/O重定向详解
- TensorFlow 2.0要来了,tf.contrib要砍了 | 有什么意见你说啊
- buildroot 下载和make nconfig
- 此文已删除,为何删不掉?
- iOS的音频文件的格式转换
- Struts2通配符和它的各种问题总结
- 学生专用计算机怎么没声音,班班通电脑没声音了
- opencv直方图,lomo,cartoon
- 2019.1.30《C Primer Plus》拖了一天写完的第八章编程练习答案
- TOJ 4171 L-The math problem(水题)
- 2022-2028全球与中国呼吸系统疾病治疗市场现状及未来发展趋势
- 导航算法A*的简单实现
- Java初级面试笔记
- day18-面向对象作业