当前位置: 首页 > news >正文

校园选课助手【5】-解决Elasticsearch和MySQL同步

未优化前:课程检索库中的数据经过一次同步后固定不变,用户搜索到对应的课程后点击跳转到课程详情页面,进行选课

存在的问题:

  1. 用户使用不友好,搜索就是为了进行选课,应该返回对应课程的余量,如果没有余量了,进行友好提示,如果有余量,跳转到详情页面进行选课。
  2. 数据不一致,可能修改了课程信息,而检索库中的数据依旧没有更新。

解决方案:
引入消息队列,当CourseController将数据写入mysql后,需要自己再往MQ发条消息,说"数据更新了",EsController收到消息去更新索引库。

1.声明队列和交换机

@Configuration
public class MqConfig {//交换机名称public static final String EXCHANGE_NAME = "course.topic";//新增和修改队列public static final String INSERT_QUEUE_NAME = "course.insert.queue";//删除队列public static final String DELETE_QUEUE_NAME = "course.delete.queue";//RoutingKeypublic static final String INSERT_KEY = "course.insert";public static final String DELETE_KEY = "course.delete";@Beanpublic TopicExchange topicExchange(){return new TopicExchange(EXCHANGE_NAME,true,false);}@Beanpublic Queue insertQueue(){return new Queue(INSERT_QUEUE_NAME,true);}@Beanpublic Queue deleteQueue(){return new Queue(DELETE_QUEUE_NAME,true);}/*** 绑定队列和交换机关系*/@Beanpublic Binding insertQueueBinding(){return BindingBuilder.bind(insertQueue()).to(topicExchange()).with(INSERT_KEY);}@Beanpublic Binding deleteQueueBinding(){return BindingBuilder.bind(deleteQueue()).to(topicExchange()).with(DELETE_KEY);}

2.发送消息

import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;import java.security.InvalidParameterException;@RestController
@RequestMapping("Course")
public class courseController {@Autowiredprivate ICourseService courseService;@Autowiredprivate RabbitTemplate rabbitTemplate;@PostMappingpublic void saveCourse(@RequestBody Course course){courseService.save(course);rabbitTemplate.convertAndSend("course.topic","course.insert", course.getId());}@PutMapping()public void updateById(@RequestBody course course){if (course.getId() == null) {throw new InvalidParameterException("id不能为空");}courseService.updateById(course);// 发送MQ消息rabbitTemplate.convertAndSend("course.topic","course.insert", course.getId());}@DeleteMapping("/{id}")public void deleteById(@PathVariable("id") Long id) {courseService.removeById(id);// 发送MQ消息rabbitTemplate.convertAndSend("course.topic", "course.delete", id);}   
}

3.监听消息队列并进行处理


import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;import javax.annotation.Resource;@Component
public class CourseListener {@ResourceICourselService courseService;/*** 监听课程新增或者修改的业务* id接受一个Long,因为发送过来的是一个Long id*/@RabbitListener(queues = "course.insert.queue“)public void listenCourseInsertAndUpdate(Long id){CourseService.insertDocById(id);}/*** 监听课程删除业务*/@RabbitListener(queues = "course.delete.queue“)public void listenCourseDelete(Long id){CourseService.deleteDocById(id);}
}

4.实现上述service功能

新增或修改课程逻辑

  • 1)根据id查询课程数据Item
  • 2)将Item封装为ItemDoc
  • 3)将ItemDoc序列化为JSON
  • 4)创建IndexRequest,指定索引库名和id
  • 5)准备请求参数,也就是JSON文档
  • 6)发送请求

删除课程逻辑

  • 1)准备Request对象,因为是删除,这次是DeleteRequest对象。要指定索引库名和id
  • 3)发送请求。因为是删除,所以是client.delete()方法
