😎 知识点概览
为了方便后续回顾该项目时能够清晰的知道本章节讲了哪些内容,并且能够从该章节的笔记中得到一些帮助,所以在完成本章节的学习后在此对本章节所涉及到的知识点进行总结概述。
本章节为【学成在线】项目的 day10
的内容
- 课程发布功能开发
-
ElasticsSearch
安装部署 -
ElasticsSearch
快速入门、IK
分词器、映射、索引。
目录
内容会比较多,小伙伴们可以根据目录进行按需查阅。
一、课程发布
0x01 需求分析
课程发布后将生成正式的课程详情页面,课程发布后用户即可浏览课程详情页面,并开始课程的学习。课程发布生成课程详情页面的流程与课程预览业务流程相同,如下:
1、用户进入教学管理中心,进入某个课程的管理界面
2、点击课程发布,前端请求到课程管理服务
3、课程管理服务远程调用 CMS
生成课程发布页面,CMS
将课程详情页面发布到服务器
4、课程管理服务修改课程发布状态为 “已发布”,并向前端返回发布成功
5、用户在教学管理中心点击 “课程详情页面” 链接,查看课程详情页面内容
流程图如下
0x02 CMS一键发布接口
1、需求分析
根据需求分析内容,需要在 cms
服务增加页面发布接口供课程管理服务调用,此接口的功能如下:
1、接收课程管理服务发布的页面信息
2、将页面信息添加到 数据库**(mongodb)**
3、对页面信息进行静态化
4、将页面信息发布到服务器
2、接口定义
1、创建响应结果类型
页面发布成功cms返回页面的 url
页面 Url
= cmsSite.siteDomain
+ cmsSite.siteWebPath
+ cmsPage.pageWebPath
+ cmsPage.pageName
@Data
@NoArgsConstructor
public class CmsPostPageResult extends ResponseResult {
String pageUrl;
public CmsPostPageResult(ResultCode resultCode,String pageUrl){
super(resultCode);
this.pageUrl = pageUrl;
}
}
2、在 api
工程定义页面发布接口
/**
* 一键发布页面
*/
@ApiOperation("一键发布页面")
public CmsPostPageResult postPageQuick(CmsPage cmsPage);
3、Dao
/**
* 继承MongoDB自带的一些Repository
*/
public interface CmsSiteRepository extends MongoRepository<CmsSite,String{
}
4、Service
/**
* 一键发布页面
* @param cmsPage
* @return
*/
public CmsPostPageResult postPageQuick(CmsPage cmsPage) {
//添加页面,这里直接调用我们在做预览页面时候开发的保存页面方法
CmsPageResult cmsPageResult = this.saveCmsPage(cmsPage);
if(!cmsPageResult.isSuccess()){
//添加页面失败
return new CmsPostPageResult(CommonCode.FAIL,null);
}
CmsPage saveCmsPage = cmsPageResult.getCmsPage();
String pageId = saveCmsPage.getPageId();
//发布页面,通知cms client发布页面
ResponseResult responseResult = this.postPage(pageId);
if(!responseResult.isSuccess()){
//发布失败
return new CmsPostPageResult(CommonCode.FAIL,null);
}
//得到页面的url,页面url=站点域名+站点webpath+页面webpath+页面名称
//所以这里我们需要获取站点信息
String siteId = saveCmsPage.getSiteId();
Optional<CmsSite> cmsSiteOptional = cmsSiteRepository.findById(siteId);
if(!cmsSiteOptional.isPresent()){
//获取站点异常
return new CmsPostPageResult(CommonCode.FAIL,null);
}
CmsSite cmsSite = cmsSiteOptional.get();
//站点和页面的信息
String siteDomain = cmsSite.getSiteDomain();
String siteWebPath = cmsSite.getSiteWebPath();
String pageWebPath = saveCmsPage.getPageWebPath();
String pageName = saveCmsPage.getPageName();
//发布页面的访问地址
String pageUrl = siteDomain + siteWebPath + pageWebPath + pageName;
return new CmsPostPageResult(CommonCode.SUCCESS, pageUrl);
}
2、页面发布方法
5、Controller
/**
* 一键发布页面
* @param cmsPage
* @return
*/
@Override
@PostMapping("/postPageQuick")
public CmsPostPageResult postPageQuick(@RequestBody CmsPage cmsPage) {
return pageService.postPageQuick(cmsPage);
}
0x03 课程发布接口
1、API接口
@ApiOperation("课程发布")
public CoursePublishResult CoursePublish(String courseId);
2、创建Feign Client
定义一个远程调用的方法,用于远程调用刚才我们在 CMS 服务中定义的一键发布接口。
@FeignClient(value = "XC-SERVICE-MANAGE-CMS")
public interface CmsPageClient {
@PostMapping("/cms/page/postPageQuick")
CmsPostPageResult postPageQuick(@RequestBody CmsPage cmsPage);
}
3、Service
1、配置课程发布页面参数
新增课程详情页面的站点信息,如果已增加课程详情页面的站点则忽略此步骤。
向 mongodb
的 cms_site
中新增如下信息
{
"_id" : ObjectId("5b30b052f58b4411fc6cb1cf"),
"_class" : "com.xuecheng.framework.domain.cms.CmsSite",
"siteName" : "课程详情站点",
"siteDomain" : "http://www.xuecheng.com",
"sitePort" : "80",
"siteWebPath" : "/",
"siteCreateTime" : ISODate("2018-02-03T02:34:19.113+0000")
}
在 application.yml
中配置
course-publish:
siteId: 5b30b052f58b4411fc6cb1cf
templateId: 5e93d2e3d79e7d6ed1009b95
previewUrl: http://www.xuecheng.com/cms/preview/
pageWebPath: /course/detail/
pagePhysicalPath: G:/job/code/Project/XueChengOnline/xcEduUI01/xuecheng/static/course/detail/
dataUrlPre: http://localhost:31200/course/preview/model/
-
siteId
:站点id
-
templateId
:模板id
-
dataurlPre
:数据url
的前缀 -
pageWebPath
: 页面的web
访问路径 -
pagePhysicalPath
: 这个指的是页面要发布到nginx
服务器的物理路径,我们在配置文件中定义,可以动态调整,便于扩展。
2、service 方法如下
//拼装页面信息
private CmsPage setPageInfo(String courseId){
//获取课程信息
CourseBase courseBaseById = this.findCourseBaseById(courseId);
//拼装页面基本信息
CmsPage cmsPage = new CmsPage();
cmsPage.setDataUrl(publish_dataUrlPre + courseId);
cmsPage.setPagePhysicalPath(publish_page_physicalpath);
cmsPage.setPageWebPath(publish_page_webpath);
cmsPage.setSiteId(publish_siteId);
cmsPage.setTemplateId(publish_templateId);
cmsPage.setPageName(courseId + ".html");
//页面别名
cmsPage.setPageAliase(courseBaseById.getName());
return cmsPage;
}
/**
* 课程详细页面发布
*/
@Transactional
public CoursePublishResult coursePublish(String courseId){
//拼装页面信息
CmsPage cmsPage = setPageInfo(courseId);
//发布课程详细页面
CmsPostPageResult cmsPostPageResult = cmsPageClient.postPageQuick(cmsPage);
if(!cmsPostPageResult.isSuccess()){
return new CoursePublishResult(CommonCode.FAIL,null);
}
//更新课程状态
CourseBase courseBaseById = this.findCourseBaseById(courseId);
courseBaseById.setStatus("202002");
courseBaseRepository.save(courseBaseById);
//课程索引...
//课程缓存...
//页面url
String pageUrl = cmsPostPageResult.getPageUrl();
return new CoursePublishResult(CommonCode.SUCCESS,pageUrl);
}
4、Controller
/**
* 课程发布
* @param courseId
* @return
*/
@Override
@PostMapping("/publish/{id}")
public CoursePublishResult CoursePublish(@PathVariable("id") String courseId) {
return courseService.coursePublish(courseId);
}
5、接口测试
0x04 测试CMS一键发布接口
测试前准备工作
1、启动RabbitMQ
服务
2、启动 cms
、course
服务
3、启动 cms_client
,注意配置 routingKey
和队列名称,routingKey
为所使用的站点id
4、这里我们分别在 course
、cms
、cms client 三个服务内对应的地方打上断点,观察发布的流程
course
服务断点,我们设置在远程调用 cms 一键发布接口返回结果之后
cms 服务断点,在 一键发布接口 开始执行的地方我们打上断点
当 cms 客户端接收到 cms 通过 rabbitMQ 发送的消息后,会调用该方法将页面保存到 nginx 服务器的物理路径内
准备工作做完了,我们在 course 服务生成的 sawgger-ui 进行测试
发送请求后,我们在 idea 中可以看到,断点已经跑到了 cms 服务的一键发布接口
继续执行的话,cms
服务会调用 this.postPage
方法,获取该页面的 数据模型、以及模板数据,将数据静态化后得到完整的页面数据,并且写入到 GridFS
中;
写入 GridFS
后通过 rabbitMQ
发送消息到 cms client
,消息的内容包含一个页面id
,入下图,断点已经走到了 cms client
服务的 savePageToServerPath
方法中
``cms client接收到
pageId后,获取该页面数据的 fileId,通过该id到
GridFS` 中找到该页面的数据,并写入到页面的物理路径内,写入完成后,回到 cms 服务内拼装发布后的页面地址,再返回到 course 服务
course 服务接收到 cms 的响应,取出 pageUrl 返回到前端,如下图
回到 swagger ui,我们可以看到已经返回了一个发布成功的url
访问页面看下效果
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-W09QhrNt-1595564922590)(https://qnoss.codeyee.com/20200704_10/image11)]
0x05 前端页面开发与测试
1、页面开发
<el-card class="box-card">
<div slot="header" class="clearfix">
<span>课程发布</span>
</div>
<div class="text item">
<div v-if="course.status == '202001'">
状态:制作中<br/>
<el-button type="primary" @click.native="publish" >新课程发布</el-button>
</div>
<div v-else-if="course.status == '202003'">
状态:已下线
<br/><br/>
<span><a :href="'http://www.xuecheng.com/course/detail/'+this.courseid+'.html'" target="_blank">点我查看课程详情页面 </a> </span>
</div>
<div v-else-if="course.status == '202002'">
状态:已发布<br/>
<el-button type="primary" @click.native="publish" >修改发布</el-button>
<br/><br/>
<span><a :href="'http://www.xuecheng.com/course/detail/'+this.courseid+'.html'" target="_blank">点我查看课程详情页面 </a> </span>
</div>
</div>
</el-card>
2、获取课程状态
getCourseView(){
courseApi.findCourseView(this.courseid).then(res=>{
if(res){
//获取课程状态
this.course.status = res.status;
}
})
}
在页面初始化完成其前执行
mounted(){
//课程id
this