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

Spring中网络请求客户端WebClient的使用详解

Spring中网络请求客户端WebClient的使用详解_java_脚本之家

Spring5的WebClient使用详解-腾讯云开发者社区-腾讯云

在 Spring 5 之前,如果我们想要调用其他系统提供的 HTTP 服务,通常可以使用 Spring 提供的 RestTemplate 来访问,不过由于 RestTemplate 是 Spring 3 中引入的同步阻塞式 HTTP 客户端,因此存在一定性能瓶颈。根据 Spring 官方文档介绍,在将来的版本中它可能会被弃用。

​ 作为替代,Spring 官方已在 Spring 5 中引入了 WebClient 作为非阻塞式 Reactive HTTP 客户端。下面通过样例演示如何使用 WebClient。

一、基本介绍

1.什么是 WebClient

从 Spring 5 开始,Spring 中全面引入了 Reactive 响应式编程。而 WebClient 则是 Spring WebFlux 模块提供的一个非阻塞的基于响应式编程的进行 Http 请求的客户端工具。

由于 WebClient 的请求模式属于异步非阻塞,能够以少量固定的线程处理高并发的 HTTP 请求。因此,从 Spring 5 开始,HTTP 服务之间的通信我们就可以考虑使用 WebClient 来取代之前的 RestTemplate。

2.WebClient 的优势

(1)与 RestTemplate 相比,WebClient 有如下优势:

  • 非阻塞,Reactive 的,并支持更高的并发性和更少的硬件资源。
  • 提供利用 Java 8 lambdas 的函数 API。
  • 支持同步和异步方案。
  • 支持从服务器向上或向下流式传输。

(2)RestTemplate 不适合在非阻塞应用程序中使用,因此 Spring WebFlux 应用程序应始终使用 WebClient。在大多数高并发场景中,WebClient 也应该是 Spring MVC 中的首选,并且用于编写一系列远程,相互依赖的调用。

3.安装配置

编辑 pom.xml 文件,添加 Spring WebFlux 依赖,从而可以使用 WebClient。

1

2

3

4

<dependency>

    <groupId>org.springframework.boot</groupId>

    <artifactId>spring-boot-starter-webflux</artifactId>

</dependency>

二、创建 WebClient 实例

​ 从 WebClient 的源码中可以看出,WebClient 接口提供了三个不同的静态方法来创建 WebClient 实例:

1.利用 create() 创建

(1)下面利用 create() 方法创建一个 WebClient 对象,并利用该对象请求一个网络接口,最后将结果以字符串的形式打印出来。

注意:由于利用 create() 创建的 WebClient 对象没有设定 baseURL,所以这里的 uri() 方法相当于重写 baseURL。

1

2

3

4

5

6

7

8

9

WebClient webClient = WebClient.create();

  

Mono<String> mono = webClient

        .get() // GET 请求

        .uri("http://jsonplaceholder.typicode.com/posts/1")  // 请求路径

        .retrieve() // 获取响应体

        .bodyToMono(String.class); //响应数据类型转换

  

System.out.println(mono.block());

2.利用 create(String baseUrl) 创建

(1)下面利用 create(String baseUrl) 方法创建一个 WebClient 对象,并利用该对象请求一个网络接口,最后将结果以字符串的形式打印出来。

注意:由于利用 create(String baseUrl) 创建的 WebClient 对象时已经设定了 baseURL,所以 uri() 方法会将返回的结果和 baseUrl 进行拼接组成最终需要远程请求的资源 URL。

1

2

3

4

5

6

7

8

9

WebClient webClient = WebClient.create("http://jsonplaceholder.typicode.com");

  

