【Spring底层原理高级进阶】基于Spring Boot和Spring WebFlux的实时推荐系统的核心:响应式编程与 WebFlux 的颠覆性变革

 🎉🎉欢迎光临🎉🎉

🏅我是苏泽,一位对技术充满热情的探索者和分享者。🚀🚀

🌟特别推荐给大家我的最新专栏《Spring 狂野之旅:底层原理高级进阶》 🚀

本专栏纯属为爱发电永久免费!!!

这是苏泽的个人主页可以看到我其他的内容哦👇👇

努力的苏泽icon-default.png?t=N7T8http://suzee.blog.csdn.net/

最近在忙项目 好久没做知识积累了  这两天狂补一下

废话不多说 上正文

目录

1. 传统的Spring MVC架构的限制

2. 响应式编程的概念和优势

响应式编程的基本概念和原则:

响应式编程相对于传统编程模型的优势和特点:

响应式编程在异步、并发和响应性方面的优势

响应式编程的应用场景

 响应式编程的基本原理

事件驱动、数据流和异步编程的关系

响应式编程的调度和线程模型

引入依赖:在Maven或Gradle中引入Spring WebFlux的依赖,它是Spring框架中用于支持响应式编程的模块。创建控制器:使用@RestController注解创建一个响应式的控制器类,该类将处理HTTP请求并返回响应。在控制器方法中,可以使用响应式的数据类型,如Mono和Flux。

处理数据流:在上述示例中,Mono表示一个包含单个值的数据流,而Flux表示一个包含多个值的数据流。通过使用这些响应式类型,可以将数据流作为响应返回给客户端。

异步处理:Spring WebFlux使用基于事件驱动的非阻塞I/O模型来实现异步处理。它使用反应堆(Reactor)库提供的线程池和调度器来处理大量的并发操作,而不会阻塞主线程。

响应式反馈:在Spring WebFlux中,可以使用操作符和函数式编程的方式对数据流进行转换和处理。例如,可以使用map操作符对数据流中的元素进行转换,使用filter操作符对数据流进行过滤,以及使用flatMap操作符对多个数据流进行合并等。


1. 传统的Spring MVC架构的限制

  • 介绍传统的Spring MVC架构的基本原理和组件

传统的Spring MVC架构是一种基于Java的Web应用程序开发框架,它遵循了MVC(Model-View-Controller)设计模式。下面将介绍传统Spring MVC架构的基本原理和组件:

  1. 基本原理:

    • 请求处理流程:当用户发送一个HTTP请求时,Spring MVC的前端控制器(Front Controller)接收到请求并将其分发给相应的处理器(Handler)进行处理。处理器可以是一个控制器类或者一个处理器方法。处理器执行业务逻辑后,生成一个模型(Model)对象和视图名称(View Name)。
    • 视图解析和渲染:模型和视图名称被传递给视图解析器(View Resolver),它根据视图名称解析出具体的视图对象。视图对象负责将模型数据渲染成最终的响应结果,通常是HTML页面或其他格式的数据。
  2. 组件:

    • 前端控制器(DispatcherServlet):作为整个框架的核心组件,负责接收所有的HTTP请求并进行分发。它是应用程序的入口点,协调其他组件的工作。
    • 处理器映射器(Handler Mapping):根据请求的URL路径或其他条件,将请求映射到相应的处理器。它可以根据配置文件或注解来进行请求映射的定义。
    • 处理器(Handler):处理器是实际执行业务逻辑的组件,可以是一个控制器类或者一个处理器方法。它接收请求参数、处理业务逻辑,并生成模型数据和视图名称。
    • 处理器适配器(Handler Adapter):处理器适配器负责将具体的处理器包装成一个可执行的处理器对象,以便前端控制器能够调用它的方法来处理请求。
    • 视图解析器(View Resolver):视图解析器根据视图名称解析出具体的视图对象,通常是一个JSP页面或其他模板文件。它可以根据配置文件或注解来进行视图解析的定义。
    • 视图(View):视图负责将模型数据渲染成最终的响应结果,通常是HTML页面或其他格式的数据。视图可以是JSP页面、Thymeleaf模板、Freemarker模板等。

