当前位置: 首页 > news >正文

微服务项目收获和总结---第2,3天(分库分表思想,文章业务)

①分库分表思想

文章表一对一为什么要拆分?因为文章的内容会非常大,查询效率会很低,我们经常操作文章的基本信息,不会很经常查询文章内容。充分发挥高频数据的操作效率。 

②freemarker和minIO

由于文章内容数据量过大,我们通过freemarker创建出静态页面并且上传到minIO中存储,前端访问时直接访问静态页面。

③自媒体素材管理

 数据库表:

素材表:创作者可上传素材到其中,并且可以设置收藏与否
文章表:创作者所发布的文章的表,包括每一篇文章的用户ID,标题,内容,封面格式,频道,当前状态
文章素材关系表:文章与素材引用的关系表格

业务逻辑:!!!!非常重要要捋清楚

①你写一篇文章,可以选择保存草稿或者直接发布。

②如果你是保存草稿,先要判断该文章是否已经存在,疑问点:为什么草稿也要判断是否已经存在,因为还有编辑草稿的操作,当你把之前的草稿进行重新编辑时提交就要判断是否存在。如果是新增草稿,就新增一篇文章,并把内容中的图片与素材的关系表添加数据进行绑定,而且也要把封面的图片与素材进行绑定。然后就可以结束。

③如果是发布文章,因为文章也有编辑发布和直接发布操作。所以也是要判断是否已经存在该文章。如果是直接发布文章,则不会存在ID,然后把内容和封面的图片与素材的绑定关系添加到数据库的文章素材关系表中即可。但是如果是把已经发布的文章进行编辑然后再发布,首先也是要判断是否存在当然这一步判断肯定是存在的,然后就需要把旧版本的文章内容和封面所绑定的图片进行删除,然后再更新新的绑定关系。

代码实现:

首先要熟悉前端传过来的参数:

