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

news2024/11/20 14:37:05

 🎉🎉欢迎光临🎉🎉

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

🌟特别推荐给大家我的最新专栏《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), // 将每个值乘以2
        filter(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 {
    @Override
    public 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> {
    @Override
    public 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 {
    @Id
    private 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://www.coloradmin.cn/o/1475340.html

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

相关文章

Bicycles(变形dijkstra,动态规划思想)

Codeforces Round 918 (Div. 4) G. Bicycles G. Bicycles 题意&#xff1a; 斯拉夫的所有朋友都打算骑自行车从他们住的地方去参加一个聚会。除了斯拉维奇&#xff0c;他们都有一辆自行车。他们可以经过 n n n 个城市。他们都住在城市 1 1 1 &#xff0c;想去参加位于城市…

c++实现栈和队列类

c实现栈和队列类 栈(Stack)Stack示意图Stack.cpp 队列(queue)queue 示意图queue.cpp 栈(Stack) Stack示意图 Stack.cpp #pragma once #include "ListStu.cpp"template<typename T> class Stack { public: /* * void push(T& tDate)* 参数一 &#xff1a;…

Android和Linux的开发差异

最近开始投入Android的怀抱。说来惭愧&#xff0c;08年就听说这东西&#xff0c;当时也有同事投入去看&#xff0c;因为恶心Java&#xff0c;始终对这玩意无感&#xff0c;没想到现在不会这个嵌入式都快要没法搞了。为了不中年失业&#xff0c;所以只能回过头又来学。 首先还是…

硬盘销毁:如何彻底销毁硬盘 文件销毁 数据销毁 物料销

大家对于办公这个词并不陌生&#xff0c;大多数人都知道办公就是对公事的处理&#xff0c;不是私人的事情处理。办公中会出现很多文件&#xff0c;很多的资料&#xff0c;那么办公室的文件销毁是如何处理的呢&#xff1f; 办公文件对于办公的人来说都是非常重视的&#xff0c;…

AI学习(5):PyTorch-核心模块(Autograd):自动求导

1.介绍 在深度学习中&#xff0c;自动求导是一项核心技术&#xff0c;它使得我们能够方便地计算梯度并优化模型参数。PyTorch 提供了一个强大的自动求导模块(Autograd)&#xff0c;它可以自动计算张量的导数得出梯度信息&#xff0c;同时也支持高阶导数计算。 1.1 概念词 在学…

微服务-商城订单服务项目

文章目录 一、需求二、分析三、设计四、编码4.1 商品服务4.2 订单服务4.3 分布式事务4.4 订单超时 商品、购物车 商品服务&#xff1a; 1.全品类购物平台 SPU:Standard Product Unit 标准化产品单元。是商品信息聚合的最小单位。是一组可复用、易检索的标准化信息的集合&#x…

EMR StarRocks实战——Mysql数据实时同步到SR

文章摘抄阿里云EMR上的StarRocks实践&#xff1a;《基于实时计算Flink使用CTAS&CDAS功能同步MySQL数据至StarRocks》 前言 CTAS可以实现单表的结构和数据同步&#xff0c;CDAS可以实现整库同步或者同一库中的多表结构和数据同步。下文主要介绍如何使用Flink平台和E-MapRed…

【程序员英语】【美语从头学】初级篇(入门)(笔记)Lesson 16 At the Shoe Store 在鞋店

《美语从头学初级入门篇》 注意&#xff1a;被 删除线 划掉的不一定不正确&#xff0c;只是不是标准答案。 文章目录 Lesson 16 At the Shoe Store 在鞋店对话A对话B笔记会话A会话B替换 Lesson 16 At the Shoe Store 在鞋店 对话A A: Do you have these shoes in size 8? B:…

如何运行github上的项目

为了讲明白这个过程&#xff0c;特意做了一个相当来说比较好读懂的原理图&#xff0c;希望和我一样初学的小伙伴也能很快上手哈&#x1f60a; 在Github中找到想要部署的项目&#xff0c;这里以BartoszJarocki/CV&#xff08;线上简历&#x1f4c4;&#xff09;项目为例 先从头…

经典Go知识点总结

开篇推荐 来来来,老铁们,男人女人都需要的技术活 拿去不谢:远程调试,发布网站到公网演示,远程访问内网服务,游戏联机 推荐链接 1.无论sync.Mutex还是其衍生品都会提示不能复制,但是能够编译运行 加锁后复制变量&#xff0c;会将锁的状态也复制&#xff0c;所以 mu1 其实是已…

4核8G服务器并发数多少?性能如何?

腾讯云4核8G服务器支持多少人在线访问&#xff1f;支持25人同时访问。实际上程序效率不同支持人数在线人数不同&#xff0c;公网带宽也是影响4核8G服务器并发数的一大因素&#xff0c;假设公网带宽太小&#xff0c;流量直接卡在入口&#xff0c;4核8G配置的CPU内存也会造成计算…

React Switch用法及手写Switch实现

问&#xff1a;如果注册的路由特别多&#xff0c;找到一个匹配项以后还会一直往下找&#xff0c;我们想让react找到一个匹配项以后不再继续了&#xff0c;怎么处理&#xff1f;答&#xff1a;<Switch>独特之处在于它只绘制子元素中第一个匹配的路由元素。 如果没有<Sw…

[极客大挑战 2019]LoveSQL1 题目分析与详解

一、题目简介&#xff1a; 二、通关思路&#xff1a; 1、首先查看页面源代码&#xff1a; 我们发现可以使用工具sqlmap来拿到flag&#xff0c;我们先尝试手动注入。 2、 打开靶机&#xff0c;映入眼帘的是登录界面&#xff0c;首先尝试万能密码能否破解。 username: 1 or 11…

IDEA如何开启Dashboard

普通的面板 Run Dashboard面板 修改配置文件 找到项目的.idea文件夹 点击编辑workspace.xml文件 添加下方代码 <component name"RunDashboard"><option name"ruleStates"><list><RuleState><option name"name" valu…

雾锁王国服务器配置怎么选择?阿里云和腾讯云

雾锁王国/Enshrouded服务器CPU内存配置如何选择&#xff1f;阿里云服务器网aliyunfuwuqi.com建议选择8核32G配置&#xff0c;支持4人玩家畅玩&#xff0c;自带10M公网带宽&#xff0c;1个月90元&#xff0c;3个月271元&#xff0c;幻兽帕鲁服务器申请页面 https://t.aliyun.com…

通过QScrollArea寻找最后一个弹簧并且设置弹簧大小

项目原因&#xff0c;最近需要通过QScrollArea寻找其中最后一个弹簧并且设置大小和策略&#xff0c;因为无法直接调用UI指针&#xff0c;所以只能用代码寻找。 直接上代码&#xff1a; if (m_scrollArea){int iScrollWidth m_labelSelectedTitle->width();m_scrollArea-&g…

数据结构与算法(数组,栈,队列,链表,哈希表,搜索算法,排序算法,查找算法,策略算法,递归算法,二叉搜索树BST,动态规划算法)

文章目录 1 课程介绍1.1 前置知识1.2 为什么要学习算法1.3 大厂面试常见数据结构题目(基础)1.4 数据结构和算法的关系 2 数据结构2.1 数据结构概述2.1.1 数据结构是什么2.1.2 数据结构分类2.1.2.1 线性结构2.1.2.2 非线性结构2.1.2.3 小总结 2.1.3 数据结构范围 2.2 数组Array2…

前端基础面试题(二)

摘要&#xff1a;最近&#xff0c;看了下慕课2周刷完n道面试题&#xff0c;记录下... 1. offsetHeight scrollHeight clientHeight 区别 计算规则&#xff1a; offsetHeight offsetWidth : border padding content clientHeight clientWidth: padding content scrollHeight…

unity学习(42)——创建(create)角色脚本(panel)——UserHandler(收)+CreateClick(发)——服务器收包2

1.解决上一次留下的问题&#xff1a; log和reg的时候也有session&#xff0c;输出看一下这两个session是同一个不&#xff1a; 实测结果reg log accOnline中的session都是同一个对象&#xff0c;但是getAccid时候的session就是另一个了。 测试结果&#xff0c;说明在LogicHan…

lv21 QT对话框3

1 内置对话框 标准对话框样式 内置对话框基类 QColorDialog, QErrorMessage QFileDialog QFontDialog QInputDialog QMessageBox QProgressDialogQDialog Class帮助文档 示例&#xff1a;各按钮激发对话框实现基类提供的各效果 第一步&#xff1a;实现组件布局&…