①分庫分表思想
文章表一對一為什么要拆分?因為文章的內容會非常大,查詢效率會很低,我們經常操作文章的基本信息,不會很經常查詢文章內容。充分發揮高頻數據的操作效率。?
②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);}}}