学成在线第七天

保存发布信息、页面静态化

点击某课程数据后的 发布 链接(审核状态为通过),即可对该课程进行发布
在这里插入图片描述
需要使用的表:
在这里插入图片描述

YAPI文档:
在这里插入图片描述
代码展示:

web层

    //保存发布信息
    @PostMapping("/publish/{courseBaseId}")
    public ResponseResult saveCoursePubMessages(@PathVariable("courseBaseId") Long courseBaseId){
        return coursePubService.saveCoursePubMessages(courseBaseId);
    }

serviceImpl层

    @Autowired
    private BasicClient basicClient;
    @Autowired
    private TeachplanService teachplanService;
    @Autowired
    private CourseBaseMapper courseBaseMapper;
    @Autowired
    private CourseTeacherMapper courseTeacherMapper;
    @Autowired
    private Configuration configuration;
    @Autowired
    private MinioService minioService;

  @Override
    @Transactional
    public ResponseResult saveCoursePubMessages(Long courseBaseId) {
        //是否以前存在课程发布信息
        LambdaQueryWrapper<CoursePub> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(CoursePub::getCourseId,courseBaseId);
        CoursePub one1 = this.getOne(queryWrapper);
        if (one1 !=null){
            throw new BusinessException(ErrorCode.ADDEERROR);
        }
        //查询课程基本信息
        CourseBase one = courseBaseMapper.selectById(courseBaseId);
        if (one == null) {
            throw new BusinessException(ErrorCode.NOTFOUND);
        }
        one.setAuditStatus(CourseConstants.AUDIT_PUBLISHED_STATUS);
        courseBaseMapper.updateById(one);
        //查询课程计划信息
        LambdaQueryWrapper<Teachplan> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Teachplan::getCourseId, courseBaseId);
        List<Teachplan> teachplanList = teachplanService.list(wrapper);
        if (teachplanList.size() == 0) {
            throw new BusinessException(ErrorCode.NOTFOUND);
        }
        String teachplanJSON = JSON.toJSONString(teachplanList);
        //课程讲师信息
        LambdaQueryWrapper<CourseTeacher> qw = new LambdaQueryWrapper<>();
        qw.eq(CourseTeacher::getCourseId, courseBaseId);
        List<CourseTeacher> courseTeachers = courseTeacherMapper.selectList(qw);
        String courseTeachersJSON = "";
        if (courseTeachers.size() != 0) {
            courseTeachersJSON = JSON.toJSONString(courseTeachers);
        }
        CoursePub coursePub = BeanHelper.copyProperties(one, CoursePub.class);
        //补全信息
        coursePub.setCourseId(courseBaseId);
        coursePub.setTeachplan(teachplanJSON);
        if (StrUtil.isNotBlank(courseTeachersJSON)) {
            coursePub.setTeachers(courseTeachersJSON);
        }
        String mt = one.getMt();
        String st = one.getSt();
        //根据id,调用feign接口查询mt、st名称
        String mtName = getMtNameOrStName(mt);
        String stName = getMtNameOrStName(st);
        coursePub.setMtName(mtName);
        coursePub.setStName(stName);
        coursePub.setCreateDate(new Date());
        boolean save = this.save(coursePub);
        if (!save) {
            throw new BusinessException(ErrorCode.COURSEPUBSHRRROR);
        }
        ResponseResult<TeachplanVo> rr = teachplanService.treeNodes(courseBaseId);
        TeachplanVo teachplanVo = rr.getData();
        //生成html页面
        try {
            HashMap<String, Object> map = new HashMap<>();
            map.put("coursePub",coursePub);
            map.put("teachplanNode",teachplanVo);
            Template template = configuration.getTemplate("learing_article.ftl");
            String htmlStr = FreeMarkerTemplateUtils.processTemplateIntoString(template, map);
            ByteArrayInputStream inputStream = new ByteArrayInputStream(htmlStr.getBytes());
            String filename = courseBaseId + ".html";
            minioService.uploadFreemarkerHtmlByMinio(inputStream, filename);
        } catch (IOException | TemplateException e) {
            e.printStackTrace();
            System.out.println(e.getMessage());
        }
        return ResponseResult.okResult();
    }

效果展示:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在页面搜索:http://www.xuecheng.com/pages/47.html,查看生成的静态页面
在这里插入图片描述
时间问题
在这里插入图片描述

#安装ntpdate工具
yum -y install ntp ntpdate
#自动同步时间
ntpdate ntp.ubuntu.com

代码优化
以前是真没在意,我的代码又长又烂,= =现在优化以下

存在的问题:
在这里插入图片描述
同步:就是在发出一个调用时,在没有得到结果之前, 该调用就不返回

