code

56 阅读4分钟

image.png

## 线程的使用方式

1、集成Thread

2、实现Runnable

3、实现Callable

4、创建线程池

5、@EnableAsync启动类 + @Async auditnews

@Async //使用异步执行当前方法

## 作业

@Async失效的场景

## 分布式环境下生成唯一不重复id

1UUID32位字母数字组合。不适合做主键

2、时间戳。YYYYMMddHHmmssSSSRRRR,23位数字

3、雪花算法。19位的long型数据。

4、使用第三方,redis,mongodb,Zookeeper

## 自媒体异步审核文章

在wmnewsserviceImpl中添加代码

保存文章成功后,异步调用审核代码
自媒体异步审核文章
在wmnewsserviceImpl中最后一个if添加代码
wmNewsAuditService.注入
保存文章成功后,异步调用审核代码

//       判断是否提交,如果不是提交 直接结束
        if(!dto.getDraft()){
//            如果是提交审核,异步 调用审核的代码
            log.info("异步提交,审核文章");//线程池
           threadpool wmNewsAuditService.auditWmNews(wmNews);
        }
service
package com.heima.wemedia.service.impl;

import com.heima.common.enums.AppHttpCodeEnum;
import com.heima.common.exception.LeadException;
import com.heima.common.util.BeanHelper;
import com.heima.feignclient.client.ArticleFeign;
import com.heima.model.media.dtos.WmNewsResultDTO;
import com.heima.wemedia.entity.WmNews;
import com.heima.wemedia.service.WmNewsAuditService;
import com.heima.wemedia.service.WmNewsService;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.swing.plaf.synth.SynthTextAreaUI;

@Slf4j
@Service
public class WmNewsAuditServiceImpl implements WmNewsAuditService {

    @Lazy //实现懒加载解决循环依赖
    @Autowired
    private WmNewsService wmNewsService;
    @Autowired
    private ArticleFeign articleFeign;

    @Override
    @GlobalTransactional(rollbackFor = Exception.class)
    @Async  //使用异步执行当前方法    
    怎么知道异步打印 log.info("开始审核文章");9003exec--->task1
    public void auditWmNews(WmNews wmNews) {
        log.info("开始审核文章");
//        判断状态是否待审核
        if(wmNews.getStatus()!=1){
            log.info("不是待审核状态,结束");
            return ;
        }
        Integer wmNewsId = wmNews.getId();
//        获取文章中的文本和图片
//        阿里云文本审核
//        阿里云图片审核
//        敏感词审核
//        根据id 修改文章状态, 1-> 8
        没有时间为null
        updateWmNewsStaus(wmNewsId,8,null,null);
//        如果有定时发布,并且没有到发布时间,不要发布,直接结束
        if(wmNews.getPublishTime() != null &&
                System.currentTimeMillis() < wmNews.getPublishTime().getTime()){
            log.info("没有到发布时间,结束");
            return ;
        }
//        对象转换
        WmNewsResultDTO newsResultDTO = BeanHelper.copyProperties(wmNews, WmNewsResultDTO.class);
   用   对象转换   自媒体都认识
//        发布文章,远程调用article服务
        try {
            Long articleId = articleFeign.saveArticle(newsResultDTO);
//        修改文章状态,改成-9
            updateWmNewsStaus(wmNewsId,9,null,articleId);
        }catch (Exception e){
            log.error("远程调用article保存文章,失败");
            e.printStackTrace();
            throw new LeadException(AppHttpCodeEnum.SERVER_ERROR);
        }
    }

    /**
     * 修改文章状态
     * @param wmNewsId
     * @param status  2- 审核不同通过 3- 待人工审核 8-审核通过
     * @param reason   2和3 的时候原因
     */
    private void updateWmNewsStaus(Integer wmNewsId, int status, String reason,Long articleId) {
        WmNews wmNews = new WmNews();
        wmNews.setId(wmNewsId);
        wmNews.setStatus(status);
        if(status == 2 || status==3) {
            wmNews.setReason(reason);
        }
        if(articleId != null){
            wmNews.setArticleId(articleId);
        }
        boolean b = wmNewsService.updateById(wmNews);
        if(!b){
            log.error("更新文章状态失败,wmNewsId={}",wmNewsId);
            throw new LeadException(AppHttpCodeEnum.SERVER_ERROR);
        }
    }
}
article创建文章
  ApArticle实体类添加注解
@TableId(value = "id",type = IdType.ASSIGN_ID)
private Long id;
ApArticleContent实体类添加注解
@TableId(value = "article_id",type = IdType.INPUT)
  @ApiModelProperty(value = "文章ID")
    private Long articleId;
controller    
package com.heima.article.controller;

import com.heima.article.service.ApArticleService;
import com.heima.article.service.impl.ApArticleServiceImpl;
import com.heima.model.media.dtos.WmNewsResultDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ArticleController {

    @Autowired
    private ApArticleService apArticleService;
    /**
     * 保存文章数据
     * @param dto
     * @return  文章articleId
     */
    @PostMapping("/api/v1/article/save")
    public Long saveArticle(@RequestBody WmNewsResultDTO dto){
        return apArticleService.saveArticle(dto);
    }
}

