JavaWeb_LeadNews_Day3-图片管理, 文章管理

JavaWeb_LeadNews_Day3-图片管理, 文章管理

  • 图片管理
    • 图片上传
      • 实现思路
      • 获取用户信息
      • 将图片上传至minio
    • 图片列表
  • 文章管理
    • 频道列表查询
    • 文章列表查询
    • 文章发布
      • 实现思路
      • 具体代码
  • 来源

图片管理

图片上传

实现思路

  1. 在GateWay解析前端请求, 获取用户信息, 存储在header中
  2. 在Interceptor得到header中的用户信息, 存入当前线程
  3. 将图片上传到minio中, 得到图片路径
  4. 将用户id, 图片路径及其他数据保存到素材表中

获取用户信息

// GateWay
@Component
public class AuthorizeFilter implements Ordered, GlobalFilter {@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {ServerHttpRequest request = exchange.getRequest();...String token = request.getHeaders().getFirst("token");...try {Claims claimsBody = AppJwtUtil.getClaimsBody(token);...// 获取用户信息String userId = claimsBody.get("id").toString();// 存储在header中ServerHttpRequest serverHttpRequest = request.mutate().headers(httpHeaders -> {httpHeaders.add("userId", userId);}).build();// 重置请求exchange.mutate().request(serverHttpRequest);} catch (Exception e) {e.printStackTrace();}...}...
}// ThreadLocal
public class WmThreadLocalUtil {private final static ThreadLocal<WmUser> WM_USER_THREAD_LOCAL = new ThreadLocal<>();// 存入线程中public static void setUser(WmUser wmUser){WM_USER_THREAD_LOCAL.set(wmUser);}// 从线程中获取public static WmUser getUser(){return WM_USER_THREAD_LOCAL.get();}// 清理public static void clear(){WM_USER_THREAD_LOCAL.remove();}
}// Interceptor
public class WmTokenInterceptor implements HandlerInterceptor {/*** 得到header中的用户信息, 并且存入到当前线程中*/@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {String userId = request.getHeader("userId");if(userId != null){// 存入当前线程WmUser wmUser = new WmUser();wmUser.setId(Integer.valueOf(userId));WmThreadLocalUtil.setUser(wmUser);}return true;}/*** 清理线程中的数据*/@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {WmThreadLocalUtil.clear();}
}// WebMvcConfig
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new WmTokenInterceptor()).addPathPatterns("/**");}
}

将图片上传至minio

@Slf4j
@Service
@Transactional
public class WmMaterialServiceImpl extends ServiceImpl<WmMaterialMapper, WmMaterial> implements WmMaterialService {@Autowiredprivate FileStorageService fileStorageService;/*** 图片上传* @param multipartFile* @return*/@Overridepublic ResponseResult uploadPicture(MultipartFile multipartFile) {// 1. 检查参数if(multipartFile == null || multipartFile.getSize() == 0){return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);}// 2. 上传图片到minio中String fileName = UUID.randomUUID().toString().replace("-", "");String originalFilename = multipartFile.getOriginalFilename();String postfix = originalFilename.substring(originalFilename.lastIndexOf("."));String fileId = null;try {fileId = fileStorageService.uploadImgFile("", fileName+postfix, multipartFile.getInputStream());log.info("上传图片到minio中, fileId: {}", fileId);} catch (IOException e) {log.error("WmMaterialServiceImpl-上传文件失败");throw new RuntimeException(e);}// 3. 保存到数据库中WmMaterial wmMaterial = new WmMaterial();wmMaterial.setUserId(WmThreadLocalUtil.getUser().getId());wmMaterial.setUrl(fileId);wmMaterial.setIsCollection((short) 0);wmMaterial.setType((short) 0);wmMaterial.setCreatedTime(new Date());save(wmMaterial);// 4. 返回结果return ResponseResult.okResult(wmMaterial);}
}

图片列表

// WmMaterialDto
@Data
public class WmMaterialDto extends PageRequestDto {/*** 1.收藏, 0.未收藏*/private Short isCollection;
}// Service
@Override
public ResponseResult findList(WmMaterialDto dto) {// 1. 检查参数dto.checkParam();// 2. 分页查询IPage page = new Page(dto.getPage(), dto.getSize());LambdaQueryWrapper<WmMaterial> queryWrapper = new LambdaQueryWrapper<>();// 是否收藏if(dto.getIsCollection() != null && dto.getIsCollection() == 1){queryWrapper.eq(WmMaterial::getIsCollection, 1);}// 按照用户查询queryWrapper.eq(WmMaterial::getUserId, WmThreadLocalUtil.getUser().getId());// 按照时间倒序排序queryWrapper.orderByDesc(WmMaterial::getCreatedTime);page(page, queryWrapper);PageResponseResult result = new PageResponseResult(dto.getPage(), dto.getSize(), (int) page.getTotal());result.setData(page.getRecords());// 3. 结果返回return result;
}

文章管理

频道列表查询

@Override
public ResponseResult findAll() {return ResponseResult.okResult(list());
}

文章列表查询

// WmNewsPageReqDto
@Data
public class WmNewsPageReqDto extends PageRequestDto {/*** 状态*/private Short status;/*** 开始时间*/private Date beginPubDate;/*** 结束时间*/private Date endPubDate;/*** 所属频道ID*/private Integer channelId;/*** 关键字*/private String keyword;
}// Service
@Service
@Slf4j
@Transactional
public class WmNewsServiceImpl  extends ServiceImpl<WmNewsMapper, WmNews> implements WmNewsService {/*** 查询文章* @param dto* @return*/@Overridepublic ResponseResult findAll(WmNewsPageReqDto dto) {// 1. 参数检验dto.checkParam();// 2. 分页查询IPage page = new Page(dto.getPage(), dto.getSize());LambdaQueryWrapper<WmNews> queryWrapper = new LambdaQueryWrapper<>();// 2.1 查询状态queryWrapper.eq(dto.getStatus()!=null, WmNews::getStatus, dto.getStatus());// 2.2 查询所属频道queryWrapper.eq(dto.getChannelId()!=null, WmNews::getChannelId, dto.getChannelId());// 2.3 查询关键字queryWrapper.like(dto.getKeyword()!=null, WmNews::getTitle, dto.getKeyword());// 2.4 查询时间queryWrapper.between(dto.getBeginPubDate()!=null&&dto.getEndPubDate()!=null, WmNews::getPublishTime, dto.getBeginPubDate(), dto.getEndPubDate());// 2.5 根据当前用户查询queryWrapper.eq(WmNews::getUserId, WmThreadLocalUtil.getUser().getId());// 2.6 根据发布时间倒序排序queryWrapper.orderByDesc(WmNews::getPublishTime);// 2.7 查询结果page(page, queryWrapper);// 3. 返回结果PageResponseResult result = new PageResponseResult(dto.getPage(), dto.getSize(), (int) page.getTotal());result.setData(page.getRecords());return result;}
}

文章发布

实现思路