异步:调用在发出之后,这个调用就直接返回了,没有返回结果

常见的异步处理有两类:

  • 在同一应用(微服务)内部:使用多线程
  • 设计到夸应用调用(微服务调用):基于消息中间件

@Async是Spring提供的异步处理注解,被此注解标注的方法会在新的线程中执行,其实就相当于我们自己new Thread。此注解使用起来也比较简单。

  • 引导类中使用@EnableAsync注解开启异步调用
    在这里插入图片描述

  • 在方法上加上@Async注解(标明要异步调用)

将需要多线程处理的业务逻辑,抽取到一个新的java类中,配置方法。在方法上添加@Async注解

在这里插入图片描述

package com.xuecheng.content.service.impl;

import com.xuecheng.basic.api.BasicClient;
import com.xuecheng.content.mappers.CourseBaseMapper;
import com.xuecheng.content.mappers.CourseTeacherMapper;
import com.xuecheng.content.service.MinioService;
import com.xuecheng.content.service.PublishHtmlService;
import com.xuecheng.content.service.TeachplanService;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

@Service
public class PublishHtmlServiceImpl implements PublishHtmlService {
    @Autowired
    private Configuration configuration;
    @Autowired
    private MinioService minioService;

    @Override
    @Async
    public void publish(Map map, Long courseBaseId) {
        try {
            Template template = configuration.getTemplate("learing_article.ftl");
            String htmlStr = FreeMarkerTemplateUtils.processTemplateIntoString(template, map);
            ByteArrayInputStream inputStream = new ByteArrayInputStream(htmlStr.getBytes());
            String filename = courseBaseId + ".html";
            minioService.uploadFreemarkerHtmlByMinio(inputStream, filename);
        } catch (IOException | TemplateException e) {
            e.printStackTrace();
            System.out.println(e.getMessage());
        }
    }
}

修改CoursePubServiceImpl.class
在这里插入图片描述
效果演示:
需要删除之前的信息

发送MQ消息

课程发布对于该项目来说是一个核心业务,除了页面生成之外,一般都需要扩展其他操作,这些逻辑若都在课程发布中接入,那课程发布的实现将耦合所有下游业务。且下游模块出现问题,将会影响该核心业务。

  • 搜索服务:在门户网站使用ElasticSearch进行搜索,同步es索引
  • 短信服务:当订阅了某个教育机构,发布新课程时,会受到课程通知。
    在这里插入图片描述
    存在的问题:
  1. 耦合度高:每次加入新的需求,都要修改原来的代码
  2. 性能下降:调用者需要等待服务提供者响应,如果调用链过长则响应时间等于每次调用的时间之和。
  3. 资源浪费:调用链中的每个服务在等待响应过程中,不能释放请求占用的资源,高并发场景下会极度浪费系统资源
  4. 级联失败:如果服务提供者出现问题,所有调用方都会跟着出问题,如同多米诺骨牌一样,迅速导致整个微服务群故障

为了解决上诉问题,我们使用RabbitMQ消息中间件来完成。
在这里插入图片描述
访问mq:
管理后台地址:http://192.168.136.150:15672/

用户名/密码:guest/guest

和使用Mysql类似,Java代码操作时一般不会使用超级管理员账号

  • 一个项目分配一个账号
  • 一个项目分配一个虚拟主机
  • 分配此账号对此虚拟主机的操作权限
  • 本次课程:我们设置的用户名-密码-虚拟机均为xuecheng
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>

在这里插入图片描述

rabbitmq:
  host: 192.168.136.150
  virtual-host: xuecheng
  username: xuecheng
  password: xuecheng

在这里插入图片描述

发送消息

CoursePubServiceImpl:

    @Autowired
    private RabbitTemplate rabbitTemplate;
rabbitTemplate.convertAndSend("content-exchange","course.pub",coursePub.getId());

在这里插入图片描述
测试消息
在这里插入图片描述
在这里插入图片描述
编写监听器:
在这里插入图片描述

package com.xuecheng.search.listener;

import cn.hutool.log.Log;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

@Component
@Slf4j
public class MessageListener {

    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = "course.index.queue"),
            exchange = @Exchange(
                    value = "content-exchange",
                    type = ExchangeTypes.TOPIC
            ),
            key = "course.*"
    ))
    public void updateIndex(Long coursePubId){
        log.info("获取的课程发布id为:"+coursePubId);
        //更新es,下次做
    }
}

效果展示:
删除以前的数据,重新发布
在这里插入图片描述
今天的任务完成,突然觉得自己的代码写的跟shi山一样…
需要资料的私聊我

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

皇家小黄

创作不易!!!!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值