代码:
public class WmNewsServiceImpl extends ServiceImpl<WmNewsMapper,WmNews> implements WmNewsService {@Overridepublic ResponseResult findList(WmNewsPageReqDto dto) {//检查参数dto.checkParam();//分页查询IPage page =new Page(dto.getPage(),dto.getSize());LambdaQueryWrapper<WmNews> lambdaQueryWrapper = new LambdaQueryWrapper();//状态精确查询if(dto.getStatus() != null){lambdaQueryWrapper.eq(WmNews::getStatus,dto.getStatus());}//频道精确查询if(dto.getChannelId() != null){lambdaQueryWrapper.eq(WmNews::getChannelId,dto.getChannelId());}//时间范围查询if(dto.getBeginPubDate() != null && dto.getEndPubDate() != null){lambdaQueryWrapper.between(WmNews::getPublishTime,dto.getBeginPubDate(),dto.getEndPubDate());}//关键字模糊查询if (StringUtils.isNotBlank(dto.getKeyword())){lambdaQueryWrapper.like(WmNews::getTitle,dto.getKeyword());}//查询当前登录人的文章lambdaQueryWrapper.eq(WmNews::getUserId, WmThreadLocalUtil.getUser().getId());//按照发布时间倒序查询lambdaQueryWrapper.orderByDesc(WmNews::getPublishTime);//查询page = page(page, lambdaQueryWrapper);ResponseResult responseResult = new PageResponseResult(dto.getPage(), dto.getSize(), (int) page.getTotal());responseResult.setData(page.getRecords());//结果返回return responseResult;}@Overridepublic ResponseResult submitNews(WmNewsDto dto) {//条件判断,判断前端穿过来的值不为空if(dto == null || dto.getContent() == null){return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);}//保存或者修改文章,把基本信息保存到News文章对象中WmNews wmNews = new WmNews();BeanUtils.copyProperties(dto,wmNews);//图片的类型转换,把字符串中的封面图片路径提取出来,保存到Nes对象中if(dto.getImages() != null && dto.getImages().size()>0){String imgesStr = StringUtils.join(dto.getImages(), ",");wmNews.setImages(imgesStr);}//如果封面类型为自动,先把封面类型设置为空if(dto.getType().equals(WemediaConstants.WM_NEWS_TYPE_AUTO)){wmNews.setType(null);}//直接保存到数据库中,并且把图片和素材的关系删除saveOrUpdateNews(wmNews);//判断是否为草稿就可以直接返回,如果是,结束方法if(dto.getStatus().equals(WmNews.Status.NORMAL.getCode())){return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);}//不是草稿,保存文章内容图片与素材的关系//获取到内容中的图片信息List<String> materials = ectractUrlInfo(dto.getContent());//将正文中的图片信息+文章的ID,即正文图片与素材的绑定关系保存到数据库中saveRelativeInfoForContent(materials,wmNews.getId());//保存文章封面图片与素材的关系saveRelativeInfoForCover(dto,wmNews,materials);return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);}/*** 根据封面规则去存储* @param dto* @param wmNews* @param materials*///内容图片等于1  小于3  单图 type 1//大于3 多图 type 3//没图  无图 type 0//保存封面与素材的关系@Autowiredprivate WmMaterialMapper wmMaterialMapper;@Autowiredprivate WmNewsMaterialMapper wmNewsMaterialMapper;//保存或修改文章private void saveOrUpdateNews(WmNews wmNews) {//补全属性wmNews.setUserId(WmThreadLocalUtil.getUser().getId());wmNews.setCreatedTime(new Date());wmNews.setSubmitedTime(new Date());wmNews.setEnable((short) 1); //默认为上架if(wmNews.getId() == null){//保存save(wmNews);}else{//修改//删除文章图片与素材的关系wmNewsMaterialMapper.delete(Wrappers.<WmNewsMaterial>lambdaQuery().eq(WmNewsMaterial::getNewsId,wmNews.getId()));updateById(wmNews);}}//提取文章内容的图片信息private List<String> ectractUrlInfo(String content) {List<String> materials = new ArrayList<>();List<Map> maps = JSON.parseArray(content, Map.class);for (Map map : maps) {if(map.get("type").equals("image")){String imgUrl  = (String) map.get("value");materials.add(imgUrl);}}return materials;}//处理文章内容图片与素材的关系private void saveRelativeInfoForContent(List<String> materials, Integer newsId) {saveRelativeInfo(materials,newsId, WemediaConstants.WM_CONTENT_REFERENCE);}//保存文章内容图片和素材的关系到数据库中private void saveRelativeInfo(List<String> materials, Integer newsId, Short type) {if(materials != null && !materials.isEmpty()){//通过图片查询素材的idList<WmMaterial> dbMaterials = wmMaterialMapper.selectList(Wrappers.<WmMaterial>lambdaQuery().in(WmMaterial::getUrl, materials));//判断素材是否有效if(dbMaterials == null || dbMaterials.size() == 0){//手动抛异常throw new CustomException(AppHttpCodeEnum.MATERIAL_REFERENCE_FALL);}if(materials.size() != dbMaterials.size()){throw new CustomException(AppHttpCodeEnum.MATERIAL_REFERENCE_FALL);}List<Integer> idList = dbMaterials.stream().map(WmMaterial::getId).collect(Collectors.toList());//批量保存wmNewsMaterialMapper.saveRelations(idList,newsId,type);}}//保存封面图片和素材的关系到数据库中private void saveRelativeInfoForCover(WmNewsDto dto, WmNews wmNews, List<String> materials) {List<String> images = dto.getImages();if(dto.getType().equals(WemediaConstants.WM_NEWS_TYPE_AUTO)){//多图if(materials.size() >= 3){wmNews.setType(WemediaConstants.WM_NEWS_MANY_IMAGE);images = materials.stream().limit(3).collect(Collectors.toList());}else if(materials.size() >1 && materials.size() <3){//单图wmNews.setType(WemediaConstants.WM_NEWS_SINGLE_IMAGE);images = materials.stream().limit(1).collect(Collectors.toList());}else{//无图wmNews.setType(WemediaConstants.WM_NEWS_NONE_IMAGE);}//修改文章if(images != null && images.size() > 0){wmNews.setImages(StringUtils.join(images,","));}updateById(wmNews);}if(images != null && images.size() > 0){saveRelativeInfo(images,wmNews.getId(),WemediaConstants.WM_COVER_REFERENCE);}}}

相关文章:

微服务项目收获和总结---第2,3天(分库分表思想,文章业务)

①分库分表思想 文章表一对一为什么要拆分&#xff1f;因为文章的内容会非常大&#xff0c;查询效率会很低&#xff0c;我们经常操作文章的基本信息&#xff0c;不会很经常查询文章内容。充分发挥高频数据的操作效率。 ②freemarker和minIO 由于文章内容数据量过大&#xff0c…...

【全网最全】2024电工杯数学建模A题21页初步参考论文+py代码+保奖思路等(后续会更新)

您的点赞收藏是我继续更新的最大动力&#xff01; 一定要点击如下的卡片链接&#xff0c;那是获取资料的入口&#xff01; 【全网最全】2024电工杯数学建模A题21页初步参考论文py代码保奖思路等&#xff08;后续会更新成品论文&#xff09;「首先来看看目前已有的资料&#x…...

怎么通过OpenAI API调用其多模态大模型(GPT-4o)

现在只要有额度&#xff0c;大家都可以调用OpenAI的多模态大模型了&#xff0c;例如GPT-4o和GPT-4 Turbo&#xff0c;我一年多前总结过一些OpenAI API的用法&#xff0c;发现现在稍微更新了一下。主要参考了这里&#xff1a;https://platform.openai.com/docs/guides/vision 其…...

自定义文字线性

...

robosuite导入自定义机器人

目录 目的&#xff1a;案例一&#xff1a;成果展示具体步骤&#xff1a;URDF文件准备xml文件生成xml修改机器人构建 目的&#xff1a; 实现其他标准/非标准机器人的构建 案例一&#xff1a; 成果展示 添加机器人JAKA ZU 7 这个模型 具体步骤&#xff1a; URDF文件准备 从…...

四天学会JS高阶(学好vue的关键)——构造函数数据常用函数(理论+实战)(第二天)

一、对象创建引发构造函数产生 1.1 创建对象三种方式&#xff1a; 利用对象字面量创建对象 const obj {name: 佩奇}注&#xff1a;对象字面量的由来&#xff1a;即它是直接由字面形式&#xff08;由源代码直接&#xff09;创建出来的对象&#xff0c;而不是通过构造函数或者…...

【Linux学习】进程地址空间与写时拷贝

文章目录 Linux进程内存布局图&#xff1a;内存布局的验证 进程地址空间写时拷贝 Linux进程内存布局图&#xff1a; 地址空间的范围&#xff0c;在32位机器上是2^32比特位,也就是[0,4G]。 内存布局的验证 代码验证内存布局&#xff1a; 验证代码&#xff1a; #include<s…...

Git远程控制

文章目录 1. 创建仓库1.1 Readme1.2 Issue1.3 Pull request 2. 远程仓库克隆3. 推送远程仓库4. 拉取远程仓库5. 配置Git.gitignore配置别名 使用GitHub可以&#xff0c;采用Gitee也行 1. 创建仓库 1.1 Readme Readme文件相当于这个仓库的说明书&#xff0c;gitee会初始化2两份…...

怎样从SQL中分析和提取访问的字段信息?| OceanBase实践

当执行任意一条SELECT SQL语句时&#xff0c;我们如何能够分析出所访问的字段信息&#xff0c;并进一步判断结果集中的每一列数据具体来自于哪些数据库、表以及表中的哪些字段呢&#xff1f;本文将会详细阐述针对此问题的技术解决方案。 应用场景 从 SQL 中解析访问的原始字段…...

MySQL 服务无法启动

常见原因: 检查端口占用&#xff1a; 使用命令行工具&#xff08;如netstat&#xff09;来检查3306端口是否已被其他程序占用,输入netstat -ano&#xff08;Windows&#xff09;或netstat -tulnp | grep 3306&#xff08;Linux/Mac&#xff09;来查找3306端口的占用情况。如果…...

Python贪心算法

贪心算法&#xff08;Greedy Algorithm&#xff09;是一种常见的算法设计策略&#xff0c;它在每一步选择当前最优解&#xff0c;希望通过局部最优解最终得到全局最优解。贪心算法通常适用于满足一些特定条件的问题&#xff0c;例如货币找零、活动选择、任务调度等。贪心算法的…...

牛客网刷题 | BC85 牛牛学数列3

目前主要分为三个专栏&#xff0c;后续还会添加&#xff1a; 专栏如下&#xff1a; C语言刷题解析 C语言系列文章 我的成长经历 感谢阅读&#xff01; 初来乍到&#xff0c;如有错误请指出&#xff0c;感谢&#xff01; 描述 牛牛准备继续进阶&…...

quartz定时任务

Quartz 数据结构 quartz采用完全二叉树&#xff1a;除了最后一层每一层节点都是满的&#xff0c;而且最后一层靠左排列。 二叉树节点个数规则&#xff1a;每层从左开始&#xff0c;第一层只有一个&#xff0c;就是2的0次幂&#xff0c;第二层两个就是2的1次幂&#xff0c;第三…...

Python基础学习笔记(五)——选择结构与循环结构

目录 程序的组织结构条件选择结构1. 单分支结构2. 双分支结构3. 多分支结构4. 嵌套&#xff08;分支&#xff09;结构5. 无内容执行6. 条件表达式 循环结构1. 可迭代对象2. range()函数3. for循环语句4. while循环语句5. 结束语句 程序的组织结构 程序的组织结构主要有以下三种…...

Vue插槽solt如何传递具名插槽的数据给子组件?

在Vue中&#xff0c;你可以通过作用域插槽&#xff08;scoped slots&#xff09;来传递数据给子组件。这同样适用于具名插槽。首先&#xff0c;你需要在子组件中定义一个具名插槽&#xff0c;并通过v-slot指令传递数据。例如&#xff1a; 子组件&#xff08;ChildComponent.vu…...

小程序-收货地址管理模块实现

页面结构代码&#xff1a; address-form.vue --->新建地址和修改地址页面 <template><view class"content"><form><!-- 表单内容 --><view class"form-item"><text class"label">收货人</text>…...

【星海随笔】微信小程序(三)

网络数据请求 1.小程序中网络数据请求的限制 出于安全性方面的考虑,小程序官方对 数据接口的请求 做出了如下 两个限制: ① 只能请求 HTTPS 类型的接口 ② 必须将 接口的域名 添加到 信任列表 中 微信小程序只能请求 https 类型的接口 且需要请求的域名必须提前进行设置后,才可…...

pip(包管理器) for Python

pip是什么 pip是Python的包安装程序&#xff0c;即python包管理器。您可以使用 pip 从Python包索引和其他索引安装包。 1. pip 安装 python 包 pip install 包名 例如&#xff1a;pip install pymssql &#xff1a; 使用pip安装数据库驱动包 pymssql 2.pip 卸载 python 包 pi…...

Ubuntu上安装Maven

在Ubuntu上安装Maven的步骤如下&#xff1a; 更新包索引&#xff1a; sudo apt update 安装Maven&#xff1a; sudo apt install maven 验证安装是否成功&#xff1a; mvn -version 以上步骤将会安装Maven并添加到系统路径中&#xff0c;你可以通过运行mvn -version来验…...

java中使用svnkit实现文件的版本管理

java中使用svnkit实现文件的版本管理 一、引入svnKit依赖二、初始化仓库工厂类二、使用svnkit创建本地存储仓库三、svn基本原子操作四、通过原子方法实现简单svn相应操作 一、引入svnKit依赖 <dependency><groupId>org.tmatesoft.svnkit</groupId><artifa…...

别再硬扛内存了:用Gensim的Word2Vec分批次处理超大语料库(附Python代码)

高效处理海量文本&#xff1a;Gensim Word2Vec分批次训练实战指南 当面对数十GB的文本数据时&#xff0c;传统的一次性加载方法往往会让内存不堪重负。本文将深入探讨如何利用Gensim库的Word2Vec实现分批次训练&#xff0c;突破内存限制&#xff0c;同时保持模型质量。 1. 大…...

Windows下GridSearchCV并行计算避坑指南:解决n_jobs=-1导致的编码错误

Windows平台高效调参实战&#xff1a;GridSearchCV并行计算编码问题终极解决方案 当你在Windows系统上使用Scikit-learn的GridSearchCV进行超参数调优时&#xff0c;是否遇到过这样的报错信息&#xff1f;"UnicodeEncodeError: ascii codec cant encode characters...&quo…...

无需寻找激活码,用快马平台五分钟搭建你的第一个Web项目管理面板原型

最近在折腾一个Web项目管理面板的原型设计&#xff0c;发现用传统方式从零搭建实在太费时间。刚好试用了InsCode(快马)平台&#xff0c;五分钟就搞定了基础功能&#xff0c;完全不需要操心本地环境配置或者找什么激活码。记录下这个超快手的实现过程&#xff1a; 功能拆解 这个…...

[资料整理]魔法师传奇 MagicMayhem

魔法师传奇 Magic&Mayhem魔法师传奇中文站网站魔法师传奇2023版介绍魔法师传奇中文站网站 网站地址&#xff1a;魔法师传奇中文站 http://zb.l4d.top:1983/magic 备用链接&#xff1a;http://zb.my.to:1983/magic 论坛地址&#xff1a;魔法师传奇中文论坛 http://zb.l4d.t…...

OpenRPA工作项队列管理:实现批量数据处理的最佳实践

OpenRPA工作项队列管理&#xff1a;实现批量数据处理的最佳实践 【免费下载链接】openrpa Free Open Source Enterprise Grade RPA 项目地址: https://gitcode.com/gh_mirrors/op/openrpa OpenRPA作为一款免费开源的企业级RPA自动化工具&#xff0c;其强大的工作项队列管…...

硬件笔记——立创逻辑派开关电源案例解读

立创逻辑派开发板中有上图三个BUCK电路,使用SY8113B芯片将5V电压分别降压至3.3V、1.5V、1.0V。 SY8113B 是一款同步降压型稳压 IC,它将 PWM 控制模块、高端开关管与低端开关管集成在同一芯片上,以此最大限度降低开关转换损耗与导通损耗。凭借超低导通电阻Rds (on)的…...

游戏角色建模新革命:用Face3D.ai Pro快速生成高精度3D人脸资产

游戏角色建模新革命&#xff1a;用Face3D.ai Pro快速生成高精度3D人脸资产 1. 从一张照片到游戏角色&#xff0c;到底有多远&#xff1f; 想象一下这个场景&#xff1a;你是一位游戏美术师&#xff0c;刚刚拿到策划发来的角色设定图。图上是一位面容坚毅的东方武士&#xff0…...

Transformer与NLP研究

自2017年Google Brain团队提出以来,Transformer架构已成为自然语言处理(NLP)领域的核心引擎,彻底改变了AI处理序列数据的方式。从BERT、GPT到T5,再到2025年谷歌发布的Titans架构,这一架构不断演进,突破了传统循环神经网络(RNN)和卷积神经网络(CNN)在并行计算、长距离…...

Qwen3.5-9B基础教程:start.sh脚本解析+环境变量注入+PATH调试技巧

Qwen3.5-9B基础教程&#xff1a;start.sh脚本解析环境变量注入PATH调试技巧 1. 项目概述 Qwen3.5-9B是一个拥有90亿参数的开源大语言模型&#xff0c;具备强大的逻辑推理、代码生成和多轮对话能力。该模型支持多模态理解&#xff08;图文输入&#xff09;和长上下文处理&…...

2026年一体化HR系统TOP8盘点:从集团管控到AI落地的选型指南

进入2026年&#xff0c;企业选一体化HR系统不再只看模块是否齐全&#xff0c;更看能否支撑集团管控、复杂用工、数据洞察与AI提效闭环。红海云在国央企与复杂场景的深度适配、以及AI在招聘与员工服务等环节的可落地性上更突出&#xff1b;用友、北森、金蝶在业人融合、PaaS扩展…...