import org.springframework.stereotype.Service;import javax.annotation.Resource;
import java.io.IOException;@Service
public class CourseService extends ServiceImpl<CourseMapper, Course> implements ICourseService {@ResourceRestHighLevelClient client;@Overridepublic void insertDocById(Long id) {try {//0.根据ID查数据,并转为文档类型Course Course = getById(id);CourseDoc CourseDoc = new CourseDoc(Course);//1.准备requestIndexRequest request = new IndexRequest("Course").id(CourseDoc.getId().toString());//2.准备DSLrequest.source(JSON.toJSONString(CourseDoc), XContentType.JSON);//3.发送请求client.index(request,RequestOptions.DEFAULT);} catch (IOException e) {throw new RuntimeException(e);}}@Overridepublic void deleteDocById(Long id) {try {//1.准备requestDeleteRequest request = new DeleteRequest("Course",id.toString());//2.发送请求client.delete(request,RequestOptions.DEFAULT);} catch (IOException e) {throw new RuntimeException(e);}}
}

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 无人机之保护野生动物篇
  • JS+H5打字练习器
  • JAVA-案列练习-ATM项目
  • DDOS攻击有哪些攻击手段?
  • linux内核,中断上下文,中断下半部的处理2种方法: tasklet_schedule,工作队列workqueue
  • docker安装与container基本使用
  • android 音频播放器,(一)SoundPool音频播放实例
  • linux 原子操作,信号量,互斥锁mutex,自旋锁splock
  • 嵌入式数据库 sqlite3
  • 中央处理器CPU
  • 力扣第五十题——Pow(x,n)
  • Linux中yum、rpm、apt-get、wget的区别,yum、rpm、apt-get常用命令,CentOS、Ubuntu中安装wget
  • 【Linux】-----进度条小程序
  • 计算机毕业设计选题推荐-课程教学辅助系统-Java/Python项目实战
  • 【教程】Python语言的地球科学常见数据——植被指数数据-GIMMS NDVI的处理
  • 自己简单写的 事件订阅机制
  • Angular 4.x 动态创建组件
  • const let
  • Docker容器管理
  • React-生命周期杂记
  • Shadow DOM 内部构造及如何构建独立组件
  • Tornado学习笔记(1)
  • v-if和v-for连用出现的问题
  • VuePress 静态网站生成
  • 纯 javascript 半自动式下滑一定高度,导航栏固定
  • 技术发展面试
  • 浅谈web中前端模板引擎的使用
  • 强力优化Rancher k8s中国区的使用体验
  • 如何正确配置 Ubuntu 14.04 服务器?
  • 项目管理碎碎念系列之一:干系人管理
  • - 语言经验 - 《c++的高性能内存管理库tcmalloc和jemalloc》
  • ​html.parser --- 简单的 HTML 和 XHTML 解析器​
  • # 再次尝试 连接失败_无线WiFi无法连接到网络怎么办【解决方法】
  • #预处理和函数的对比以及条件编译
  • (06)Hive——正则表达式
  • (3)llvm ir转换过程
  • (35)远程识别(又称无人机识别)(二)
  • (Arcgis)Python编程批量将HDF5文件转换为TIFF格式并应用地理转换和投影信息
  • (delphi11最新学习资料) Object Pascal 学习笔记---第13章第1节 (全局数据、栈和堆)
  • (js)循环条件满足时终止循环
  • (Matlab)使用竞争神经网络实现数据聚类
  • (web自动化测试+python)1
  • (简单) HDU 2612 Find a way,BFS。
  • (每日一问)操作系统:常见的 Linux 指令详解
  • (五)IO流之ByteArrayInput/OutputStream
  • (转)项目管理杂谈-我所期望的新人
  • . ./ bash dash source 这五种执行shell脚本方式 区别
  • .[hudsonL@cock.li].mkp勒索病毒数据怎么处理|数据解密恢复
  • .naturalWidth 和naturalHeight属性,
  • .NET CF命令行调试器MDbg入门(四) Attaching to Processes
  • .NET Core WebAPI中使用swagger版本控制,添加注释
  • .NET Core使用NPOI导出复杂,美观的Excel详解
  • .net wcf memory gates checking failed
  • .NET 使用 ILMerge 合并多个程序集,避免引入额外的依赖
  • .net(C#)中String.Format如何使用