<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      # 第七章 自媒體文章審核

      目標

      • 能夠掌握自媒體文章審核的流程
      • 能夠使用阿里云安全服務檢測文章內容
      • 能夠完成自媒體文章審核的功能
      • 能夠完成自媒體發布文章與審核對接

      1 自媒體文章自動審核需求說明

      1.1 自媒體文章自動審核流程

      做為內容類產品,內容安全非常重要,所以需要進行對自媒體用戶發布的文章進行審核以后才能到app端展示給用戶。

      審核的流程如下:也可以查看當前講義文件夾下:day07-文章審核時序圖.pdf

      1615103638885

      解釋:

      1.當發生自媒體文章保存之后 發送消息給kafka
      2.運營管理平臺接收到消息之后 進行查詢自媒體文章信息
      3.查詢到圖片和文本內容
      4.調用反垃圾阿里云服務 并獲取結果
      5.再調用自定義的敏感詞進行審核
      6.獲取審核結果 分為3個情況
      	6.1 如果是block 則為拒絕 更新自媒體文章狀態2
      	6.2 如果是review 則為人工審核 更新自媒體文章狀態為3
      	6.3 如果是PASS 則更新狀態為 8 或者9 
      		6.3.1 有發布時間 則 更新為8
      		6.3.2 沒有發布時間 則 更新為9
      7.生成索引		
      

      1.2 表結構

      涉及到的表如下

      (1)1615103683878

      (2)文章表 文章配置表 文章內容表 作者表

      1615104000224

      (3)敏感詞表

      1615104044473

      2 文章審核功能實現

      2.1 實現思路分析

      1615127263031

      1.自媒體保存文章 發送消息給kafka 
      2.管理微服務進行接收消息獲取相關的信息 進行 審核
      3.通過feign調用進行處理即可。具體的流程參考時序圖
      

      具體的步驟如下:

      1 自媒體發送消息
      2 管理微服務接收消息
      	2.1 獲取到消息內容 通過Feign調用獲取自媒體文章信息
      	2.2 獲取文章的標題 和 內容中解析出來的文本 
      	2.3 獲取到文章的封面圖片和內容中解析出來的圖片
      	2.4 調用獲取阿里云反垃圾服務進行審核文本 和 審核圖片 以及調用管理微服務本身的敏感詞審核
      	2.5 判斷審核的結果
      		2.5.1 如果是Block  則 通過feign調用更新自媒體文章的狀態為2
      		2.5.2 如果是review 則 通過feign調用更新自媒體文章的狀態為3
      		2.5.3 如果是pass  
      			2.5.3.1 判斷發布時間是否有值 如果有  則通過feign調用更新自媒體文章的狀態為8
      			2.5.3.2 判斷發布時間是否有值 如果無  則通過feign調用更新自媒體文章的狀態為9
      	2.6 保存文章信息到 article庫中
          2.7 調用feign更新文章的ID 到自媒體文章表中
      

      2.2 功能實現

      步驟:

      1 先實現消息的發送和接收

      2 監聽端-獲取文章的信息

      3 獲取需要審核的文本和圖片

      4 進行自動審核

      5 判斷審核的狀態

      ? 5.1 如果是Block 則 通過feign調用更新自媒體文章的狀態為2
      ? 5.2 如果是review 則 通過feign調用更新自媒體文章的狀態為3
      ? 5.3 如果是pass
      ? 5.3.1 判斷發布時間是否有值 如果有 則通過feign調用更新自媒體文章的狀態為8
      ? 5.3.2 判斷發布時間是否有值 如果無 則通過feign調用更新自媒體文章的狀態為9

      ?

      2.2.1 實現消息發送和接收

      步驟:

      生產者端:
      (1)添加kafka依賴
      (2)修改yml 配置kafak生成者配置
      (3)修改保存文章的方法 添加發送消息
      消費者端:
      (1)添加kafak依賴
      (2)修改yml 配置消費者配置
      (3)添加監聽類 進行獲取
      
      2.2.1.1 生產者端

      (1)添加依賴:在自媒體微服務中添加

      <!-- kafka依賴 begin -->
      <dependency>
          <groupId>org.springframework.kafka</groupId>
          <artifactId>spring-kafka</artifactId>
      </dependency>
      <dependency>
          <groupId>org.springframework.kafka</groupId>
          <artifactId>spring-kafka-test</artifactId>
          <scope>test</scope>
      </dependency>
      

      (2)修改配置

        kafka:
          # 配置連接到服務端集群的配置項 ip:port,ip:port
          bootstrap-servers: 192.168.211.136:9092
          producer:
            batch-size: 16384
            buffer-memory: 33554432
            key-serializer: org.apache.kafka.common.serialization.StringSerializer
            retries: 10
            value-serializer: org.apache.kafka.common.serialization.StringSerializer
      

      1615128258498

      (3)修改方法 添加發送消息

      1615128298062

      //如果count >0 表示 成功  并且是 待審核狀態 的時候才需要
      if(count>0 && isSubmit==1){
          //同步發送消息
          kafkaTemplate.send(BusinessConstants.MqConstants.WM_NEWS_AUTO_SCAN_TOPIC,JSON.toJSONString(wmNews.getId()));
      }
      

      添加常量類值:

      1615128332495

       public static class ScanConstants{
              /**
               * 通過
               */
              public static final String PASS = "pass";
              /**
               * 拒絕
               */
              public static final String BLOCK="block";
              /**
               * 不確定
               */
              public static final String REVIEW="review";
      
          }
      

      1615128369153

      public static class MqConstants {
          /**
               * 文章自動審核
               */
          public static final String WM_NEWS_AUTO_SCAN_TOPIC = "wm.news.auto.scan.topic";
      
      }
      
      2.2.1.2 消費者端

      (1)添加依賴 :在admin微服務中添加

      <!-- kafka依賴 begin -->
      <dependency>
          <groupId>org.springframework.kafka</groupId>
          <artifactId>spring-kafka</artifactId>
      </dependency>
      <dependency>
          <groupId>org.springframework.kafka</groupId>
          <artifactId>spring-kafka-test</artifactId>
          <scope>test</scope>
      </dependency>
      

      (2)修改kafka配置

        kafka:
          # 配置連接到服務端集群的配置項 ip:port,ip:port
          bootstrap-servers: 192.168.211.136:9092
          consumer:
            auto-offset-reset: earliest
            group-id: test-consumer-group
            # 默認值即為字符串
            key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
            # 默認值即為字符串
            value-deserializer: org.apache.kafka.common.serialization.StringDeserializer
      

      1615128517975

      (3) 創建監聽類

      @Component
      public class MediaNewsAutoListener {
      
          @Autowired
          private WemediaNewsAutoScanService wemediaNewsAutoScanService;
      
          //監聽主題
          @KafkaListener(topics = BusinessConstants.MqConstants.WM_NEWS_AUTO_SCAN_TOPIC)
          public void recevieMessage(ConsumerRecord<?,?> record){
              if(record!=null){
                  String value = (String) record.value();
                  System.out.println(value);
                  try {
                      wemediaNewsAutoScanService.autoScanByMediaNewsId(Integer.valueOf(value));
                  } catch (Exception e) {
                      e.printStackTrace();
                  }
              }
          }
      }
      

      1615128669990

      (4)創建WemediaNewsAutoScanService接口和實現類:

      @Service
      public class WemediaNewsAutoScanServiceImpl implements WemediaNewsAutoScanService {
          @Override
          public void autoScanByMediaNewsId(Integer id) throws Exception {//數據需要進行同步
              System.out.println(id);
              //1 獲取文章信息
              //2 獲取審核的 文本 和 圖片
              //3 進行自動審核
              //4 判斷審核的狀態 進行更新
              //5 保存文章數據
              //6 更新文章的ID 
          }
      }
      
      //1 獲取文章信息
      //2 獲取審核的 文本 和 圖片
      //3 進行自動審核
      //4 判斷審核的狀態 進行更新
      //5 保存文章數據
      //6 更新文章的ID 
      

      2.2.2 實現監聽業務-獲取自媒體文章信息

      步驟:通過feign進行調用即可

      (1)admin端微服務引入依賴

      <!--添加自媒體feign相關-->
      <dependency>
          <groupId>com.itheima</groupId>
          <artifactId>itheima-leadnews-wemedia-api</artifactId>
          <version>1.0-SNAPSHOT</version>
      </dependency>
      

      1615128931878

      (2)創建feign

      1615129161564

      @FeignClient(name="leadnews-wemedia",path = "/wmNews",contextId ="wmNews")
      public interface WmNewsFeign extends CoreFeign<WmNews> {
      
      }
      

      (3)添加依賴 如果有添加則不需要再加了

      1615129207152

      (4)修改feign,如圖添加contextId 用于區分不同的業務

      1615129299975

      (5)實現類中調用

      1615129473414

      (6) 啟用feignclients

      1615130411250

      2.2.3 實現監聽業務-獲取審核的文本和圖片

      分析:由于有圖片和文本 而且 文本是在title 和content中有 圖片是封面和content也有,那么就需要解析出content中的圖片和文本 分別進行審核。

      編寫代碼如下

      //2.1 獲取文本圖片結合
      String content = wmNews.getContent();
      //2.2 獲取圖片合并列表
      List<String> imagesFromContent = getImagesFromContent(content, wmNews.getImages());
      //2.3獲取文本合并列表
      List<String> textFromContent = getTextFromContent(content, wmNews.getTitle());
      

      1615129640354

      獲取圖片

       //獲取圖片
          private List<String> getImagesFromContent(String content, String images) {
              //1.定義一個List 用來封裝所有的圖片路徑
              List<String> imagesAllList  = new ArrayList<String>();
              if(!StringUtils.isEmpty(content)) {
                  //2.將content 轉成 List<ContentNode>
                  List<ContentNode> contentNodes = JSON.parseArray(content, ContentNode.class);
      
                  //3.循環遍歷獲取到type類型為image的value的值 添加到list中
                  for (ContentNode contentNode : contentNodes) {
                      if(contentNode.getType().equals("image")){
                          imagesAllList.add(contentNode.getValue());
                      }
                  }
              }
              //images的數據格式:12345.jpg
              if(!StringUtils.isEmpty(images)) {
                  //4.將 images 添加list
                  String[] split = images.split(",");
                  List<String> imagesList = Arrays.asList(split);
                  imagesAllList.addAll(imagesList);
              }
              //5.返回list
              return imagesAllList;
          }
      

      獲取文本:

        //獲取文本
          private List<String> getTextFromContent(String content, String title) {
              //1.定義一個List 用來封裝所有的文本
              List<String> texts  = new ArrayList<String>();
      
              if(!StringUtils.isEmpty(content)) {
                  //2.將content 轉成 List<ContentNode>
                  List<ContentNode> contentNodes = JSON.parseArray(content, ContentNode.class);
                  //3.循環遍歷獲取到type類型為text的value的值 添加到list中
                  for (ContentNode contentNode : contentNodes) {
                      if (contentNode.getType().equals("text")) {
                          texts.add(contentNode.getValue());
                      }
                  }
              }
              //4.將title 添加list
              texts.add(title);
              //5.返回list
              return texts;
          }
      

      2.2.4 實現監聽業務-自動審核

      分析:

      根據文本列表 和 圖片地址列表 調用阿里云內容發垃圾服務進行審核,再調用本地敏感詞進行過濾 并返回結果即可
      

      (1)封裝審核的方法

      @Autowired
      private DfsFeign dfsFeign;
      
      @Autowired
      private GreenTextScan greenTextScan;
      
      @Autowired
      private GreenImageScan greenImageScan;
      
      @Autowired
      private AdSensitiveMapper adSensitiveMapper;
      
      //阿里云文本和圖片審核 以及 敏感詞審核
      private String scanTextAndImage(List<String> texts, List<String> images) throws Exception {
          //1審核文本
          if (texts != null) {
              Map map = greenTextScan.greeTextScan(texts);
              String result1 = getScanResult(map);
              //如果不成功 則直接返回 不需要執行了
              if (!result1.equals(BusinessConstants.ScanConstants.PASS)) {
                  return result1;
              }
          }
      
      
          //2 審核 圖片
          if (images != null) {
              List<byte[]> bytes = dfsFeign.downLoadFile(images);
              Map map = greenImageScan.imageScan(bytes);
              String result2 = getScanResult(map);
              //如果不成功 則直接返回 不需要執行了
              if (!result2.equals(BusinessConstants.ScanConstants.PASS)) {
                  return result2;
              }
          }
          if(texts!=null) {
              //3 審核敏感詞
              List<String> adSensitives = adSensitiveMapper.selectSensitives();
              //這個可以優化放到緩存中
              SensitiveWordUtil.initMap(adSensitives);
              //掃描并判斷是否正確DynamicServerListLoadBalancer
              for (String text : texts) {
                  Map<String, Integer> stringIntegerMap = SensitiveWordUtil.matchWords(text);
                  if (stringIntegerMap.size() > 0) {
                      return BusinessConstants.ScanConstants.BLOCK;
                  }
              }
          }
          //通過
          return BusinessConstants.ScanConstants.PASS;
      }
      
      //封裝
      private String getScanResult(Map map) {
          Object suggestion = map.get("suggestion");
          if (!suggestion.equals("pass")) {
              //有敏感詞
              if (suggestion.equals("block")) {
                  return BusinessConstants.ScanConstants.BLOCK;
              }
              //人工審核
              if (suggestion.equals("review")) {
                  return BusinessConstants.ScanConstants.REVIEW;
              }
          }
          //如果沒錯誤 返回成功
          return BusinessConstants.ScanConstants.PASS;
      }
      

      (2)創建dfsfeign 獲取圖片地址對應的的字節數組列表

      創建dfs-api工程,并創建feign

      1615130242357

      (3)dsf微服務中實現獲取字節數組返回

      @PostMapping("/downLoad")
      public List<byte[]> downLoadFile(@RequestBody List<String> images){
          List<byte[]> bytesList = new ArrayList<>();
          for (String image : images) {
              //解析路徑
              StorePath storePath = StorePath.parseFromUrl(image);
              //返回字節數組
              byte[] bytes = fastFileStorageClient.downloadFile(storePath.getGroup(), storePath.getPath(), new DownloadCallback<byte[]>() {
                  @Override
                  public byte[] recv(InputStream ins) throws IOException {
                      byte[] bytes1 = IOUtils.toByteArray(ins);
                      return bytes1;
                  }
              });
              bytesList.add(bytes);
          }
      
          return bytesList;
      }
      

      1615130334593

      (4)添加依賴到admin微服務中

      1615130444454

      (5)添加方法用于mapper查詢敏感詞

      1615130534126

      (6)調用方法 添加

      1615130606113

      2.2.5 實現監聽業務-狀態判斷

      根據上邊的分析思路如下:

      	2.5 判斷審核的結果
      		2.5.1 如果是Block  則 通過feign調用更新自媒體文章的狀態為2
      		2.5.2 如果是review 則 通過feign調用更新自媒體文章的狀態為3
      		2.5.3 如果是pass  
      			2.5.3.1 判斷發布時間是否有值 如果有  則通過feign調用更新自媒體文章的狀態為8
      			2.5.3.2 判斷發布時間是否有值 如果無  則通過feign調用更新自媒體文章的狀態為9
      

      添加代碼如下:

      switch (status) {
          // 如果是 拒絕 則更新狀態 為【審核失敗】
          case BusinessConstants.ScanConstants.BLOCK: {
              WmNews record = new WmNews();
              record.setId(id);
              record.setStatus(2);
              record.setReason("文本或圖片違規");
              wmNewsFeign.updateByPrimaryKey(record);
              break;
          }
          // 如果是 審核成功 則更新狀態根據情況來進行處理   1如果是發布時間為null 則 更新為9 ; 2: 如果是發布時間不為null 則更新為8
          case BusinessConstants.ScanConstants.PASS: {
              if (wmNews.getPublishTime() != null) {
                  WmNews record = new WmNews();
                  record.setId(id);
                  record.setStatus(8);
                  wmNewsFeign.updateByPrimaryKey(record);
              } else {
                  WmNews record = new WmNews();
                  record.setId(id);
                  record.setStatus(9);
                  wmNewsFeign.updateByPrimaryKey(record);
              }
              break;
          }
          // 如果是 不確定 則人工審核
          case BusinessConstants.ScanConstants.REVIEW: {
              WmNews record = new WmNews();
              record.setId(id);
              record.setStatus(3);
              wmNewsFeign.updateByPrimaryKey(record);
              break;
          }
          default:
              System.out.println("錯誤信息");
              break;
      }
      

      1615130731129

      2.2.6 實現監聽業務-文章信息進行保存

      步驟分析:

      (1)文章信息設計到的表為3張,并且還需要作者信息 所以我們可以定義一個dto對象包含相關屬性
      (2)定義feign 
      (3)實現feign
      (4)admin端進行feign調用
      	添加依賴
      	啟用feignclients
      	注入并進行調用	
      

      (1)定義dto對象

      @Data
      @Getter
      @Setter
      public class ArticleInfoDto {
          private ApArticle apArticle;
          private ApArticleContent apArticleContent;
          private ApArticleConfig apArticleConfig;
      }
      
      

      1615168461816

      (2)創建feign接口實現更新保存

      @FeignClient(name="leadnews-article",path = "/apArticle",contextId = "apArticle")
      public interface ApArticleFeign {
          //保存文章或者更新文章信息
          @PostMapping("/articleInfo/save")
          public Result<ApArticle> save(@RequestBody ArticleInfoDto articleInfoDto);
      }
      
      

      1615168517053

      另外也需要修改apAuthorFeign的配置如下:

      1615168551229

      (3)實現feign接口對應的業務邏輯:

      controller:

        //保存文章或者更新文章 用于遠程調用
          @PostMapping("/articleInfo/save")
          public Result<ApArticle> save(@RequestBody ArticleInfoDto articleInfoDto){
              ApArticle apArticle = apArticleService.saveArticle(articleInfoDto);
              return Result.ok(apArticle);
          }
      

      1615168617115

      service實現類:

       @Autowired
          private ApArticleMapper apArticleMapper;
          @Autowired
          private ApArticleConfigMapper apArticleConfigMapper;
          @Autowired
          private ApArticleContentMapper apArticleContentMapper;
      
      	//更新的情況不會存在,但是為了避免出現錯誤,我們可以進行更新
          @Override
          public ApArticle saveArticle(ArticleInfoDto articleInfoDto) {
              //1.獲取文章信息 判斷 是否有值
              ApArticle apArticle = articleInfoDto.getApArticle();
              //更新的
              if (apArticle.getId() != null) {
                  //更新文章
                  //apArticleMapper.updateById(apArticle);
      
                  //更新配置  不需要更新配置(是在文章審核通過之后進行的)
                 /* QueryWrapper<ApArticleConfig> wrapper1 = new QueryWrapper<ApArticleConfig>();
                  wrapper1.eq("article_id",apArticle.getId());
                  apArticleConfigMapper.update(articleInfoDto.getApArticleConfig(),wrapper1);*/
                  //更新內容
                 // QueryWrapper<ApArticleContent> wrapper2 = new QueryWrapper<ApArticleContent>();
                 // wrapper2.eq("article_id",apArticle.getId());
                  //apArticleContentMapper.update(articleInfoDto.getApArticleContent(),wrapper2);
              } else {
                  //添加
                  apArticle.setCreatedTime(LocalDateTime.now());
                  apArticleMapper.insert(apArticle);
      
                  ApArticleConfig apArticleConfig = articleInfoDto.getApArticleConfig();
                  apArticleConfig.setArticleId(apArticle.getId());
                  apArticleConfigMapper.insert(apArticleConfig);
      
                  ApArticleContent apArticleContent = articleInfoDto.getApArticleContent();
                  apArticleContent.setArticleId(apArticle.getId());
                  apArticleContentMapper.insert(apArticleContent);
              }
              return apArticle;
          }
      

      (4)admin微服務中添加依賴

      <!--添加文章相關api-->
      <dependency>
          <groupId>com.itheima</groupId>
          <artifactId>itheima-leadnews-article-api</artifactId>
          <version>1.0-SNAPSHOT</version>
      </dependency>
      

      (5)實現feign調用

      設置flag 表示當狀態為9的時候才能進行創建文章。

      1616772137384

      @Autowired
      private ApArticleFeign apArticleFeign;
      @Override
      public void autoScanByMediaNewsId(Integer id) throws Exception {
      
          //略
      
          if(flag) {
              //4.保存文章相關信息 并進行狀態同步 涉及到三個表 article article_content article_config
              ArticleInfoDto articleInfoDto = new ArticleInfoDto();
      
              ApArticle article = new ApArticle();
      
              //該值有可能為null
              if (wmNews.getArticleId() != null) {
                  article.setId(wmNews.getArticleId());
              }
              article.setTitle(wmNews.getTitle());
              //根據自媒體賬號獲取作者信息
              //自媒體賬號ID
              ApAuthor apAuthor = apAuthorFeign.getByWmUserId(wmNews.getUserId());
              if (apAuthor != null) {
                  article.setAuthorId(apAuthor.getId());
                  article.setAuthorName(apAuthor.getName());
              }
              //獲取頻道
              AdChannel adChannel = adChannelService.getById(wmNews.getChannelId());
              if (adChannel != null) {
                  article.setChannelId(adChannel.getId());
                  article.setChannelName(adChannel.getName());
              }
              //文章布局
              article.setLayout(wmNews.getType());
              //普通文章
              article.setFlag(0);
      
              article.setImages(wmNews.getImages());
      
              article.setLabels(wmNews.getLabels());
      
              if (wmNews.getPublishTime() != null) {
                  article.setPublishTime(wmNews.getPublishTime());
              }
              //同步狀態
              article.setSyncStatus(wmNews.getStatus());
              articleInfoDto.setApArticle(article);
      
      
              ApArticleConfig articleConfig = new ApArticleConfig();
              //設置默認值
              articleConfig.setIsDown(0);
              //設置默認值
              articleConfig.setIsDelete(0);
      
              articleInfoDto.setApArticleConfig(articleConfig);
      
      
              ApArticleContent articleContent = new ApArticleContent();
              //內容
              articleContent.setContent(wmNews.getContent());
      
              articleInfoDto.setApArticleContent(articleContent);
      
              //獲取到文章的ID
              Result<ApArticle> resultApArticle = apArticleFeign.save(articleInfoDto);
          }
          //略
      }
      

      代碼所在位置

      1615168992919

      還需要定義apAuthor的方法用于根據自媒體用戶的ID 獲取作者信息:

      /*@PostMapping
          public Result<ApAuthor> save(@RequestBody ApAuthor record);*/
      @GetMapping("/author/{wmUserId}")
      public ApAuthor getByWmUserId(@PathVariable(name="wmUserId") Integer wmUserId);
      

      1616834152662

      在文章微服務中進行“實現”接口:

      /**
           * 根據mw_user_id 獲取作者()
           * @param wmUserId  自媒體用戶的ID主鍵值
           * @return
           */
      @GetMapping("/author/{wmUserId}")
      public ApAuthor getByWmUserId(@PathVariable(name="wmUserId") Integer wmUserId){
          QueryWrapper<ApAuthor> queryWrapper = new QueryWrapper<ApAuthor>();
          queryWrapper.eq("wm_user_id",wmUserId);
          return apAuthorService.getOne(queryWrapper);
      }
      

      1616834199097

      2.2.7 實現監聽任務-實現文章ID更新到自媒體文章中

      
      ApArticle data = resultApArticle.getData();
      //獲取ID 更新到自媒體表當中
      Long articleId = data.getId();
      WmNews record = new WmNews();
      record.setId(id);
      record.setArticleId(articleId);
      
      wmNewsFeign.updateByPrimaryKey(record);
      
      

      1615169092914

      2.3 整體代碼如下

      package com.itheima.admin.service.impl;
      
      import com.alibaba.fastjson.JSON;
      import com.itheima.admin.mapper.AdSensitiveMapper;
      import com.itheima.admin.pojo.AdChannel;
      import com.itheima.admin.service.AdChannelService;
      import com.itheima.admin.service.WemediaNewsAutoScanService;
      import com.itheima.article.dto.ArticleInfoDto;
      import com.itheima.article.feign.ApArticleFeign;
      import com.itheima.article.feign.ApAuthorFeign;
      import com.itheima.article.pojo.ApArticle;
      import com.itheima.article.pojo.ApArticleConfig;
      import com.itheima.article.pojo.ApArticleContent;
      import com.itheima.article.pojo.ApAuthor;
      import com.itheima.common.constants.BusinessConstants;
      import com.itheima.common.pojo.Result;
      import com.itheima.common.util.GreenImageScan;
      import com.itheima.common.util.GreenTextScan;
      import com.itheima.common.util.SensitiveWordUtil;
      import com.itheima.dfs.feign.DfsFeign;
      import com.itheima.media.dto.ContentNode;
      import com.itheima.media.feign.WmNewsFeign;
      import com.itheima.media.feign.WmUserFeign;
      import com.itheima.media.pojo.WmNews;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.stereotype.Service;
      import org.springframework.util.StringUtils;
      
      import java.util.ArrayList;
      import java.util.Arrays;
      import java.util.List;
      import java.util.Map;
      
      /**
       * 自動審核
       *
       * @author ljh
       * @version 1.0
       * @date 2021/3/5 16:25
       * @description 標題
       * @package com.itheima.admin.service.impl
       */
      @Service
      public class WemediaNewsAutoScanServiceImpl implements WemediaNewsAutoScanService {
          @Autowired
          private WmNewsFeign wmNewsFeign;
      
          @Autowired
          private DfsFeign dfsFeign;
      
          @Autowired
          private GreenTextScan greenTextScan;
      
          @Autowired
          private GreenImageScan greenImageScan;
      
          @Autowired
          private AdSensitiveMapper adSensitiveMapper;
      
          @Autowired
          private ApArticleFeign apArticleFeign;
      
          @Autowired
          private ApAuthorFeign apAuthorFeign;
      
          @Autowired
          private AdChannelService adChannelService;
      
      
          @Override
          public void autoScanByMediaNewsId(Integer id) throws Exception {//數據需要進行同步
      
              //1.根據ID 獲取自媒體文章信息
              WmNews wmNews = wmNewsFeign.findById(id).getData();
              if (wmNews != null) {
                  //2.獲取審核的文本 和 圖片
                  //2.1 獲取文本圖片結合
                  String content = wmNews.getContent();
                  //2.2 獲取圖片合并列表
                  List<String> imagesFromContent = getImagesFromContent(content, wmNews.getImages());
                  //2.3獲取文本合并列表
                  List<String> textFromContent = getTextFromContent(content, wmNews.getTitle());
      
                  //3 進行自動審核
                  String status = scanTextAndImage(textFromContent, imagesFromContent);
      
                  //判斷是否狀態為9 如果是9 才需要進行創建文章 (在8的時候也不行,當后面我們實現功能XXL-JOB進行更新的時候 再進行調用)
                  boolean flag=false;
                  switch (status) {
                          // 如果是 拒絕 則更新狀態 為【審核失敗】
                      case BusinessConstants.ScanConstants.BLOCK: {
                          WmNews record = new WmNews();
                          record.setId(id);
                          record.setStatus(2);
                          record.setReason("文本或圖片違規");
                          wmNewsFeign.updateByPrimaryKey(record);
                          break;
                      }
                          // 如果是 審核成功 則更新狀態根據情況來進行處理   1如果是發布時間為null 則 更新為9 ; 2: 如果是發布時間不為null 則更新為8
                      case BusinessConstants.ScanConstants.PASS: {
                          if (wmNews.getPublishTime() != null) {
                              WmNews record = new WmNews();
                              record.setId(id);
                              record.setStatus(8);
                              wmNewsFeign.updateByPrimaryKey(record);
                          } else {
                              WmNews record = new WmNews();
                              record.setId(id);
                              record.setStatus(9);
                              flag=true;
                              wmNewsFeign.updateByPrimaryKey(record);
                          }
                          break;
                      }
                          // 如果是 不確定 則人工審核
                      case BusinessConstants.ScanConstants.REVIEW: {
                          WmNews record = new WmNews();
                          record.setId(id);
                          record.setStatus(3);
                          wmNewsFeign.updateByPrimaryKey(record);
                          break;
                      }
                      default:
                          System.out.println("錯誤信息");
                          break;
                  }
                  //4.保存文章相關信息 并進行狀態同步 涉及到三個表 article article_content article_config
                  if(flag) {
                      ArticleInfoDto articleInfoDto = new ArticleInfoDto();
      
                      ApArticle article = new ApArticle();
      
                      //該值有可能為null
                      if (wmNews.getArticleId() != null) {
                          article.setId(wmNews.getArticleId());
                      }
                      article.setTitle(wmNews.getTitle());
                      //根據自媒體賬號獲取作者信息
                      //自媒體賬號ID
                      ApAuthor apAuthor = apAuthorFeign.getByWmUserId(wmNews.getUserId());
                      if (apAuthor != null) {
                          article.setAuthorId(apAuthor.getId());
                          article.setAuthorName(apAuthor.getName());
                      }
                      //獲取頻道
                      AdChannel adChannel = adChannelService.getById(wmNews.getChannelId());
                      if (adChannel != null) {
                          article.setChannelId(adChannel.getId());
                          article.setChannelName(adChannel.getName());
                      }
                      //文章布局
                      article.setLayout(wmNews.getType());
                      //普通文章
                      article.setFlag(0);
      
                      article.setImages(wmNews.getImages());
      
                      article.setLabels(wmNews.getLabels());
      
                      if (wmNews.getPublishTime() != null) {
                          article.setPublishTime(wmNews.getPublishTime());
                      }
                      //同步狀態
                      article.setSyncStatus(wmNews.getStatus());
                      articleInfoDto.setApArticle(article);
      
      
                      ApArticleConfig articleConfig = new ApArticleConfig();
                      //設置默認值
                      articleConfig.setIsDown(0);
                      //設置默認值
                      articleConfig.setIsDelete(0);
      
                      articleInfoDto.setApArticleConfig(articleConfig);
      
      
                      ApArticleContent articleContent = new ApArticleContent();
                      //內容
                      articleContent.setContent(wmNews.getContent());
      
                      articleInfoDto.setApArticleContent(articleContent);
      
                      //獲取到文章的ID
                      Result<ApArticle> resultApArticle = apArticleFeign.save(articleInfoDto);
      
                      ApArticle data = resultApArticle.getData();
                      //獲取ID 更新到自媒體表當中
                      Long articleId = data.getId();
                      WmNews record = new WmNews();
                      record.setId(id);
                      record.setArticleId(articleId);
      
                      wmNewsFeign.updateByPrimaryKey(record);
                  }
      
              }
          }
      
         //獲取圖片
          private List<String> getImagesFromContent(String content, String images) {
              //1.定義一個List 用來封裝所有的圖片路徑
              List<String> imagesAllList  = new ArrayList<String>();
              if(!StringUtils.isEmpty(content)) {
                  //2.將content 轉成 List<ContentNode>
                  List<ContentNode> contentNodes = JSON.parseArray(content, ContentNode.class);
      
                  //3.循環遍歷獲取到type類型為image的value的值 添加到list中
                  for (ContentNode contentNode : contentNodes) {
                      if(contentNode.getType().equals("image")){
                          imagesAllList.add(contentNode.getValue());
                      }
                  }
              }
              //images的數據格式:12345.jpg
              if(!StringUtils.isEmpty(images)) {
                  //4.將 images 添加list
                  String[] split = images.split(",");
                  List<String> imagesList = Arrays.asList(split);
                  imagesAllList.addAll(imagesList);
              }
              //5.返回list
              return imagesAllList;
          }
      
          //獲取文本并合并
           private List<String> getTextFromContent(String content, String title) {
              //1.定義一個List 用來封裝所有的文本
              List<String> texts  = new ArrayList<String>();
      
              if(!StringUtils.isEmpty(content)) {
                  //2.將content 轉成 List<ContentNode>
                  List<ContentNode> contentNodes = JSON.parseArray(content, ContentNode.class);
                  //3.循環遍歷獲取到type類型為text的value的值 添加到list中
                  for (ContentNode contentNode : contentNodes) {
                      if (contentNode.getType().equals("text")) {
                          texts.add(contentNode.getValue());
                      }
                  }
              }
              //4.將title 添加list
              texts.add(title);
              //5.返回list
              return texts;
          }
      
      
          //阿里云文本和圖片審核 以及 敏感詞審核
          private String scanTextAndImage(List<String> texts, List<String> images) throws Exception {
              //1審核文本
              if (texts != null) {
                  Map map = greenTextScan.greeTextScan(texts);
                  String result1 = getScanResult(map);
                  //如果不成功 則直接返回 不需要執行了
                  if (!result1.equals(BusinessConstants.ScanConstants.PASS)) {
                      return result1;
                  }
              }
      
      
              //2 審核 圖片
              if (images != null) {
                  List<byte[]> bytes = dfsFeign.downLoadFile(images);
                  Map map = greenImageScan.imageScan(bytes);
                  String result2 = getScanResult(map);
                  //如果不成功 則直接返回 不需要執行了
                  if (!result2.equals(BusinessConstants.ScanConstants.PASS)) {
                      return result2;
                  }
              }
              if(texts!=null) {
                  //3 審核敏感詞
                  List<String> adSensitives = adSensitiveMapper.selectSensitives();
                  //這個可以優化放到緩存中
                  SensitiveWordUtil.initMap(adSensitives);
                  //掃描并判斷是否正確DynamicServerListLoadBalancer
                  for (String text : texts) {
                      Map<String, Integer> stringIntegerMap = SensitiveWordUtil.matchWords(text);
                      if (stringIntegerMap.size() > 0) {
                          return BusinessConstants.ScanConstants.BLOCK;
                      }
                  }
              }
              //通過
              return BusinessConstants.ScanConstants.PASS;
          }
      
          //封裝
          private String getScanResult(Map map) {
              Object suggestion = map.get("suggestion");
              if (!suggestion.equals("pass")) {
                  //有敏感詞
                  if (suggestion.equals("block")) {
                      return BusinessConstants.ScanConstants.BLOCK;
                  }
                  //人工審核
                  if (suggestion.equals("review")) {
                      return BusinessConstants.ScanConstants.REVIEW;
                  }
              }
              //如果沒錯誤 返回成功
              return BusinessConstants.ScanConstants.PASS;
          }
      
      }
      
      

      3 雪花算法

      ? 在我們機器越來越多的情況下,主鍵的生成策略 如果還是自增的話,那么就會在邏輯上出現主鍵不一致的情況。

      為了避免這種情況出現,我們可以采用雪花算法來生成主鍵,并且產生不重復的主鍵值。如下圖可以查看

      1615170013976

      mybatisplus已經為我們提供了該主鍵的生成策略,可以直接使用,對于文章來講,可能文章的數據是特別的多,所以文章信息我們可以采用此種解決方案。

      使用步驟很簡單 如下兩個步驟即可:

      1. 定義生成的策略
      
      2. 在微服務中進行配置
      

      1615170148765

      在article微服務中配置 datacenterid和workid

      1615170219592

      4 人工審核文章

      4.1 需求分析

      自媒體文章如果沒有自動審核成功,而是到了人工審核(自媒體文章狀態為3),需要在admin端人工處理文章的審核

      如圖所示:

      1615171344863

      管理員后臺 可以查看 【人工審核中】和【審核失敗】狀態下的文章信息,并且可以通過操作界面對某一個文章進行審核通過,和駁回。也就是審核失敗。
      

      需求如下:

      1 根據條件分頁查詢自媒體文章數據 前提條件 是查詢人工審核中 或者 審核失敗狀態下的文章信息
      2 查詢文章的詳情信息
      3 通過審核 
      4 駁回審核
      

      4.2 功能實現分析

      分析如下:

      由于有了admin網關 我們可以直接通過admin網關進行路由到自媒體微服務將數據列出返回即可。在這個查詢的過程中由于需求中需要有作者信息 那么就需要聯合查詢到對應的作者名稱。而作者名稱就是自媒體用戶的名稱。
      
      1.根據標題進行分頁查詢 自媒體文章信息 并且包含 人工審核中和審核失敗的文章
      2.審核通過
      3.審核失敗
      4.查看文章的詳情(需要作者的信息,之前的寫好的功能中沒有作者信息)
      

      1615173715240

      1615174113764

      1615174144678

      4.3 功能實現

      4.3.1 條件分頁查詢功能實現

      步驟:

      創建VO
      創建controller 實現條件分頁查詢以及查詢
      創建service
      創建mapper  
      

      (1) 創建VO 用于給前端進行展示 需要添加一些必要的字段

      @Data
      @Setter
      @Getter
      public class WmNewsVo extends WmNews {
          //作者名稱
          private String authorName;
      }
      

      1615174323386

      (2)創建controller 進行創建方法

      //條件分頁列表查詢
      @PostMapping("/vo/search")
      public Result<PageInfo<WmNewsVo>> searchByCondition(@RequestBody PageRequestDto<WmNews> pageRequestDto){
          //1.獲取條件
          //2.執行
          PageInfo<WmNewsVo> pageInfo = wmNewsService.pageForCondition(pageRequestDto);
          //4.返回結果
          return Result.ok(pageInfo);
      }
      

      (3)創建service實現類

      @Override
          public PageInfo<WmNewsVo> pageForCondition(PageRequestDto<WmNews> pageRequestDto) {
      
              String title ="";
              if (pageRequestDto.getBody()!=null && !StringUtils.isEmpty(pageRequestDto.getBody().getTitle())) {
                  title = "%"+pageRequestDto.getBody().getTitle()+"%";
              }
              Long page = pageRequestDto.getPage();
              Long size = pageRequestDto.getSize();
              //開始位置
              Long start = (page-1)*size;
              //每頁顯示的行
              List<WmNewsVo> wmNewsVos = wmNewsMapper.selectMyPage(start,size,title);
      
              Long total = wmNewsMapper.selectMyCount(title);
              //計算總頁數
              Long totalPages = total / size;
              if (total % size != 0) {
                  totalPages++;
              }
      
              PageInfo<WmNewsVo> pageInfo = new PageInfo<WmNewsVo>(page,size,total,totalPages,wmNewsVos);
      
              return pageInfo;
          }
      

      (4)mapper接口創建

      public interface WmNewsMapper extends BaseMapper<WmNews> {
      
          List<WmNewsVo> selectMyPage(@Param(value="start") Long start, @Param(value="size")Long size, @Param(value="title")String title);
      
          Long selectMyCount(@Param(value="title") String title);
      }
      

      (5)創建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.itheima.media.mapper.WmNewsMapper">
      
          <select id="selectMyPage" resultType="com.itheima.media.vo.WmNewsVo" parameterType="map">
              SELECT
              wn.*, wu.`name` as authorName
              FROM
                  wm_news wn
              LEFT JOIN wm_user wu ON wn.user_id = wu.id
              <where>
                  <if test="title!=null and title!=''">
                      and wn.title LIKE #{title}
                  </if>
                  and wn.status in (2,3)
              </where>
              LIMIT #{start}, #{size}
          </select>
          <select id="selectMyCount" resultType="java.lang.Long" parameterType="string">
              SELECT count(*)
              FROM
                  wm_news wn
              LEFT JOIN wm_user wu ON wn.user_id = wu.id
              <where>
                  <if test="title!=null and title!=''">
                      and wn.title LIKE #{title}
                  </if>
                  and wn.status in (2,3)
              </where>
          </select>
      </mapper>
      
      

      1615179378022

      (6)配置admin網關路由

      1615179528233

      整體配置yaml如下:

      spring:
        profiles:
          active: dev
      ---
      server:
        port: 6001
      spring:
        application:
          name: leadnews-admin-gateway
        profiles: dev
        cloud:
          nacos:
            server-addr: 192.168.211.136:8848
            discovery:
              server-addr: ${spring.cloud.nacos.server-addr}
          gateway:
            globalcors:
              cors-configurations:
                '[/**]': # 匹配所有請求
                  allowedOrigins: "*" #跨域處理 允許所有的域
                  allowedHeaders: "*"
                  allowedMethods: # 支持的方法
                    - GET
                    - POST
                    - PUT
                    - DELETE
            routes:
              # 平臺管理
              - id: admin
                uri: lb://leadnews-admin
                predicates:
                  - Path=/admin/**
                filters:
                  - StripPrefix= 1
              # 自媒體微服務
              - id: wemedia
                uri: lb://leadnews-wemedia
                predicates:
                  - Path=/media/**
                filters:
                  - StripPrefix= 1
      ---
      server:
        port: 6001
      spring:
        application:
          name: leadnews-admin-gateway
        profiles: test
        cloud:
          nacos:
            server-addr: 192.168.211.136:8848
            discovery:
              server-addr: ${spring.cloud.nacos.server-addr}
          gateway:
            globalcors:
              cors-configurations:
                '[/**]': # 匹配所有請求
                  allowedOrigins: "*" #跨域處理 允許所有的域
                  allowedHeaders: "*"
                  allowedMethods: # 支持的方法
                    - GET
                    - POST
                    - PUT
                    - DELETE
            routes:
              # 平臺管理
              - id: admin
                uri: lb://leadnews-admin
                predicates:
                  - Path=/admin/**
                filters:
                  - StripPrefix= 1
              # 自媒體微服務
              - id: wemedia
                uri: lb://leadnews-wemedia
                predicates:
                  - Path=/media/**
                filters:
                  - StripPrefix= 1
      ---
      server:
        port: 6001
      spring:
        application:
          name: leadnews-admin-gateway
        profiles: pro
        cloud:
          nacos:
            server-addr: 192.168.211.136:8848
            discovery:
              server-addr: ${spring.cloud.nacos.server-addr}
          gateway:
            globalcors:
              cors-configurations:
                '[/**]': # 匹配所有請求
                  allowedOrigins: "*" #跨域處理 允許所有的域
                  allowedHeaders: "*"
                  allowedMethods: # 支持的方法
                    - GET
                    - POST
                    - PUT
                    - DELETE
            routes:
              # 平臺管理
              - id: admin
                uri: lb://leadnews-admin
                predicates:
                  - Path=/admin/**
                filters:
                  - StripPrefix= 1
              # 自媒體微服務
              - id: wemedia
                uri: lb://leadnews-wemedia
                predicates:
                  - Path=/media/**
                filters:
                  - StripPrefix= 1
      

      4.3.2 實現文章審核通過和駁回

      1616510111931

      @Autowired
      private WmUserService wmUserService;
      //審核通過 或者 駁回  8 標識通過  2 標識駁回
      @PutMapping("/updateStatus/{id}/{status}")
      public Result updateStatus(@PathVariable(name="id")Integer id,@PathVariable(name="status") Integer status){
          if(status==8 || status==2){
              WmNews wmNews = new WmNews();
              wmNews.setId(id);
              wmNews.setStatus(status);
              wmNewsService.updateById(wmNews);
              return Result.ok();
          }else{
              return Result.errorMessage("錯誤的狀態值");
          }
      }
      

      4.3.3 實現文章詳情查詢

      1616510191620

      @Autowired
      private WmUserService wmUserService;
      @GetMapping("/vo/{id}")
      public Result<WmNewsVo> getVoById(@PathVariable(name="id")Integer id){
          //獲取文章信息
          WmNews wmNews = wmNewsService.getById(id);
          //獲取作者信息
          if(wmNews!=null) {
              WmUser wmUser = wmUserService.getById(wmNews.getUserId());
              //獲取到作者
              String name = wmUser.getName();
              WmNewsVo vo = new WmNewsVo();
              BeanUtils.copyProperties(wmNews,vo);
              vo.setAuthorName(name);
              return Result.ok(vo);
          }else{
              return Result.errorMessage("找不到對應的信息");
          }
      }
      

      4.4 測試

      查詢測試

      啟動微服務 和網關

      先登錄,

      1615180719357

      再實現查詢:

      1615180776049

      1615180797539

      駁回或者審核通過測試 以及查看文章詳情測試(略)。

      posted on 2022-04-25 00:48  ofanimon  閱讀(323)  評論(0)    收藏  舉報
      // 側邊欄目錄 // https://blog-static.cnblogs.com/files/douzujun/marvin.nav.my1502.css
      主站蜘蛛池模板: 久久人与动人物a级毛片 | 精品国产中文字幕av| 开心一区二区三区激情| 麻城市| 国产成年女人特黄特色大片免费 | 久久精品国产亚洲av麻豆长发| 国产在线精品一区二区三区| 欧美日韩国产亚洲沙发| 色悠悠国产精品免费观看| 精品国产av一二三四区| 免费无码黄十八禁网站| 91亚洲国产成人久久精| 97久久精品人人做人人爽| 国内精品大秀视频日韩精品| 国产一区二区三区四区激情| 精品国产午夜理论片不卡| 国内精品无码一区二区三区| 亚洲精品久久久久国色天香| 日韩乱码视频一区二区三区| 国产成人AV一区二区三区在线| 肇源县| 国产一区二区三区免费观看| 翘臀少妇被扒开屁股日出水爆乳| 澄迈县| 免费A级毛片无码A∨蜜芽试看| 精品久久久久久无码中文字幕 | 久久99九九精品久久久久蜜桃| 日韩中文免费一区二区| 免费播放一区二区三区| 国产成人亚洲精品狼色在线 | 狠狠躁夜夜躁无码中文字幕| 伊人春色激情综合激情网| 久久精品色妇熟妇丰满人| 精品一精品国产一级毛片| 国产一级小视频| 亚洲中文久久久精品无码| 海阳市| 精品久久久久久中文字幕202| 精品无码一区二区三区爱欲| 亚洲国产av无码精品无广告| 上栗县|