Mono<String> mono = webClient

        .get() // GET 请求

        .uri("/posts/1"// 请求路径

        .retrieve() // 获取响应体

        .bodyToMono(String.class); //响应数据类型转换

  

System.out.println(mono.block());

3.利用 builder 创建(推荐)

(1)下面使用 builder() 返回一个 WebClient.Builder,然后再调用 build 就可以返回 WebClient 对象。并利用该对象请求一个网络接口,最后将结果以字符串的形式打印出来。

注意:由于返回的不是 WebClient 类型而是 WebClient.Builder,我们可以通过返回的 WebClient.Builder 设置一些配置参数(例如:baseUrl、header、cookie 等),然后再调用 build 就可以返回 WebClient 对象了

1

2

3

4

5

6

7

8

9

10

11

12

13

WebClient webClient = WebClient.builder()

        .baseUrl("http://jsonplaceholder.typicode.com")

        .defaultHeader(HttpHeaders.USER_AGENT,"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko)")

        .defaultCookie("ACCESS_TOKEN", "test_token")

        .build();

  

Mono<String> mono = webClient

        .get() // GET 请求

        .uri("/posts/1"// 请求路径

        .retrieve() // 获取响应体

        .bodyToMono(String.class); //响应数据类型转换

          

System.out.println(mono.block());

三、GET 请求

1.获取 String 结果数据

下面代码将响应结果映射为一个 String 字符串,并打印出来。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

@RestController

public class HelloController {

  

    // 创建 WebClient 对象

    private WebClient webClient = WebClient.builder()

            .baseUrl("http://jsonplaceholder.typicode.com")

            .build();

  

    @GetMapping("/test")

    public void test() {

        Mono<String> mono = webClient

                .get() // GET 请求

                .uri("/posts/1"// 请求路径

                .retrieve() // 获取响应体

                .bodyToMono(String.class); //响应数据类型转换

        System.out.println(mono.block());

        return;

    }

}

2.将结果转换为对象

(1)当响应的结果是 JSON 时,也可以直接指定为一个 Object,WebClient 将接收到响应后把 JSON 字符串转换为对应的对象。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

@RestController

public class HelloController {

  

    // 创建 WebClient 对象

    private WebClient webClient = WebClient.builder()

            .baseUrl("http://jsonplaceholder.typicode.com")

            .build();

  

    @GetMapping("/test")

    public void test() {

        Mono<PostBean> mono = webClient

                .get() // GET 请求

                .uri("/posts/1"// 请求路径

                .retrieve() // 获取响应体

                .bodyToMono(PostBean.class); //响应数据类型转换

        System.out.println(mono.block());

        return;

    }

}

(2)其中定义的实体 Bean 代码如下:

1

2

3

4

5

6

7

8

9

@Getter

@Setter

@ToString

public class PostBean {

    private int userId;

    private int id;

    private String title;

    private String body;

}

3.将结果转成集合

(1)假设接口返回的是一个 json 数组,内容如下:

(2)我们也可以将其转成对应的 Bean 集合:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

@RestController

public class HelloController {

  

    // 创建 WebClient 对象

    private WebClient webClient = WebClient.builder()

            .baseUrl("http://jsonplaceholder.typicode.com")

            .build();

  

    @GetMapping("/test")

    public void test() {

        Flux<PostBean> flux = webClient

                .get() // GET 请求

                .uri("/posts"// 请求路径

                .retrieve() // 获取响应体

                .bodyToFlux(PostBean.class); //响应数据类型转换

        List<PostBean> posts = flux.collectList().block();

        System.out.println("结果数:" + posts.size());

        return;

    }

}

4.参数传递的几种方式

下面 3 种方式的结果都是一样的。

(1)使用占位符的形式传递参数:

1

2

3

4

5

Mono<String> mono = webClient

        .get() // GET 请求

        .uri("/{1}/{2}", "posts", "1"// 请求路径

        .retrieve() // 获取响应体

        .bodyToMono(String.class); //响应数据类型转换

(2)另一种使用占位符的形式:

1

2

3

4

5

6

7

8

9

String type = "posts";

int id = 1;

  

Mono<String> mono = webClient

        .get() // GET 请求

        .uri("/{type}/{id}", type, id)  // 请求路径

        .retrieve() // 获取响应体

        .bodyToMono(String.class); //响应数据类型转换

        System.out.println(mono.block());

(3)我们也可以使用 map 装载参数:

1

2

3

4

5

6

7

8

9

Map<String,Object> map = new HashMap<>();

map.put("type", "posts");

map.put("id", 1);

  

Mono<String> mono = webClient

        .get() // GET 请求

        .uri("/{type}/{id}", map)  // 请求路径

        .retrieve() // 获取响应体

        .bodyToMono(String.class); //响应数据类型转换

5.subscribe 订阅(非阻塞式调用)

(1)前面的样例我们都是人为地使用 block 方法来阻塞当前程序。其实 WebClient 是异步的,也就是说等待响应的同时不会阻塞正在执行的线程。只有在响应结果准备就绪时,才会发起通知。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

@RestController

public class HelloController {

  

    // 创建 WebClient 对象

    private WebClient webClient = WebClient.builder()

            .baseUrl("http://jsonplaceholder.typicode.com")

            .build();

  

    @GetMapping("/test")

    public void test() {

        System.out.println("--- begin ---");

  

        Mono<String> mono = webClient

                .get() // GET 请求

                .uri("/posts/1"// 请求路径

                .retrieve() // 获取响应体

                .bodyToMono(String.class); //响应数据类型转换

  

        // 订阅(异步处理结果)

        mono.subscribe(result -> {

            System.out.println(result);

        });

  

        System.out.println("--- end ---");

        return;

    }

}

附:使用 exchange() 方法获取完整的响应内容

1.方法介绍

(1)前面我们都是使用 retrieve() 方法直接获取到了响应的内容,如果我们想获取到响应的头信息、Cookie 等,可以在通过 WebClient 请求时把调用 retrieve() 改为调用 exchange()。

(2)通过 exchange() 方法可以访问到代表响应结果的对象,通过该对象我们可以获取响应码、contentType、contentLength、响应消息体等。

2.使用样例

下面代码请求一个网络接口,并将响应体、响应头、响应码打印出来。其中响应体的类型设置为 String。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

@RestController

public class HelloController {

  

    // 创建 WebClient 对象

    private WebClient webClient = WebClient.builder()

            .baseUrl("http://jsonplaceholder.typicode.com")

            .build();

  

    @GetMapping("/test")

    public void test() {

        Mono<ClientResponse> mono = webClient

                .get() // GET 请求

                .uri("/posts/1"// 请求路径

                .exchange();

  

        // 获取完整的响应对象

        ClientResponse response = mono.block();

  

        HttpStatus statusCode = response.statusCode(); // 获取响应码

        int statusCodeValue = response.rawStatusCode(); // 获取响应码值

        Headers headers = response.headers(); // 获取响应头

  

        // 获取响应体

        Mono<String> resultMono = response.bodyToMono(String.class);

        String body = resultMono.block();

  

        // 输出结果

        System.out.println("statusCode:" + statusCode);

        System.out.println("statusCodeValue:" + statusCodeValue);

        System.out.println("headers:" + headers.asHttpHeaders());

        System.out.println("body:" + body);

        return;

    }

}

四、POST 请求

1.发送一个 JSON 格式数据(使用 json 字符串)

(1)下面代码使用 post 方式发送一个 json 格式的字符串,并将结果打印出来(以字符串的形式)。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

@RestController

public class HelloController {

  

    // 创建 WebClient 对象

    private WebClient webClient = WebClient.builder()

            .baseUrl("http://jsonplaceholder.typicode.com")

            .build();

  

    @GetMapping("/test")

    public void test() {

        // 需要提交的 json 字符串

        String jsonStr = "{\"userId\": 222,\"title\": \"abc\",\"body\": \"航歌\"}";

  

        // 发送请求

        Mono<String> mono = webClient

                .post() // POST 请求

                .uri("/posts"// 请求路径

                .contentType(MediaType.APPLICATION_JSON_UTF8)

                .body(BodyInserters.fromObject(jsonStr))

                .retrieve() // 获取响应体

                .bodyToMono(String.class); //响应数据类型转换

  

        // 输出结果

        System.out.println(mono.block());

        return;

    }

}

2.发送一个 JSON 格式数据(使用 Java Bean)

(1)下面代码使用 post 方式发送一个 Bean 对象,并将结果打印出来(以字符串的形式)。结果同上面是一样的:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

@RestController

public class HelloController {

  

    // 创建 WebClient 对象

    private WebClient webClient = WebClient.builder()

            .baseUrl("http://jsonplaceholder.typicode.com")

            .build();

  

    @GetMapping("/test")

    public void test() {

        // 要发送的数据对象

        PostBean postBean = new PostBean();

        postBean.setUserId(222);

        postBean.setTitle("abc");

        postBean.setBody("航歌");

  

        // 发送请求

        Mono<String> mono = webClient

                .post() // POST 请求

                .uri("/posts"// 请求路径

                .contentType(MediaType.APPLICATION_JSON_UTF8)

                .syncBody(postBean)

                .retrieve() // 获取响应体

                .bodyToMono(String.class); //响应数据类型转换

  

        // 输出结果

        System.out.println(mono.block());

        return;

    }

}

(2)上面发送的 Bean 对象实际上会转成如下格式的 JSON 数据提交:

3.使用 Form 表单的形式提交数据

(1)下面样例使用 POST 方式发送 multipart/form-data 格式的数据:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

@RestController

public class HelloController {

  

    // 创建 WebClient 对象

    private WebClient webClient = WebClient.builder()

            .baseUrl("http://jsonplaceholder.typicode.com")

            .build();

  

    @GetMapping("/test")

    public void test() {

        //提交参数设置

        MultiValueMap<String, String> map = new LinkedMultiValueMap<>();

        map.add("title", "abc");

        map.add("body", "航歌");

  

        // 发送请求

        Mono<String> mono = webClient

                .post() // POST 请求

                .uri("/posts"// 请求路径

                .contentType(MediaType.APPLICATION_FORM_URLENCODED)

                .body(BodyInserters.fromFormData(map))

                .retrieve() // 获取响应体

                .bodyToMono(String.class); //响应数据类型转换

  

        // 输出结果

        System.out.println(mono.block());

        return;

    }

}

(2)上面代码最终会通过如下这种 form 表单方式提交数据:

4.将结果转成自定义对象

​ 上面样例我们都是将响应结果以 String 形式接收,其实 WebClient 还可以自动将响应结果转成自定的对象或则数组。具体可以参考前面写的文章:

5.设置 url 参数

(1)如果 url 地址上面需要传递一些参数,可以使用占位符的方式:

1

2

String url = "http://jsonplaceholder.typicode.com/{1}/{2}";

String url = "http://jsonplaceholder.typicode.com/{type}/{id}";

(2)具体的用法可以参考前面写的文章:

6.subscribe 订阅(非阻塞式调用)

(1)前面的样例我们都是人为地使用 block 方法来阻塞当前程序。其实 WebClient 是异步的,也就是说等待响应的同时不会阻塞正在执行的线程。只有在响应结果准备就绪时,才会发起通知。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

@RestController

public class HelloController {

  

    // 创建 WebClient 对象

    private WebClient webClient = WebClient.builder()

            .baseUrl("http://jsonplaceholder.typicode.com")

            .build();

  

    @GetMapping("/test")

    public void test() {

        System.out.println("--- begin ---");

  

        // 需要提交的 json 字符串

        String jsonStr = "{\"userId\": 222,\"title\": \"abc\",\"body\": \"航歌\"}";

  

        Mono<String> mono = webClient

                .post() // POST 请求

                .uri("/posts"// 请求路径

                .contentType(MediaType.APPLICATION_JSON_UTF8)

                .body(BodyInserters.fromObject(jsonStr))

                .retrieve() // 获取响应体

                .bodyToMono(String.class); //响应数据类型转换

  

        // 订阅(异步处理结果)

        mono.subscribe(result -> {

            System.out.println(result);

        });

  

        System.out.println("--- end ---");

        return;

    }

}

相关文章:

Spring中网络请求客户端WebClient的使用详解

Spring中网络请求客户端WebClient的使用详解_java_脚本之家 Spring5的WebClient使用详解-腾讯云开发者社区-腾讯云 在 Spring 5 之前&#xff0c;如果我们想要调用其他系统提供的 HTTP 服务&#xff0c;通常可以使用 Spring 提供的 RestTemplate 来访问&#xff0c;不过由于 …...

那些年我为了考PMP踩过的坑.....

说到考PMP我尊嘟很难过且伤心&#xff0c;众所周知&#xff0c;报考PMP都是要报机构的而且还是PMI认证的机构&#xff0c;所以在报考PMP过程中选的机构我可以说踩过了很多坑了...... Q&#xff1a;包过吗&#xff1f; 大家千万不要信某某机构说的包过噱头&#xff0c;真的很坑…...

邦芒解析:新人入职后存在的三种职场心理误区

​​多数职场新人会认为自己工作不快乐&#xff0c;不能正确处理职场人际关系。尤其是新人入职后在处理人际关系方面更明显&#xff0c;下面简述新人入职后主要存在的三种职场心理误区。 误区一&#xff1a;面对对上司的恐惧 学会和上司沟通&#xff0c;新人要采用上司容易接受…...

MFC案例:利用SetTimer函数编写一个“计时器”程序

一、希望达成效果 利用基于对话框的MFC项目&#xff0c;做一个一方面能够显示当前时间&#xff1b;另一方面在点击开始按钮时进行读秒计时&#xff0c;计时结果动态显示&#xff0c;当点击结束时读秒结束并保持最后结果。 二、编程步骤及相关代码、注释 1、启动VS…...

2. 音视频H264

视频软件基本流程 1.什么是H264 H.264是由ITU-T视频编码专家组&#xff08;VCEG&#xff09;和ISO/IEC动态图像专家组&#xff08;MPEG&#xff09;联合组成的联合视频组&#xff08;JVT&#xff0c;Joint Video Team&#xff09;提出的高度压缩数字视频编解码器标准 H265又名高…...

烽宇团队回报社会,走进贵州山区公益行

贵州省——在一片美丽的黔山秀水间,烽宇团队成员用实际行动诠释了“取之于民,用之于民”的公益精神。作为在科技和商业领域取得显著成就的团队,烽宇团队不仅在商业上取得了辉煌的成绩,还积极投身于社会公益事业,回报社会。 取之于民,用之于民 近年来,烽宇团队在多位行业领袖的…...

硬盘格式化NTFS好还是exFAT好 U盘存储文件用哪个格式好? 硬盘用exfat还是ntfs mac不能读取移动硬盘怎么解决

在计算机世界中&#xff0c;文件系统是数据管理的基石&#xff0c;而NTFS和exFAT无疑是这块基石上的两大巨头。它们各自拥有独特的特点和优势&#xff0c;并在不同的使用场景中发挥着重要作用。 什么是文件系统 文件系统提供了组织驱动器的方法。它规定了如何在驱动器上存储数…...

Elasticsearch机器学习初探:智能数据洞察

在当今数据驱动的时代&#xff0c;企业越来越依赖于数据来做出明智的决策。然而&#xff0c;随着数据量的不断增长和复杂性的增加&#xff0c;传统的数据分析方法已经无法满足快速、准确洞察数据的需求。为了应对这一挑战&#xff0c;Elasticsearch引入了机器学习功能&#xff…...

贪心算法——赶作业(C++)

慢慢来&#xff0c;沉稳一点。 2024年6月18日 题目描述 A同学有n份作业要做&#xff0c;每份作业有一个最后期限&#xff0c;如果在最后期限后交作业就会扣分&#xff0c;现在假设完成每份作业都需要一天。A同学想安排作业顺序&#xff0c;把扣分降到最低&#xff0c;请帮他实…...

Python 数据可视化 多色散点图

Python 数据可视化 多色散点图 fig, ax plt.subplots() max_line max([max(merged_df[unif_ref_value]), max(merged_df[unif_rust_value])]) min_line min([max(merged_df[unif_ref_value]), max(merged_df[unif_rust_value])]) ax.plot([min_line, max_line], [min_line, …...

C语言入门系列:数据类型之浮点数

文章目录 一&#xff0c;什么是浮点数二&#xff0c;C语言中的浮点数1&#xff0c;float1.1 float的声明1.2 float的存储格式1.3 float的精度和范围 2&#xff0c;double2.1 double变量的声明2.2 double的存储格式1.3 double的精度和范围1.4 long double 3&#xff0c;0.2 0.1…...

思科配置路由器,四台主机互相ping通

一、如图配置 PC4和PC5用来配置路由器&#xff0c;各ip、接口如图所示。 二、配置各主机ip、子网掩码SNM、默认网关DGW (一)、PC0 (二)、PC1 (三)、PC2 (四)、PC3 三、 配置路由器Router0 (期间报错是打错了字母) Router>en Router#configure terminal Enter configurat…...

个人博客测试用例设计

个人博客测试用例设计 个人博客测试用例 分别从功能、性能、安全、兼容及界面分别展开 个人博客测试用例...

Java输入输出语句 和 保留字

目录 键盘输入语句 保留字 键盘输入语句 Input.java , 需要一个 扫描器(对象), 就是Scanner 步骤 &#xff1a; 导入该类的所在包, java.util.*创建该类对象&#xff08;声明变量&#xff09;调用里面的功能 案例要求&#xff1a;可以从控制台接收用户信息&#xff0c;【姓…...

生成对抗网络——GAN深度卷积实现(代码+理解)

本篇博客为 上篇博客的 另一个实现版本&#xff0c;训练流程相同&#xff0c;所以只实现代码&#xff0c;感兴趣可以跳转看一下。 生成对抗网络—GAN&#xff08;代码理解&#xff09; http://t.csdnimg.cn/HDfLOhttp://t.csdnimg.cn/HDfLO 目录 一、GAN深度卷积实现 1. 模型…...

gbase8s数据库阻塞检查点和非阻塞检查点的执行机制

1. 检查点的描述 为了便于数据库系统的复原和逻辑恢复&#xff0c;数据库服务器生成的一致性标志点&#xff0c;称为检查点&#xff0c;其是建立在数据库系统的已知和一致状态时日志中的某个时间点检查点的目的在于定期将逻辑日志中的重新启动点向前移动 如果存在检查点&#…...

ARM32开发--串口库封装(初级)

知不足而奋进望远山而前行 目录 文章目录 前言 目标 内容 开发流程 文件目录创建 分组创建 接口定义 完整代码 总结 前言 在嵌入式软件开发中&#xff0c;封装抽取流程和抽取封装策略是非常重要的技术&#xff0c;能够提高代码的复用性和可维护性。本文将介绍如何在文…...

统一管理:Vue公共组件/公共样式/全局自定义指令

main.js 引入存放公共文件的文件路径 import "./plugins";src/plugins文件夹下的index.js 在处理公共文件中分别引入 /* 公共引入,勿随意修改,修改时需经过确认 */ import Vue from "vue";import "/icons"; // 图标 import ByuiQueryForm fr…...

Linux之旅: 基础知识点的终极指南

文章目录 1、Linux的目录结构2、ls命令3、管理文件和目录4、linux命令使用细节和技巧5、权限管理基本命令6、搜索命令7、管道符与重定向8、压缩和解压命令9、用户及vim编辑器10、用户和用户组管理一、Linux系统用户账号的基本管理二、Linux系统用户组的管理 1、Linux的目录结构…...

C#部分方法有什么用处?和传统方法有什么区别?什么时候用合适?

在C#中&#xff0c;部分类&#xff08;partial class&#xff09;和部分方法&#xff08;partial method&#xff09;是两个不同的概念&#xff0c;但它们经常一起使用&#xff0c;特别是在代码生成和框架设计中。下面我将分别解释这两个概念&#xff0c;并讨论它们的用处、与传…...

19c补丁后oracle属主变化,导致不能识别磁盘组

补丁后服务器重启&#xff0c;数据库再次无法启动 ORA01017: invalid username/password; logon denied Oracle 19c 在打上 19.23 或以上补丁版本后&#xff0c;存在与用户组权限相关的问题。具体表现为&#xff0c;Oracle 实例的运行用户&#xff08;oracle&#xff09;和集…...

应用升级/灾备测试时使用guarantee 闪回点迅速回退

1.场景 应用要升级,当升级失败时,数据库回退到升级前. 要测试系统,测试完成后,数据库要回退到测试前。 相对于RMAN恢复需要很长时间&#xff0c; 数据库闪回只需要几分钟。 2.技术实现 数据库设置 2个db_recovery参数 创建guarantee闪回点&#xff0c;不需要开启数据库闪回。…...

Oracle查询表空间大小

1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...

蓝桥杯 2024 15届国赛 A组 儿童节快乐

P10576 [蓝桥杯 2024 国 A] 儿童节快乐 题目描述 五彩斑斓的气球在蓝天下悠然飘荡&#xff0c;轻快的音乐在耳边持续回荡&#xff0c;小朋友们手牵着手一同畅快欢笑。在这样一片安乐祥和的氛围下&#xff0c;六一来了。 今天是六一儿童节&#xff0c;小蓝老师为了让大家在节…...

论文浅尝 | 基于判别指令微调生成式大语言模型的知识图谱补全方法(ISWC2024)

笔记整理&#xff1a;刘治强&#xff0c;浙江大学硕士生&#xff0c;研究方向为知识图谱表示学习&#xff0c;大语言模型 论文链接&#xff1a;http://arxiv.org/abs/2407.16127 发表会议&#xff1a;ISWC 2024 1. 动机 传统的知识图谱补全&#xff08;KGC&#xff09;模型通过…...

css的定位(position)详解:相对定位 绝对定位 固定定位

在 CSS 中&#xff0c;元素的定位通过 position 属性控制&#xff0c;共有 5 种定位模式&#xff1a;static&#xff08;静态定位&#xff09;、relative&#xff08;相对定位&#xff09;、absolute&#xff08;绝对定位&#xff09;、fixed&#xff08;固定定位&#xff09;和…...

Matlab | matlab常用命令总结

常用命令 一、 基础操作与环境二、 矩阵与数组操作(核心)三、 绘图与可视化四、 编程与控制流五、 符号计算 (Symbolic Math Toolbox)六、 文件与数据 I/O七、 常用函数类别重要提示这是一份 MATLAB 常用命令和功能的总结,涵盖了基础操作、矩阵运算、绘图、编程和文件处理等…...

c#开发AI模型对话

AI模型 前面已经介绍了一般AI模型本地部署&#xff0c;直接调用现成的模型数据。这里主要讲述讲接口集成到我们自己的程序中使用方式。 微软提供了ML.NET来开发和使用AI模型&#xff0c;但是目前国内可能使用不多&#xff0c;至少实践例子很少看见。开发训练模型就不介绍了&am…...

佰力博科技与您探讨热释电测量的几种方法

热释电的测量主要涉及热释电系数的测定&#xff0c;这是表征热释电材料性能的重要参数。热释电系数的测量方法主要包括静态法、动态法和积分电荷法。其中&#xff0c;积分电荷法最为常用&#xff0c;其原理是通过测量在电容器上积累的热释电电荷&#xff0c;从而确定热释电系数…...

【无标题】路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论

路径问题的革命性重构&#xff1a;基于二维拓扑收缩色动力学模型的零点隧穿理论 一、传统路径模型的根本缺陷 在经典正方形路径问题中&#xff08;图1&#xff09;&#xff1a; mermaid graph LR A((A)) --- B((B)) B --- C((C)) C --- D((D)) D --- A A -.- C[无直接路径] B -…...