  1. 文章提交审核或者存入草稿
  2. 存在id, 删除文章素材关系表中的关联关系, 修改文章
  3. 不存在id, 新增文章
  4. 是草稿, 草稿无需在文章素材关系表中保存关联关系
  5. 不是草稿, 在文章素材关系表中保存内容图片
  6. 不是草稿, 在文章素材关系表中保存封面图片

具体代码

// WmNewsDto
public class WmNewsDto {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;/*** 提交时间*/private Date submitedTime; /*** 状态 提交为1  草稿为0*/private Short status;/*** 封面图片列表 多张图以逗号隔开*/private List<String> images;
}// Service
@Service
@Slf4j
@Transactional
public class WmNewsServiceImpl  extends ServiceImpl<WmNewsMapper, WmNews> implements WmNewsService {/*** 发布文章或保存草稿* @param dto* @return*/@Overridepublic ResponseResult submitNews(WmNewsDto dto) {// 1. 检查数据if(dto == null || dto.getContent() == null){return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);}// 2. 保存或修改文章WmNews wmNews = new WmNews();// 属性拷贝, 属性名和类型相同才能拷贝BeanUtils.copyProperties(dto, wmNews);// 封面图片: List -> Stringif(dto.getImages() != null && dto.getImages().size() > 0){String imagesStr = StringUtils.join(dto.getImages(), ",");wmNews.setImages(imagesStr);}// 如果当前封面类型为自动-1if(dto.getType() == WemediaConstants.WM_NEWS_TYPE_AUTO){wmNews.setType(null);}saveOrUpdateWmNews(wmNews);// 3. 判断是否为草稿, 如果为草稿结束当前方法if(dto.getStatus() == WmNews.Status.NORMAL.getCode()){return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);}// 获取到文章内容中的图片信息List<String> materials = extractUrlInfo(dto.getContent());// 4. 不是草稿, 保存文章内容图片与素材的关系saveRelativeInfoForContent(materials, wmNews.getId());// 5. 不是草稿, 保存文章封面图片与素材的关系saveRelativeInfoForCover(dto, wmNews, materials);return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);}/*** 1. 若封面类型为自动, 则需设置封面类型的数据* 2. 保存封面图片与素材的关系*/private void saveRelativeInfoForCover(WmNewsDto dto, WmNews wmNews, List<String> materials) {// 自动类型设置封面类型的数据List<String> imgsCover = dto.getImages();if(dto.getType() == WemediaConstants.WM_NEWS_TYPE_AUTO){if(materials.size() >= 3){wmNews.setType(WemediaConstants.WM_NEWS_MANY_IMAGE);imgsCover = materials.stream().limit(3).collect(Collectors.toList());}else if(materials.size() >= 1){wmNews.setType(WemediaConstants.WM_NEWS_SINGLE_IMAGE);imgsCover = materials.stream().limit(1).collect(Collectors.toList());}else{wmNews.setType(WemediaConstants.WM_NEWS_NONE_IMAGE);}// 修改文章if(imgsCover!=null && imgsCover.size() > 0){wmNews.setImages(StringUtils.join(imgsCover, ","));}updateById(wmNews);}// 保存封面图片与素材的关系if(imgsCover!=null && imgsCover.size() > 0){saveRelativeInfo(imgsCover, wmNews.getId(), WemediaConstants.WM_COVER_REFERENCE);}}/*** 处理文章内容图片与素材的关系* @param materials* @param newsId*/private void saveRelativeInfoForContent(List<String> materials, Integer newsId) {saveRelativeInfo(materials, newsId, WemediaConstants.WM_CONTENT_REFERENCE);}@Autowiredprivate WmMaterialMapper wmMaterialMapper;/*** 保存文章图片与素材的关系到数据库中* @param materials* @param newsId* @param type*/private void saveRelativeInfo(List<String> materials, Integer newsId, Short type) {if(materials==null || materials.isEmpty()){return;}// 通过url查询idLambdaQueryWrapper<WmMaterial> queryWrapper = new LambdaQueryWrapper<>();queryWrapper.in(WmMaterial::getUrl, materials);List<WmMaterial> wmMaterialList = wmMaterialMapper.selectList(queryWrapper);// 判断素材是否有效if(wmMaterialList==null || wmMaterialList.size()!=materials.size()){// 手动抛出异常// 1. 提示调用者素材失效// 2. 进行数据的回滚throw new CustomException(AppHttpCodeEnum.MATERIAL_REFERENCE_FAIL);}List<Integer> ids = wmMaterialList.stream().map(WmMaterial::getId).collect(Collectors.toList());wmNewsMaterialMapper.saveRelations(ids, newsId, type);}private List<String> extractUrlInfo(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;}@Autowiredprivate WmNewsMaterialMapper wmNewsMaterialMapper;/*** 保存或修改文章* @param wmNews*/private void saveOrUpdateWmNews(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{// 修改// 删除文章图片和素材的关系LambdaQueryWrapper<WmNewsMaterial> queryWrapper = new LambdaQueryWrapper<>();queryWrapper.eq(WmNewsMaterial::getNewsId, wmNews.getId());wmNewsMaterialMapper.delete(queryWrapper);updateById(wmNews);}}
}

来源

黑马程序员. 黑马头条

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/6167.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Vue整体架构分解

Vue.js的整体架构可以分解为以下几个部分: 文章目录 1. 数据驱动2. 组件化3. 响应式系统4. 虚拟DOM5. 插件系统6. 单文件组件7. 模板编译总结 1. 数据驱动 Vue的一个核心特点是数据驱动。Vue会在初始化的时候给数据提供一个observe监听&#xff0c;当数据变化时&#xff0c;会…

uniapp 微信小程序 input详解 带小数点的input、可查看密码的输入框input

官网文档地址 1、template <!-- 本示例未包含完整css&#xff0c;获取外链css请参考上文&#xff0c;在hello uni-app项目中查看 --> <template><view><view class"uni-common-mt"><view class"uni-form-item uni-column"&g…

【C++】开源:跨平台轻量日志库easyloggingpp

&#x1f60f;★,:.☆(&#xffe3;▽&#xffe3;)/$:.★ &#x1f60f; 这篇文章主要介绍跨平台轻量日志库easyloggingpp。 无专精则不能成&#xff0c;无涉猎则不能通。。——梁启超 欢迎来到我的博客&#xff0c;一起学习&#xff0c;共同进步。 喜欢的朋友可以关注一下&am…

详细介绍Matlab中线性规划算法的使用

Matlab中提供了用于线性规划的优化工具箱&#xff0c;其中包含了多种算法&#xff0c;如单纯形法、内点法等。线性规划是一种优化问题&#xff0c;旨在找到一组变量的最佳值&#xff0c;以最大化或最小化线性目标函数&#xff0c;同时满足一组线性约束条件。 下面将详细介绍Ma…

【C++11】智能指针的定义 和 种类 及 使用

智能指针 定义 为什么需要智能指针 在C中&#xff0c;动态分配内存是一项常见的任务&#xff0c;但手动管理分配和释放内存可能会导致很多问题&#xff0c;如内存泄漏、悬垂指针以及多次释放同一块内存等。为了避免这些问题&#xff0c;引入了智能指针的概念&#xff0c;它们…

(笔记)插入排序

插入排序 插入排序是一种简单且常见的排序算法&#xff0c;它通过重复将一个元素插入到已经排好序的一组元素中&#xff0c;来达到排序的目的。在插入排序算法中&#xff0c;将待排序序列分为已排序和未排序两个部分。初始时&#xff0c;已排序部分只包含一个记录&#xff0c;…

LiveGBS流媒体平台GB/T28181功能-海康NVR摄像机自带物联网卡摄像头注册GB/T28181国标平台看不到设备的时候如何抓包及排查

海康大华宇视华为等硬件NVR摄像机注册到LiveGBS国标平台看不到设备的时候如何抓包及排查 1、设备注册后查看不到1.1、是否是自带物联网卡的摄像头1.2、关闭萤石云1.3、防火墙排查1.4、端口排查1.5、IP地址排查1.6、设备TCP/IP配置排查1.7、设备多网卡排查1.8、设备接入配置参数…

Docker(四)

文章目录 1. docker其他命令补充2. docker-registry使用3. docker-hub的使用4. 企业级私有仓库harbor4.1 harbor安装4.2 harbor配置https4.3 harbor常见使用4.3.1 harbor新建项目仓库4.3.2 harbor创建用户4.3.3 harbor仓库管理4.3.4 harbor复制管理4.3.5 harbor删除镜像 5. doc…

K8S下如何搭建eureka集群

背景 传统应用上云&#xff0c;基于传统应用需要考虑上云的方案和改造成本&#xff0c;这也是传统应用上云过程中的难点&#xff0c;本篇介绍3台eureka搭建的方案。 方案一 此方案借助了K8S中Service的一些功能。 这种方案是传统方案的简单迁移版本&#xff0c;比较易于理解…

深度学习:tf.keras实现模型搭建、模型训练和预测

在sklearn中&#xff0c;模型都是现成的。tf.Keras是一个神经网络库,我们需要根据数据和标签值构建神经网络。神经网络可以发现特征与标签之间的复杂关系。神经网络是一个高度结构化的图&#xff0c;其中包含一个或多个隐藏层。每个隐藏层都包含一个或多个神经元。神经网络有多…

【微信小程序】使用iView组件库中的icons资源

要在微信小程序中使用iView组件库中的icons资源&#xff0c;需要先下载并引入iView组件库&#xff0c;并按照iView的文档进行配置和使用。 以下是一般的使用步骤&#xff1a; 下载iView组件库的源码或使用npm安装iView。 在小程序项目的app.json文件中添加iView组件库的引入配…

mac端好用的多功能音频软件 AVTouchBar for mac 3.0.7

AVTouchBar是来自触摸栏的视听播放器&#xff0c;将跳动笔记的内容带到触摸栏&#xff0c;触摸栏可显示有趣的音频内容&#xff0c;拥有更多乐趣&#xff0c;以一种有趣的方式播放音乐&#xff0c;该软件支持多种音频播放软件&#xff0c;可在Mac上自动更改音乐~ 音频选择-与内…

Flask Bootstrap 导航条

(43条消息) Flask 导航栏&#xff0c;模版渲染多页面_U盘失踪了的博客-CSDN博客 (43条消息) 学习记录&#xff1a;Bootstrap 导航条示例_bootstrap导航栏案例_U盘失踪了的博客-CSDN博客 1&#xff0c;引用Bootstrap css样式&#xff0c;导航栏页面跳转 2&#xff0c;页面两列…

实验五 分支限界法

实验五 分支限界法 01背包问题的分治限界法的实现 剪枝函数 限界函数 1.实验目的 1、理解分支限界法的剪枝搜索策略&#xff0c;掌握分支限界法的算法框架 2、设计并实现问题&#xff0c;掌握分支限界算法。 2.实验环境 java 3.问题描述 给定n种物品和一背包。物品i的重…

Cesium态势标绘专题-位置点(标绘+编辑)

标绘专题介绍:态势标绘专题介绍_总要学点什么的博客-CSDN博客 入口文件:Cesium态势标绘专题-入口_总要学点什么的博客-CSDN博客 辅助文件:Cesium态势标绘专题-辅助文件_总要学点什么的博客-CSDN博客 本专题没有废话,只有代码,代码中涉及到的引入文件方法,从上面三个链…

企业微信在ios机型无法吊起打开个人信息页接口(openUserProfile)

wx.qy.openUserProfile({type: 1,//1表示该userid是企业成员&#xff0c;2表示该userid是外部联系人userid: "wmEQlEGwAAHxbWYDOK5u3Af13xlYAAAA", //可以是企业成员&#xff0c;也可以是外部联系人success: function(res) {// 回调} });遇到的问题&#xff1a;调用打…

动态规划入门第1课

1、从计数到选择 ---- 递推与DP&#xff08;动态规划&#xff09; 2、从递归到记忆 ---- 子问题与去重复运算 3、动态规划的要点 第1题 网格路1(grid1) 小x住在左下角(0,0)处&#xff0c;小y在右上角(n,n)处。小x需要通过一段网格路才能到小y家。每次&#xff0c;小x可以选…

macOS mysql 8.0 忘记密码

╰─➤ mysql -V mysql Ver 8.0.33 for macos13.3 on arm64 (Homebrew)mysql.server status mysql.server stopskip-grant-tables 启动mysql ─➤ /opt…

云计算和云架构是什么 有什么用途?

云计算是一种基于互联网的计算方式&#xff0c;它通过网络将计算资源(如计算能力、存储、网络带宽等)以服务的形式提供给用户&#xff0c;并允许用户根据需求进行灵活的资源调配和管理。云计算通常分为三个层次&#xff0c;即基础设施即服务(IaaS)、平台即服务(PaaS)和软件即服…

MongoDB常用语句

MongoDB常用语句 使用创建和删除查询条件查询模糊查询分页排序聚合两表连接 插入 使用 展示数据库 show dbs 或 show databases 查看当前在使用的数据库 db展示数据库下所有表 show collections 或 show tables;终端内容过多&#xff0c;用该指令清屏 cls创建和删除 如果…