使用场景:
有时候需要解耦一些功能,比如点赞通知功能,点赞和通知这两个业务现在是关联在一起的,如果通知功能出错了,那么会导致前端点赞功能没有+1,即后者如果出错了会导致前者也失败
此时就可以使用异步线程让两个业务功能走两条线,解耦这两个业务
1.在启动类上加上@EnableAsync注解表示开启异步化
// 手动调整扫描包
@ComponentScan({"com.futureport"})
// 扫描mapper
@MapperScan("com.futureport.wiki.mapper")
@SpringBootApplication
@EnableScheduling
@EnableAsync
public class WikiApplication {
2.WsService.java里使用webSocketServer发送消息给前端
@Async注解表示为异步化执行该方法,即不是同一个线程执行
@Service
public class WsService {
@Resource
public WebSocketServer webSocketServer;
@Async
public void sendInfo(String message, String logId) {
MDC.put("LOG_ID",logId);
webSocketServer.sendInfo(message);
}
}
3.在DocService.java里调用点赞方法时通过wsService调用异步化方法
public void vote(Long id) {
// docMapperCust.increaseVoteCount(id);
// 远程IP+doc.id作为key,24小时内不能重复
String ip = RequestContext.getRemoteAddr();
if (redisUtil.validateRepeat("DOC_VOTE_" + id + "_" + ip, 3600 * 24)) {
docMapperCust.increaseVoteCount(id);
} else {
throw new BusinessException(BusinessExceptionCode.VOTE_REPEAT);
}
//推送消息
Doc docDb = docMapper.selectByPrimaryKey(id);
String logId = MDC.get("LOG_ID");
// 调用异步化方法
wsService.sendInfo("【"+docDb.getName()+"】被点赞!",logId);
}
注意异步化的方法必须在另一个文件里,否则做不到异步线程执行,异步推送消息时也使用唯一流水号作为日志信息便于运维查看