总结起来,传统的Spring MVC架构通过前端控制器(DispatcherServlet)、处理器映射器(Handler Mapping)、处理器(Handler)、处理器适配器(Handler Adapter)、视图解析器(View Resolver)和视图(View)等组件,实现了请求的分发和处理,以及模型数据到视图的渲染过程。这种架构模式使得开发人员能够将业务逻辑和视图层分离,提高了代码的可维护性和可测试性。

  • 分析传统架构在高并发和大规模数据处理场景下的限制
  • 探讨为什么需要一种更加灵活和高效的编程模型

2. 响应式编程的概念和优势

  • 解释响应式编程的基本概念和原则

当谈论响应式编程的概念和优势时,以下是一些示例代码和解释,以帮助说明响应式编程的基本概念和原则,以及相对于传统编程模型的优势和特点。

  1. 响应式编程的概念和优势:

    • 响应式编程是一种基于异步数据流的编程范式,通过使用观察者模式和函数式编程的概念,实现了事件驱动和数据流驱动的编程风格。
    • 响应式编程的优势在于它可以提供更好的异步性能、并发处理能力和响应性能,以及更简洁、可维护和可扩展的代码。
  2. 响应式编程的基本概念和原则:

    • 观察者模式:响应式编程使用观察者模式来处理数据流。数据源(Observable)发布数据,并通知所有订阅者(Observer)进行处理。
    • 数据流:数据在应用程序中以流的形式传播,可以是单个值或一系列值的序列。数据流可以进行转换、过滤和组合等操作。
      // 引入RxJS库
      const { from, interval } = require('rxjs');
      const { map, filter, mergeMap } = require('rxjs/operators');// 创建一个数据流
      const dataStream = from([1, 2, 3, 4, 5]);// 使用响应式操作符进行转换和过滤
      const modifiedStream = dataStream.pipe(map(value => value * 2), // 将每个值乘以2filter(value => value > 5) // 过滤掉小于等于5的值
      );// 订阅数据流并处理结果
      modifiedStream.subscribe(value => {console.log('处理结果:', value);},error => {console.error('处理错误:', error);},() => {console.log('处理完成');}
      );// 异步处理示例
      const asyncDataStream = interval(1000); // 每秒生成一个递增的值const asyncModifiedStream = asyncDataStream.pipe(mergeMap(value => {// 模拟异步操作,延迟一秒后返回处理结果return new Promise(resolve => {setTimeout(() => {resolve(value * 3); // 将值乘以3作为处理结果}, 1000);});})
      );asyncModifiedStream.subscribe(value => {console.log('异步处理结果:', value);},error => {console.error('异步处理错误:', error);},() => {console.log('异步处理完成');}
      );// 响应式反馈示例
      const feedbackStream = from([1, 2, 3]);feedbackStream.subscribe(value => {console.log('接收到数据:', value);if (value === 3) {// 当数据为3时触发响应式反馈,打印反馈消息console.log('触发响应式反馈');}
      });

    • 响应式操作符:响应式编程提供了一组操作符,如map、filter、reduce等,用于对数据流进行处理和转换。
      Spring Reactor提供了丰富的操作符,用于对数据流进行转换、过滤、合并等操作。这些操作符包括mapfilterflatMapconcatmerge等,可以通过链式组合的方式形成复杂的数据流处理逻辑。例如:
      Flux<Integer> dataStream = Flux.just(1, 2, 3, 4, 5);Flux<Integer> modifiedStream = dataStream.map(value -> value * 2)  // 将每个值乘以2.filter(value -> value > 5);  // 过滤掉小于等于5的值

       
    • 异步:响应式编程鼓励使用异步操作,以避免阻塞线程和提高并发性能。Spring Reactor支持异步处理,可以在不阻塞主线程的情况下处理大量的并发操作。通过使用异步操作符,例如subscribeOnpublishOn,可以将操作转移到其他线程池中执行,从而提高应用程序的性能和响应能力。
      Flux<Integer> asyncDataStream = Flux.range(1, 10).map(value -> {// 模拟耗时操作try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}return value * 2;}).subscribeOn(Schedulers.elastic());asyncDataStream.subscribe(value -> {System.out.println("异步处理结果: " + value);
      });

    • 响应式调度器:通过使用调度器,可以控制数据流操作在不同线程上的执行,实现并发处理和响应性能的优化。在响应式编程中,响应式反馈鼓励组件之间的反馈机制,当数据流发生变化时,可以自动触发相关的操作和逻辑。在Spring框架中,可以通过使用FluxMono类型的数据流以及订阅操作来实现响应式反馈。
      Flux<Long> intervalStream = Flux.interval(Duration.ofSeconds(1));intervalStream.subscribe(value -> {System.out.println("接收到数据: " + value);if (value == 3) {System.out.println("触发响应式反馈");}
      });

  3. 响应式编程相对于传统编程模型的优势和特点:

    • 异步性能:响应式编程通过使用异步操作和非阻塞的方式处理数据流,提供了更好的异步性能。以下是一个使用响应式编程处理异步任务的示例代码:
      Observable.fromCallable(() -> {// 执行异步任务return result;
      })
      .subscribeOn(Schedulers.io())
      .observeOn(Schedulers.single())
      .subscribe(result -> {// 处理任务结果},error -> {// 处理错误}
      );

  • 响应式编程在异步、并发和响应性方面的优势

  • 异步处理:响应式编程通过使用异步操作,能够更好地处理并发任务,避免阻塞和等待,提高系统的吞吐量。
  • 并发性:响应式编程利用数据流的方式,可以同时处理多个请求和事件,充分利用系统资源,提高并发处理能力。
  • 响应性能:响应式编程的实时数据处理方式,能够快速响应输入事件,提供更好的用户体验和系统响应性能。

响应式编程的应用场景

响应式编程在以下场景中具有广泛的应用:

  • 响应式Web开发:处理大量并发请求,实时更新UI,处理实时数据流等。
  • 大数据处理:处理大规模数据集,进行数据流处理和实时分析。
  • 事件驱动系统:处理异步事件和消息,实现松耦合的组件通信。
  • 实时流处理:处理实时数据流,进行流式计算和实时决策。
  • 物联网应用:处理异步传感器数据,实现实时监控和控制。

 响应式编程的基本原理

事件驱动、数据流和异步编程的关系

事件驱动、数据流和异步编程是响应式编程的关键概念和组成部分。

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;// 事件驱动编程示例
class Event {private String data;public Event(String data) {this.data = data;}public String getData() {return data;}
}interface EventHandler {void handleEvent(Event event);
}class EventProducer {private List<EventHandler> handlers = new ArrayList<>();public void addHandler(EventHandler handler) {handlers.add(handler);}public void removeHandler(EventHandler handler) {handlers.remove(handler);}public void produceEvent(Event event) {for (EventHandler handler : handlers) {handler.handleEvent(event);}}
}class EventConsumer implements EventHandler {@Overridepublic void handleEvent(Event event) {System.out.println("Event consumed: " + event.getData());}
}// 数据流示例
class DataStream<T> {private List<T> data = new ArrayList<>();public void addData(T value) {data.add(value);}public void processData(DataProcessor<T> processor) {for (T value : data) {processor.process(value);}}
}interface DataProcessor<T> {void process(T value);
}class StringProcessor implements DataProcessor<String> {@Overridepublic void process(String value) {System.out.println("Processing string: " + value);}
}// 异步编程示例
public class AsyncProgrammingExample {public static void main(String[] args) {// 创建事件生产者和消费者EventProducer producer = new EventProducer();EventConsumer consumer = new EventConsumer();producer.addHandler(consumer);// 产生事件Event event = new Event("Event 1");producer.produceEvent(event);// 创建数据流并处理数据DataStream<String> stream = new DataStream<>();stream.addData("Data 1");stream.addData("Data 2");stream.addData("Data 3");DataProcessor<String> processor = new StringProcessor();stream.processData(processor);// 异步操作示例CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {// 模拟耗时操作try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}return "Async Result";});future.thenAccept(result -> {System.out.println("Async operation completed: " + result);});System.out.println("Main thread continues...");}
}

 

  • 事件驱动编程:通过EventProducerEventConsumer来展示事件的触发和处理。EventProducer产生一个事件,然后将其传递给所有注册的EventHandler(在此示例中只有一个EventConsumer)进行处理。

  • 数据流:通过DataStreamDataProcessor来展示数据流的操作。DataStream可以添加数据,并通过processData方法将数据传递给注册的DataProcessor(在此示例中是StringProcessor)进行处理。

  • 异步编程:通过CompletableFuture来展示异步操作。在示例中,我们使用supplyAsync方法模拟一个耗时的异步操作,然后使用thenAccept方法在操作完成后处理结果。

响应式编程的调度和线程模型

响应式编程中的调度和线程模型是为了处理异步操作和并发操作而设计的。

调度是指确定某个操作在什么时候执行的过程。在响应式编程中,可以使用调度器(Scheduler)来管理操作的执行时机,包括指定在哪个线程或线程池中执行操作,以及操作的优先级和顺序。

线程模型是指应用程序中多个线程之间的关系和交互方式。在响应式编程中,通常使用事件循环或线程池来管理线程的执行。事件循环模型使用单个线程顺序执行任务,而线程池模型使用多个线程并行执行任务。选择合适的线程模型可以根据应用程序的需求来平衡性能和资源消耗。

响应式编程的调度和线程模型需要根据具体的应用场景和需求来进行选择和配置。

  • 响应式编程是一种以数据流和变化传播为核心的编程范式。其基本原理是将应用程序的各个组件和操作定义为数据流的操作符,通过订阅和触发事件的方式,实现组件之间的响应式交互。

    响应式编程的设计思想包括以下几个方面:

  • 数据流:响应式编程将应用程序中的数据和状态抽象为数据流,数据流可以是单个的值,也可以是一系列的值。组件之间通过订阅和触发数据流的方式进行交互。

  • 响应式操作符:响应式编程提供了丰富的操作符,用于对数据流进行转换、过滤、合并等操作。这些操作符可以链式组合,形成复杂的数据流处理逻辑。

  • 异步处理:响应式编程支持异步处理,能够在不阻塞主线程的情况下处理大量的并发操作。通过异步处理,可以提高应用程序的性能和响应能力。

  • 响应式反馈:响应式编程鼓励组件之间的反馈机制,当数据流发生变化时,可以自动触发相关的操作和逻辑。





    引入依赖:在Maven或Gradle中引入Spring WebFlux的依赖,它是Spring框架中用于支持响应式编程的模块。

    创建控制器:使用@RestController注解创建一个响应式的控制器类,该类将处理HTTP请求并返回响应。在控制器方法中,可以使用响应式的数据类型,如MonoFlux
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;@RestController
public class ReactiveController {@GetMapping("/hello")public Mono<String> hello() {return Mono.just("Hello, World!");}@GetMapping("/numbers")public Flux<Integer> numbers() {return Flux.range(1, 10);}
}

处理数据流:在上述示例中,Mono表示一个包含单个值的数据流,而Flux表示一个包含多个值的数据流。通过使用这些响应式类型,可以将数据流作为响应返回给客户端。

异步处理:Spring WebFlux使用基于事件驱动的非阻塞I/O模型来实现异步处理。它使用反应堆(Reactor)库提供的线程池和调度器来处理大量的并发操作,而不会阻塞主线程。

响应式反馈:在Spring WebFlux中,可以使用操作符和函数式编程的方式对数据流进行转换和处理。例如,可以使用map操作符对数据流中的元素进行转换,使用filter操作符对数据流进行过滤,以及使用flatMap操作符对多个数据流进行合并等。

实战应用

使用响应式编程的思想,我们可以通过构建一个基于数据流的实时推荐系统

基于Spring Boot和Spring WebFlux的实时推荐系统的核心部分:

  1. 创建实体类和存储库:
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;@Document(collection = "products")
public class Product {@Idprivate String id;private String name;private String description;// 省略构造函数、getter和setter方法
}import org.springframework.data.mongodb.repository.ReactiveMongoRepository;
import reactor.core.publisher.Flux;public interface ProductRepository extends ReactiveMongoRepository<Product, String> {Flux<Product> findByKeyword(String keyword);
}

 

创建服务类:

import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;@Service
public class ProductRecommendationService {private ProductRepository productRepository;public ProductRecommendationService(ProductRepository productRepository) {this.productRepository = productRepository;}public Flux<Product> getRecommendations(String keyword) {return productRepository.findByKeyword(keyword).flatMap(this::processRecommendation).take(5);}private Mono<Product> processRecommendation(Product product) {// 根据产品信息进行推荐处理逻辑// ...return Mono.just(product);}
}

控制器

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;@RestController
public class RecommendationController {private ProductRecommendationService recommendationService;public RecommendationController(ProductRecommendationService recommendationService) {this.recommendationService = recommendationService;}@GetMapping("/recommendations/{keyword}")public Flux<Product> getRecommendations(@PathVariable String keyword) {return recommendationService.getRecommendations(keyword);}
}

这里我们定义了一个Product实体类,它表示产品的基本信息。ProductRepository是一个响应式的存储库接口,用于对产品进行数据库操作。

ProductRecommendationService是一个服务类,它依赖于ProductRepository,用于处理实时推荐的业务逻辑。getRecommendations方法接收一个关键字作为参数,通过调用productRepository.findByKeyword(keyword)从数据库中查询匹配的产品数据流。然后,使用flatMap操作符对每个产品进行推荐处理,最后使用take(5)操作符限制只返回前5个推荐产品。

RecommendationController是一个控制器类,它依赖于ProductRecommendationService,用于处理HTTP请求并返回响应。在getRecommendations方法中,我们通过调用recommendationService.getRecommendations(keyword)来获取实时推荐的产品数据流。

好了这就是本期的全部 感谢观看 资源过段时会传哈 (要是有人要哈哈)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/2813421.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

安达发APS|多分厂多车间协同排产软件

多分厂多车间协同排产软件可以帮助各个分厂和车间之间实现信息的共享和协同工作&#xff0c;从而提高生产效率、降低成本、提高产品质量。那么&#xff0c;如何选择一款合适的多分厂多车间协同排产软件呢&#xff1f;本文将从以下几个方面进行详细介绍。 1. 功能需求 首先&…

Vue实现登录保存token并校验实现保存登录状态

文章目录 一、登录vue二、路由index 一、登录vue <script> import request from "/axios/baseURL"; import router from "/router";// 接口数据初始化 const FORM_DATA {userName: "",password: "", }; export default {data(…

opencv图像处理(3)

1.图像平滑 1.1图像噪声 由于图像采集、处理、传输等过程不可避免的会受到噪声的污染&#xff0c;妨碍人们对图像理解及分析处理。常见的图像噪声有高斯噪声、椒盐噪声等。 1.1.1椒盐噪声 椒盐噪声也称为脉冲噪声&#xff0c;是图像中经常见到的一种噪声&#xff0c;它是一…

CKA认证,开启您的云原生之旅!

在当今数字化时代&#xff0c;云计算已经成为企业和个人发展的关键技术。而获得CKA&#xff08;Certified Kubernetes Administrator&#xff09;认证&#xff0c;将是您在云原生领域迈出的重要一步。 CKA认证是由Kubernetes官方推出的权威认证&#xff0c;它旨在验证您在Kuber…

Java SpringBoot 创建项目工程输出 Hello World

Java SpringBoot 创建项目工程输出 Hello World 1、新建项目 2、创建 controller 3、编写 Hello World 代码 package com.zhong.demo01.controller;import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.Res…

音视频数字化(数字与模拟-电视)

上一篇文章【音视频数字化(数字与模拟-音频广播)】谈了音频的广播,这次我们聊电视系统,这是音频+视频的采集、传输、接收系统,相对比较复杂。 音频系统的广播是将声音转为电信号,再调制后发射出去,利用“共振”原理,收音机接收后解调,将音频信号还原再推动扬声器,我…

实战 vue3 使用百度编辑器ueditor

前言 在开发项目由于需求vue自带对编辑器不能满足使用&#xff0c;所以改为百度编辑器&#xff0c;但是在网上搜索发现都讲得非常乱&#xff0c;所以写一篇使用流程的文章 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、下载ueditor编辑器 一个“…

编译 Linux SDK源码包(基于迅为电子的RK3568开发板)

前言&#xff1a; 本文所使用的开发板是迅为电子的RK3568开发板&#xff0c;Linux源码包也是从的开发板自带资料中获取到的&#xff0c;有兴趣者可自行购买&#xff08;话说最近瑞芯微的芯片真的很火啊&#xff09; 目录 前言&#xff1a; SDK 包说明&#xff1a; SDK 包源…

如何使用Logstash搜集日志传输到es集群并使用kibana检测

引言&#xff1a;上一期我们进行了对Elasticsearch和kibana的部署&#xff0c;今天我们来解决如何使用Logstash搜集日志传输到es集群并使用kibana检测 目录 Logstash部署 1.安装配置Logstash &#xff08;1&#xff09;安装 &#xff08;2&#xff09;测试文件 &#xff…

Java+SpringBoot+Vue+MySQL:美食推荐系统的技术革新

✍✍计算机编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java实战 |…

2024-02-26(Spark,kafka)

1.Spark SQL是Spark的一个模块&#xff0c;用于处理海量结构化数据 限定&#xff1a;结构化数据处理 RDD的数据开发中&#xff0c;结构化&#xff0c;非结构化&#xff0c;半结构化数据都能处理。 2.为什么要学习SparkSQL SparkSQL是非常成熟的海量结构化数据处理框架。 学…

docker小知识:linux环境安装docker

安装必要软件包&#xff0c;执行如下命令 yum install -y yum-utils device-mapper-persistent-data lvm2目的是确保在安装 Docker 之前&#xff0c;系统已经安装了必要的软件包和服务&#xff0c;以支持 Docker 的正常运行。设置yum源&#xff0c;添加Docker官方的CentOS存储…

阿里云服务器2024年优惠价格表曝光,太可怕了!

2024阿里云服务器优惠活动政策整理&#xff0c;轻量2核2G3M服务器61元一年、2核4G4M带宽165元1年&#xff0c;云服务器4核16G10M带宽26元1个月、149元半年&#xff0c;阿里云ECS云服务器2核2G3M新老用户均可99元一年续费不涨价&#xff0c;企业用户2核4G5M带宽199元一年&#x…

微服务-微服务链路追踪组件Skywalking实战

自动化监控系统Prometheus&Grafana实战&#xff1a; 4 trem APM-性能监控项目班&#xff1a; https://vip.tulingxueyuan.cn/detail/p_602e574ae4b035d3cdb8f8fe/6 1. skywalking是什么 1.1 Skywalking主要功能特性 1.2 Skywalking整体架构 1.3 SkyWalking 环境搭建部…

2024热门UI设计工具推荐

最好的UI设计工具可以适应几乎每一个设计过程&#xff0c;并且有望满足您的创造性要求。但既然UI设计工具那么多&#xff0c;应该用什么工具呢&#xff1f; 在过去的几年里&#xff0c;Sketch和figma的结合一直是许多设计师的选择&#xff0c;但其他工具也提供了有竞争力的特点…

Redis 16种妙用

1、缓存 2、数据共享分布式 3、分布式锁 4、全局ID 5、计数器 6、限流 7、位统计 8、购物车 9、用户消息时间线timeline 10、消息队列 11、抽奖 12、点赞、签到、打卡 13、商品标签 14、商品筛选 15、用户关注、推荐模型 16、排行榜 1、缓存 String类型 例如&#xff1a;热点…

QT信号槽实现分析

1.宏定义 qt中引入了MOC来反射&#xff0c;编译阶段变成 MOC–>预处理–>编译–>汇编–>链接 1-1、Q_OBJECT 这个宏定义了一系列代码&#xff0c;包括元对象和处理的函数 #define Q_OBJECT \public: \QT_WARNING_PUSH \Q_OBJECT_NO_OVERRIDE_WARNING \static c…

【学海无涯】嵌入式工程师的100本专业书籍

001《大话数据结构》 002《鸟哥的 linux 私房菜》 003《疯狂 android 讲义》 004《第一行代码》 005《linux 内核设计与实现》 006《驱动设计开发》 007《linux 内核解密》 008《unix 环境高级编程》 009《linux 内核设计与实现》 010《essential C》 011《嵌入式 li…

CTFHub技能树web之XSS

在XSS系列的题目中&#xff0c;由于需要使用能够接受XSS数据的平台&#xff0c;并且由于使用的是CTFHub的模拟机器人点击我们的虚假URL&#xff0c;因此使用的XSS平台不能是自己本地搭建的&#xff0c;如果是本地的模拟点击的机器人将无法访问我们给的这个URL地址&#xff0c;也…

移动端学习:如何把exe转换成apk

exe转换成apk是怎么实现的呢?-电脑端-一门科技将exe文件转换成apk文件是一个比较常见的需求,尤其是对于一些开发者和用户来说。但是,这个过程并不是简单的复制和粘贴。在本文中,我们将介绍exe转换成apk的原理和详细介绍。首先,我们需要了解什么https://www.yimenapp.net/k…