``
`

```js
service
service
package com.heima.article.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.heima.article.entity.ApArticle;
import com.heima.article.entity.ApArticleContent;
import com.heima.article.entity.ApAuthor;
import com.heima.article.mapper.ApArticleMapper;
import com.heima.article.service.ApArticleContentService;
import com.heima.article.service.ApArticleService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.article.service.ApAuthorService;
import com.heima.common.enums.AppHttpCodeEnum;
import com.heima.common.exception.LeadException;
import com.heima.common.util.BeanHelper;
import com.heima.model.media.dtos.WmNewsResultDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;

/**
 * <p>
 * 文章信息表,存储已发布的文章 服务实现类
 * </p>
 *
 * @author HM
 * @since 2022-09-15
 */
@Slf4j
@Service
public class ApArticleServiceImpl extends ServiceImpl<ApArticleMapper, ApArticle> implements ApArticleService {


    @Autowired
    private ApArticleContentService contentService;
    @Autowired
    private ApAuthorService apAuthorService;
    /**
     * 保存文章数据
     * 保存ap_article
     * 保存ap_article_content
     * @param dto
     * @return  文章articleId
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long saveArticle(WmNewsResultDTO dto) {
//        根据自媒体文章id查询article信息
        Integer wmNewsId = dto.getId();
        LambdaQueryWrapper<ApArticle> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ApArticle::getWmNewsId,wmNewsId);
        ApArticle article = getOne(queryWrapper);
//        保存/修改 文章表
        if(article==null){
//            新增   
            article  = BeanHelper.copyProperties(dto,ApArticle.class);
            article.setId(null);
//          属性拷贝   自媒体用户id 
            Integer wmUserId = dto.getWmUserId();
//            根据wmUserId,查询文章作者数据
            ApAuthor apAuthor = apAuthorService.getByWmUserId(wmUserId);
            if(apAuthor != null) {
                article.setAuthorId(apAuthor.getId());
                article.setAuthorName(apAuthor.getName());
            }
            没有初始值要设置
            article.setLayout(dto.getType());
            article.setFlag(0);
            article.setLikes(0L);
            article.setComments(0L);
            article.setViews(0L);
            article.setCollection(0L);
            article.setCreatedTime(new Date());
            article.setPublishTime(dto.getPublishTime()==null?new Date():dto.getPublishTime());
            article.setIsComment(true);
            article.setIsForward(true);
            article.setIsDelete(false);
            article.setIsDown(false);
            article.setWmNewsId(wmNewsId);
            boolean b = save(article);
            if(!b){
                log.error("新增文章失败,wmNewsId={}",wmNewsId);
                throw new LeadException(AppHttpCodeEnum.SERVER_ERROR);
            }
        }else{
            article.setTitle(dto.getTitle());
            article.setChannelId(dto.getChannelId());
            article.setChannelName(dto.getChannelName());
            article.setLabels(dto.getLabels());
            article.setImages(dto.getImages());
            article.setLayout(dto.getType());
            article.setPublishTime(dto.getPublishTime()==null?new Date():dto.getPublishTime());
//            修改
            boolean b = updateById(article);
            if(!b){
                log.error("修改文章失败,articleId={}",article.getId());
                throw new LeadException(AppHttpCodeEnum.SERVER_ERROR);
            }
        }
//        文章id 之前是小字段的
        Long articleId = article.getId();
        大字段的id
//        保存/修改文章内容表
        ApArticleContent apArticleContent = new ApArticleContent();
        apArticleContent.setArticleId(articleId);
        apArticleContent.setContent(dto.getContent());
        boolean b = contentService.saveOrUpdate(apArticleContent);
        if(!b){
            log.error("新增/修改文章内容失败,articleId={}",articleId);
            throw new LeadException(AppHttpCodeEnum.SERVER_ERROR);
        }
        return articleId;
    }
}
在ArticleFeign接口中添加方法
/**
 * 保存文章数据
 * @param dto
 * @return  文章articleId
 */
@PostMapping("/api/v1/article/save")
Long saveArticle(@RequestBody WmNewsResultDTO dto);
自媒体服务weeadia添加feign依赖
    <dependency>
    <groupId>com.heima</groupId>
    <artifactId>heima-leadnews-feign-api</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency> 
自媒体启动类添加注解  
@EnableFeignClients(basePackages = {"com.heima.feignclient.client"})    
## 业务总结

### 自动审核

1、修改自媒体文章的状态

2、调用第三方接口,审核文章的内容和图片

3、远程调用article服务,创建文章和内容

mybaitsplus自动生成@

   ApArticle实体类添加注解
@TableId(value = "id",type = IdType.ASSIGN_ID)
private Long id;

技术点

1、异步调用的方式,@EnableAsync + @Async

2、生成分布式环境唯一不重复id的方式,雪花算法

3MybatisPlus实体类标记主键,需要加注解@TableId

4、审核发布业务跨服务,需要是分布式事务

image.png