课程发布
需求分析
课程发布后生成正式的课程详情页面,课程发布后用户即可浏览课程详情页面,并开始课程的学习.课程发布设工程课程详情也米娜的流程与课程预览业务流程相同,如下:
1.用户进入课程发布,进入某个课程管理界面
2.点击课程发布,前端请求到课程管理服务
3.课程管理服务远程调用CMS生成课程发布页面,CMS将课程详情页面发布到服务器
4课程管理服务修改课程发布状态为"已发布"
5.用户在教学管理中心点击"课程详情页面"链接,查看课程详情页面内容
CMS一键发布接口
需求分析
根据需求分析内容,需要在cms服务增加页面发布接口供课程管理服务调用,此接口的功能如下:
1.接收课程管理服务发布到页面信息
2.将页面信息添加到数据库(mongodb)
3.对页面信息进行静态化
4.将页面信息发布到服务器
接口定义
1.创建响应结果
页面发布成功cms返回页面的url
页面Url=cmSite.siteDomain+cmsSite.siteWebPath+cmsPage.pageWebPath+cmsPage.pageName
CmsPostPageResult类,继承ResponseResult,有一个pageUrl属性
package com.xuecheng.framework.domain.cms.response;
import com.xuecheng.framework.model.response.ResponseResult;
import com.xuecheng.framework.model.response.ResultCode;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author Andrewer
* @version 1.0
* @project xcEduService01
* @description
* @date 2022/12/20 22:55:39
*/
@Data
@NoArgsConstructor//要进行远程调用,就一定要添加无参构造
public class CmsPostPageResult extends ResponseResult {
private String pageUrl;
public CmsPostPageResult(ResultCode resultCode,String pageUrl){
super(resultCode);
this.pageUrl = pageUrl;
}
}
API一键发布功能
@ApiOperation("一键发布页面")
public CmsPostPageResult postPageQuick(CmsPage cmsPage);
CmsPageController:
@Override
@PostMapping("/postPageQuick")
public CmsPostPageResult postPageQuick(CmsPage cmsPage) {
return pageService.postPageQuick(cmsPage);
}
PageService:
//一键发布页面
public CmsPostPageResult postPageQuick(CmsPage cmsPage) {
// 将页面信息存储到cmspage集合中
CmsPageResult save = this.save(cmsPage);
if (!save.isSuccess()){
ExceptionCast.cast(CommonCode.FAIL);
}
// 得到页面的id
CmsPage cmsPageSave = save.getCmsPage();
String pageId = cmsPageSave.getPageId();
// 执行页面发布(先静态化,保存GridFs,向MQ发送消息)
ResponseResult post = this.post(pageId);
if (!post.isSuccess()){
ExceptionCast.cast(CommonCode.FAIL);
}
// 拼装页面Url=cmsSite.siteDomain+cmsSite.siteWebPath+cmsPage.pageName
String siteId = cmsPageSave.getSiteId();
CmsSite cmsSite = this.findCmsSiteById(siteId);
//拿到站点的信息之后,就可以拼装页面了
String pageUrl =cmsSite.ge tSiteDomain()+cmsSite.getSiteWebPath()+cmsPage.getPageName();
}
// 根据站点id查询站点信息
public CmsSite findCmsSiteById(String siteId){
Optional<CmsSite> optional = cmsSiteRepository.findById(siteId);
if (optional.isPresent()) {
return optional.get();
}
return null;
}
课程发布服务端
Api接口
@ApiOperation("课程发布")
public CoursePublishResult publish(String id);
Controller
@Override
@PostMapping("/publish/{id}")
public CoursePublishResult publish(@PathVariable("id") String id) {
return courseService.publish(id);
}
Service:
// 课程发布
@Transactional
public CoursePublishResult publish(String id) {
// 1.这个接口实现什么功能?
CmsPage cmsPage = new CmsPage();
cmsPage.setSiteId(publish_siteId);
cmsPage.setDataUrl(publish_dataUrlPre+id);
cmsPage.setPageName(id+".html");
cmsPage.setPageAliase(getCourseBaseById(id).getName());
cmsPage.setPagePhysicalPath(publish_page_physicalpath);
cmsPage.setPageWebPath(publish_page_webpath);
cmsPage.setTemplateId(publish_templateId);
// 1.调用cms一键发布接口,将课程详情页面发布到服务器中
CmsPostPageResult cmsPostPageResult = cmsPageClient.postPageQuick(cmsPage);
if (!cmsPostPageResult.isSuccess()) {
//如果不成功,就说明发布失败
return new CoursePublishResult(CommonCode.FAIL,null);
}
// 2.保存课程的发布状态为已发布
CourseBase courseBase = this.saveCoursePubState(id);
// 保存课程索引的一些信息
// 保存缓存的一些信息
//得到页面的url
String pageUrl = cmsPostPageResult.getPageUrl();
return new CoursePublishResult(CommonCode.SUCCESS,pageUrl);
}
// 更改课程状态为已发布 202002
private CourseBase saveCoursePubState(String courseId){
CourseBase courseBaseById = this.findCourseBaseById(courseId);
courseBaseById.setStatus("202002");
courseBaseRepository.save(courseBaseById);
return courseBaseById;
}
测试
启动Client
这里需要修改 队列名称,每个队列对应一种工作模式
启动cms
这里执行静态化和页面一键发布
启动courseManager
这里调用一键发布功能
在前端测试页面功能
调试信息
ElasticSearch介绍
介绍:
Elasticsearch 是位于 Elastic Stack 核心的分布式搜索和分析引擎。Logstash 和 Beats 有助于收集、聚合和丰富您的数据并将其存储在 Elasticsearch 中。Kibana 使您能够以交互方式探索、可视化和分享对数据的见解,并管理和监控堆栈。Elasticsearch 是索引、搜索和分析魔法发生的地方。
Elasticsearch 为所有类型的数据提供近乎实时的搜索和分析。无论您拥有结构化或非结构化文本、数字数据还是地理空间数据,Elasticsearch 都能以支持快速搜索的方式高效地存储和索引它。您可以超越简单的数据检索和聚合信息来发现数据中的趋势和模式。随着您的数据和查询量的增长,Elasticsearch 的分布式特性使您的部署能够随之无缝增长。
总结
1.elasticserarch 是一个基于Lucene的高拓展的分布式服务器,支持开箱即用
2.elasticsearch隐藏了Lucene的复杂性,对外提供Restful接口来操作索引,搜索
突出优点:
1.拓展性好处理PB(1024GB)数据
2.实时索引
es和solr选择哪个?
solr满足条件就不用换
公司准备大型全文检索,使用es,因为GitHub这样的大规模的搜索也在用
索引结构:
黑色硬件,黄色逻辑结构
倒排索引
根据词找文章
es在项目中的应用方式
解压es压缩包
配置在一个路径全英文的文件下
里面会有几个文件夹
在config中打开elisticseach.yml文件
#集群名称
cluster.name: xuecheng
#节点名称
node.name: xc_node_1
#配置绑定ip的地址,这里的0表示任何都可以访问
network.host: 0.0.0.0
#暴露的http端口,通过http访问的端口
http.port: 9200
#内部的交流端口,这两个端口没有关系
transport.tcp.port: 9300
#如果部署成为集群方式,会有主节点和数据节点
#这个是主节点
node.master: true
#数据节点
node.data: true
#两个集群节点
discovery.zen.ping.unicast.hosts: ["0.0.0.0:9300", "0.0.0.0:9301"]
#主节点数量的最少值
discovery.zen.minimum_master_nodes: 1
node.ingest: true
#锁住内存,避免与swap交换
bootstrap.memory_lock: false
node.max_local_storage_nodes: 1
path.data: D:\BaiduNetdiskDownload\es\elasticsearch-1\data
path.logs: D:\BaiduNetdiskDownload\es\elasticsearch-1\logs
http.cors.enabled: true
http.cors.allow-origin: /.*/
这里采用属性配置的方法
也可以采用idea中的分层方法都可以
配置完成后,在bin目录下打开执行文件
elasticseach.bat
文件
执行成功,
这里需要注意,确定好文件的权限,如果权限不允许,会出现闪退现象
访问路径,成功
es-head插件
解压成功后cmd
npm run start
就会执行插件
然后访问端口,得到页面
按住shift然后单击右键,就可以打开powerShell管理员命令窗口
创建索引库
索引库是一个逻辑概念,包括分词列表和文档列表,
在postman中发送信息
在head点击连接刷新信息,收到信息
也可以在head插件中的索引中创建
创建映射
概念说明
索引中的每个文档都有一个或者多个filed,创建映射,就是创建filed的过程,下边是document和filed与关系数据的概念类比:
文档(Document)-------------->Row记录
字段(Filed)---------------------->Columns列
在es6之前,还有type的概念,相当于关系型数据库中的表(Collection)
创建文档
Es中的文档,相当于MySql数据库表中的记录.
发送:put或者Post http://localhost:9200/xc_course/doc/id值
如果不指定id,会自动生成ID
发送后在head中可以看到
IK分词器
测试分词器
当前索引库引用的分词器:
分词中文文档,会将每个字作为一个词,无法有效的表示一个词语
所以引入ik分词器,注意版本要匹配,否则会出现不兼容的问题
导致es无法启动
将ik分词器的压缩包解压,F2为ik然后放置到es的plugin中
重新启动es即可
有两种模式,ik_max_word和ik_smart
自定义词库
可以在ik中的config总有一个配置文件ik的一个conf文件,在里面可以配置自己的词典,xxx.dic如果有文件夹,需要注意相对路径是以当前文件所在目录下为标准
然后引入dic词典,在dic词典中可以自己定义词语
映射
映射的维护方法
映射可以添加,但是一旦确定添加的类型,就不可以修改,如果想要取修改,就需要删除,然后重新添加
常用的映射类型
text文本字段
字符串包括text和keyword两种类型:
text可以分开索引,
keyword必须作为一整块被索引
一般在
“analyzer”:“ik_max_word”
“search_analyzer”:“ik_smart”
索引管理
搭建工程
ES客户端
有一点焦虑了…看看leetcode看看掘金,哎,生活呀.生活呀,生活呀.
为什么我这么弱小呢?我已经很努力了呀.
将文件资料中的xc-service-search 中的项目zip包下载到项目SERVICE中,然后再Construct中导入项目,项目里面除了启动类之外,还有一个类,ElasticSearchConfig类,类中定义了
RestHighLevelClient和RestClient两个Bean
在测试包下建一个测试类,
@Autowired两个类
进行测试
写入删除test
//
@Test
// 删除索引库
public void testDeleteIndex() throws IOException {
// 创建删除索引库
DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest("xc_andrew");
// 是用highClient删除
DeleteIndexResponse delete = restHighLevelClient.indices().delete(deleteIndexRequest);
// 确认返回值布尔类型
boolean acknowledged = delete.isAcknowledged();
// 输出布尔类型返回值
System.out.println(acknowledged);
}
删除成功
写入创建:
@Test
public void testCreateIndex() throws IOException {
CreateIndexRequest createIndexReques = new CreateIndexRequest("xc_andrew1");
createIndexReques.settings(Settings.builder().put("number_of_shards",1).put("number_of_replicas",0));
createIndexReques.mapping("doc","{\n" +
" \"properties\": {\n" +
" \"description\": {\n" +
" \"type\": \"text\",\n" +
" \"analyzer\": \"ik_max_word\",\n" +
" \"search_analyzer\": \"ik_smart\"\n" +
" },\n" +
" \"name\": {\n" +
" \"type\": \"text\",\n" +
" \"analyzer\": \"ik_max_word\",\n" +
" \"search_analyzer\": \"ik_smart\"\n" +
" },\n" +
" \"pic\": {\n" +
" \"type\": \"text\",\n" +
" \"index\": false\n" +
" },\n" +
" \"studymodel\": {\n" +
" \"type\": \"text\"\n" +
" }\n" +
" }\n" +
" }", XContentType.JSON);
CreateIndexResponse createIndexResponse = restHighLevelClient.indices().create(createIndexReques);
boolean acknowledged = createIndexResponse.isAcknowledged();
System.out.println(acknowledged);
}
创建成功
添加文档
// 添加文档
@Test
public void testAddDoc() throws IOException {
//
Map<String,Object>json = new HashMap<>();
json.put("name","spring,java实战");
json.put("description","本课程,主要从四个章节讲解:1.微服务架构入门,2.spring cloud基础入门 3.实战" +
"springBoot 4.注册中心eureka");
json.put("studymodel","201001");
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
json.put("timewstamp", dateFormat.format(new Date()));
json.put("price",5.6f);
IndexRequest indexRequest = new IndexRequest("xc_andrew1","doc");
indexRequest.source(json);
IndexResponse index = restHighLevelClient.index(indexRequest);
DocWriteResponse.Result result = index.getResult();
System.out.println(result);
}
添加成功
查询文档
// 查询文档
@Test
public void testGetDoc() throws IOException {
GetRequest getRequest = new GetRequest(
"xc_andrew1",
"doc",
"MssbOIUBEFeEJWJbnRof"
);
GetResponse documentFields = restHighLevelClient.get(getRequest);
boolean exists = documentFields.isExists();
Map<String, Object> sourceAsMap = documentFields.getSourceAsMap();
System.out.println(sourceAsMap);
}
查询成功
更新文档
// 更新文档
@Test
public void testUpdateDoc() throws IOException {
UpdateRequest updateRequest = new UpdateRequest("xc_andrew1",
"doc","MssbOIUBEFeEJWJbnRof");
Map<String,Object> json = new HashMap<>();
json.put("name","spring cluod 实战");
updateRequest.doc(json);
UpdateResponse update = restHighLevelClient.update(updateRequest);
boolean fragment = update.isFragment();
RestStatus status = update.status();
System.out.println(status );
}
删除文档
// 删除文档
@Test
public void testDeleteDoc() throws IOException {
DeleteRequest deleteRequest = new DeleteRequest("xc_andrew1","doc",
"MssbOIUBEFeEJWJbnRof");
DeleteResponse delete = restHighLevelClient.delete(deleteRequest);
RestStatus status = delete.status();
System.out.println(status);
}
删除成功