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

关于函数式接口和编程的解析和案例实战

文章目录

  • 匿名内部类
    • “匿名”在哪里
  • 函数式编程
    • lambda表达式的条件
    • Supplier
      • 使用示例
    • Consumer
      • accept
      • andThen
      • 使用场景
    • Functional
      • BiFunctional
      • TriFunctional

匿名内部类

匿名内部类的学习和使用是实现lambda表达式和函数式编程的基础。是想一下,我们在使用接口中的方法的时候,正常流程都是定义这个接口的实现类,然后使用实现类的对象调用接口中的方法。下面展示一个接口的方法使用的常规方法

public interface Test {void forTest();
}

如果想要使用这个接口,我们需要定义Test的实现类

// 定义一个学生类实现 Swim 游泳接口
public class TestImpl implements Test{// 实现方法@Overridepublic void test() {//for testSystem.out.println("测试test方法");}//测试public static void main(String[] args) {// 创建 Student 类的对象 s1TestImpl t = new TestImpl();//打印调用实现的方法t.test();}
}

“匿名”在哪里

1. 匿名了实现的接口所在的父类
java中可以根据传入的对象类型,区分这个对象的类信息,所以匿名的第一层就是省略了这个类,省去了 implements ClassName中的ClassName。之所以被称为 “匿名”,主要是因为它没有显式地定义类名,并且在创建对象的同时就直接实现了某个接口或者继承了某个类,以下是关于它为何可以实现匿名以及具体匿名了哪些信息的详细解释:

2. 匿名了外部独立的类定义结构
匿名内部类将类的定义和使用紧密结合在了一起,它直接嵌套在创建对象的代码语句中,没有像常规类那样在外部单独的代码块里呈现完整的类结构,比如类的修饰符(public、private 等)、类的继承关系(除了在匿名内部类中体现的继承自某个类或者实现某个接口)等这些在普通类定义中可能出现的结构信息都被隐去了,整个类的定义仿佛是 “匿名” 地融入到了使用它的那一处代码当中,使代码结构更加简洁,不过也相对牺牲了一些代码的清晰性和可维护性。换而言之,匿名内部类中我们的TestImpl也不再需要显示给出,这里我们以实现自定义比较器作为示例

List<Integer> nums = Arrays.asList(1,5,3,7,11,6,2);
nums.sort(new Comparator<Integer>(){@Overridepublic int compare(Integer i1, Integer i2){return i2- i1;}
});

3. 其他信息补充说明
对于内部的方法入参和重写的注解,是实现一个接口方法中必须的信息,有无返回值需要根据接口方法定义是void还是其他区分,以上就是匿名内部类的使用。在日常开发中,基于参数是一个接口方法返回值的这种写法较为常见,例如:Runnable或者Comarator等

函数式编程

当前java 8中提供了很多基于函数式的新特性。其中函数式接口有代表性的非 lambda表达式莫属。相较于匿名内部类,lambda表达式更加精简,仅保留传入的实参和返回值以及计算逻辑。上文中的自定义比较器在lambda表达式下可以优化为:“

List<Integer> nums = Arrays.asList(1,5,3,7,11,6,2);
nums.sort((i1, i2) -> i2- i1);

lambda表达式的条件

1. 必须实现的是函数式接口

	函数式接口是指只包含一个抽象方法的接口(除了从 Object 类继承的公共方法,如 equals、hashCode 等,这些不算额外的抽象方法)。这是最关键的前提条件,因为 Lambda 表达式本质上就是为了简洁地实现函数式接口而设计的语法糖。

代码示例:“下面的Runnable仅包含一个接口,因此可以改写为lambda表达式

new Runnable() {@Overridepublic void run() {System.out.println("执行任务");}
};

如果是含有多个抽象方法的接口,无法使用lambda表达式改写,因为编译器无法区分你需要覆盖的具体方法,所以下面的接口无法适配lambda表达式的改造

MyTestInterface myObj = new MyTestInterface() {@Overridepublic void method1() {// 具体实现逻辑}@Overridepublic int method2(int num) {return num * 2;}
};

2. 接口抽象方法的参数和返回值类型需明确可推断
虽然 Java 有类型推断机制,但在使用 Lambda 表达式改写匿名内部类时,接口抽象方法的参数类型和返回值类型要能够相对清晰地确定,以便编译器能正确解析 Lambda 表达式所代表的逻辑。例如比较器的重写,编译器可以根据传入的实参判断类型是String

interface StringJoinerFunction {String join(String s1, String s2);
}
public class StringJoinerExampleWithError {public static void main(String[] args) {StringJoinerFunction joiner = (s1, s2) -> {System.out.println(s1 + s2);return s1+s2; // 返回值类型与接口定义的String不符,无法正确改写};System.out.println(joiner.join("Hello", "World"));}
}

3. 实现逻辑相对简单,无复杂的语句块或逻辑分支
这个要求仅仅基于代码本身的可读写,例如一些if else逻辑也可以用于lamvbda表达式,但是却失去了代码简洁原本的意义。不如直接使用匿名内部类或者实现接口的形式完成抽象方法的调用。

Supplier

Supplier(供给者) Supplier是一个不接受任何输入参数但返回一个结果的操作。它主要用于生成数据或对象。Supplier接口定义了一个get方法,该方法不接受任何输入参数并返回一个结果。表示从函数式接口返回的对象中获取Supplier内的数据

 Supplier<String> supplier =  () -> {return "Hello World";};System.out.println(supplier.get());

Supplier在企业级开发中的应用场景大约有以下几个方面

使用示例

1. 动态加载配置
一些数据库配置信息和连接池的加载如果消耗较大的资源,并且希望使用时候动态加载的情况下,可以使用Supplier预先定义这个连接配置项。避免在应用启动阶段就占用大量内存和初始化时间。
例如,创建一个数据库连接池对象,代码示例如下:

    public static Supplier<DataSource> supplier = () -> {HikariDataSource dataSource = new HikariDataSource();dataSource.setJdbcUrl("xxxx:3306/pdb_19c");dataSource.setUsername("Hikari");dataSource.setPassword("123456");return dataSource;};public static DataSource getDataSource () {return (DataSource) Optional.ofNullable(supplier).get();}public static Connection getConnectionDyn() throws Exception {return getDataSource().getConnection();}

2. 生成默认数据

继续上面的思路,可以使用static final修饰默认值,使用Supplier处理指向默认值的配置,用作某属性为空的兜底配置

   private static final Supplier<Integer> portSupplier = () -> {Optional<Integer> configPort = readPortFromConfig();return configPort.orElse(DEFAULT_PORT);};private static Optional<Integer> readPortFromConfig() {// 模拟从配置文件读取端口号,这里假设返回Optional.empty()表示读取失败Integer i1 = null;return Optional.ofNullable(i1);}public static void main(String[] args) {System.out.println(portSupplier.get());}

3. 实现灵活的策略模式
策略模式在企业级开发中常用于根据不同情况选择不同的业务逻辑执行方式。Supplier 结合 Lambda 表达式可以让策略模式的实现更加简洁和灵活,下面是用Supplier实现的策略模式

    public static Supplier<BigDecimal> normalMemberDiscount = () -> {return BigDecimal.valueOf(0.9); // 9折};// 高级会员折扣策略public static Supplier<BigDecimal> premiumMemberDiscount = () -> {return BigDecimal.valueOf(0.8); // 8折};public static BigDecimal calculateDiscount(Order order, Supplier<BigDecimal> discountSupplier) {return order.getAmount().multiply(discountSupplier.get());}

4. 生成运行时的测试数据
Supplier 结合 Lambda 表达式可以方便地实现这一点,让测试数据的生成更加灵活和动态。
例如,在测试一个用户注册模块时,需要生成不同的用户信息作为测试数据

class UserTestDataGenerator {private static Supplier<String> usernameSupplier = () -> {Random random = new Random();return "user_" + random.nextInt(1000);};private static Supplier<String> passwordSupplier = () -> {Random random = new Random();return "pass_" + random.nextInt(1000);};private static Supplier<String> emailSupplier = () -> {Random random = new Random();return "user_" + random.nextInt(1000) + "@example.com";};public static Supplier<User> userSupplier = () -> new User(usernameSupplier.get(), passwordSupplier.get(), emailSupplier.get());
}

Consumer

序言:顾名思义,是消费者的意思。这个函数本身不接收返回值类型,一般实现打印、输出、入参的转换处理等操作
1. 代码示例
下面给出Consumer定义的示例,可以看到这个对象的定义类似于一个Comparator比较器,其作用是接收一个字符串,然后执行accept方法中对于字符串的操作。

 Consumer<String> con = new Consumer<String>() {@Overridepublic void accept(String string) {System.out.println("string values :" + string);}};con.accept("Hello World"); 

如果使用新版idea编译器的亲们,可以发现编译器提示这个方法的优化写法为使用lambda表达式的形式,即下面的格式:

  Consumer<String> con = string -> System.out.println("string values :" + string);con.accept("Hello World");

accept

accept在笔者看来可以视作一个开关,当主线程调用这个方法的时候,执行开关内部的逻辑。可以类比线程的submit方法,执行内部的代码块,:

 public static void main(String[] args) {// 定义一个Consumer<String>类型的变量,使用Lambda表达式实现其accept方法Consumer<String> stringConsumer = (str) -> System.out.println(str);// 调用accept方法,传入一个字符串参数stringConsumer.accept("Hello, World!");}
}

由上面的代码可以了解到,我们设置Consumer的定义,并且在想要让其执行的地方应用accept()触发Consumer的函数部分,输出了Hello World

andThen

如果一个操作之后还有其他操作,可以将其Consumer对象放到andThen的参数位置上,这个是因为andThen相当于执行accept的accept,从源码分析上可以得到这样的结论

default Consumer<T> andThen(Consumer<? super T> after) {Objects.requireNonNull(after);return (T t) -> { accept(t); after.accept(t); };}

consumer之间可以使用andThen进行串联式的编排,例如对姓名进行输出之后转换字符串为小写,通过consumer的定义和组装可以轻松实现。同时这两consumer对象也可以放在函数方法的形参位置作为回调方法使用

        List<String> arr = Arrays.asList("Wang", "Zi", "Meng");Consumer<String> con2 = out -> System.out.print("会员姓名:"+ out +";");Consumer<String> con3 = str2 -> System.out.println("小写版本为: " +str2.toLowerCase());con2.andThen(con3);arr.stream().forEach(con2.andThen(con3)::accept);

输出结果:
在这里插入图片描述

使用场景

使用函数式的consumer和普通的for循环有什么区别,将通过下面的示例进行展示

case 1 代码简洁性与可读性

如果在for循环中需要多重处理,并且这段代码整体写在循环体内容易造成多层嵌套或者本身具有一定程度的复用性,应该考虑将其抽象出来作为一个Consumer对象,例如循环处理某一个属性,需要将属性进行字符的转换或者精度的保留
  Consumer<String> con = string -> System.out.println(string.toUppercase());con.accept("Hello World");

2. 更好地支持函数式编程范式

Java 8 引入了函数式编程的一些特性,Consumer 作为函数式接口(只包含一个抽象方法 accept 的接口),符合函数式编程中对行为(操作)的抽象概念。它可以方便地与其他函数式接口(如 Predicate、Function 等)以及 Stream API 等配合使用,实现更高级、更灵活的编程模式,比如对集合进行过滤(使用 Predicate)后再对满足条件的元素进行消费(使用 Consumer)等操作,能够在代码中更好地体现数据的转换、处理流程,让代码更具逻辑性和条理性,同时也便于进行代码的单元测试等维护工作。

3. 增强代码的可复用性和灵活性

将操作抽象为 Consumer 接口,可以方便地在不同的地方复用这些操作逻辑。例如,前面提到的将字符串转换为大写的 Consumer 操作,可以在多个需要对字符串进行此处理的地方重复使用,只需要传递这个 Consumer 实例即可。而且通过将 Consumer 作为方法参数,能让方法的功能更加灵活多样,根据传入的不同 Consumer 实现不同的业务逻辑,提高了代码应对不同需求变化的能力,降低了代码的耦合度,使得整个代码库更加易于扩展和维护。虽然在很多情况下使用普通逻辑确实也能实现相同的功能,但 Consumer 函数式接口凭借其在代码简洁性、函数式编程支持以及复用性和灵活性等方面的优势,在 Java 编程中有着广泛且合适的应用场景,能够帮助开发人员更高效、优雅地编写代码,应对各种复杂的业务需求

Functional

通过lambda表达式可以看出匿名内部类的优化写法,func定义如下:

		Function<Integer,String> func = new Function<Integer, String>() {@Overridepublic String apply(Integer integer) {return String.valueOf(integer);}};list.stream().forEach(li -> {System.out.println(func.apply(li));});Function<Integer,String> funcLLambda = integer -> String.valueOf(integer);

BiFunctional

这个接口有四个类型参数,T、U、V 分别对应三个输入参数的类型,而 R 对应返回结果的类型,其唯一的抽象方法 apply 接受三个参数(分别为 T、U、V 类型),并返回一个 R 类型的结果,符合接受三个元素作为入参并返回结果的需求,并且由于标注了 @FunctionalInterface,可以很好地使用 Lambda 表达式来实现它。

代码示例

   private BiFunction<Double,Double,Double> biFunction = (Double a, Double b) -> Math.sqrt(a*a + b*b);

TriFunctional

这个接口有四个类型参数,T、U、V 分别对应三个输入参数的类型,而 R 对应返回结果的类型,其唯一的抽象方法 apply 接受三个参数(分别为 T、U、V 类型),并返回一个 R 类型的结果,符合接受三个元素作为入参并返回结果的需求,并且由于标注了 @FunctionalInterface,可以很好地使用 Lambda 表达式来实现它

代码示例

 public static void main(String[] args) {TriFunction<String, String, String, String> formatFunction = (str1, str2, str3) -> {return String.format("姓名: %s, 年龄: %s, 城市: %s", str1, str2, str3);};String result = formatFunction.apply("张三", "25", "北京");System.out.println(result);}

相关文章:

关于函数式接口和编程的解析和案例实战

文章目录 匿名内部类“匿名”在哪里 函数式编程lambda表达式的条件Supplier使用示例 ConsumeracceptandThen使用场景 FunctionalBiFunctionalTriFunctional 匿名内部类 匿名内部类的学习和使用是实现lambda表达式和函数式编程的基础。是想一下&#xff0c;我们在使用接口中的方…...

Linux 僵尸进程和孤儿进程, 进程优先级

僵尸进程 之间在进程状态中了解到了 "僵尸状态". 那么处于僵尸状态的进程就是僵尸进程. 僵尸状态是一种特殊的进程状态, 它表示一个进程已经完成执行, 但其父进程尚未回收其终止状态. "僵尸状态" 的本质就是死亡状态. 如何理解僵尸进程: 举个例子: 一个正…...

爬虫笔记24——纷玩岛自动抢票脚本笔记

纷玩岛自动抢票&#xff0c;协议抢票思路实现 一、获取Authorization凭证二、几个关键的参数三、几个关键的接口获取参数v&#xff0c;这个参数其实可以写死&#xff0c;可忽略通过价位获取演出的参数信息获取观演人信息&#xff0c;账号提前录入即可提交订单接口 先看实现图&a…...

《白帽子讲Web安全》15-16章

《白帽子讲Web安全》15-16章 《白帽子讲Web安全》15章15、Web Server配置安全15.1、Apache安全15.2、Nginx安全15.3、jBoss远程命令执行15.4、Tomcat远程命令执行15.5、HTTP Parameter Pollution15.6、小结 第四篇 互联网公司运营安全《白帽子讲Web安全》16章16、互联网业务安全…...

计算机毕业设计Python+LSTM天气预测系统 AI大模型问答 vue.js 可视化大屏 机器学习 深度学习 Hadoop Spark

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…...

大语言模型压缩技术;推理优化技术;SparseGPT算法;GPTQ算法

目录 大语言模型落地的成本、效率与效果 模型压缩技术 推理优化技术 SparseGPT算法 GPTQ算法 大语言模型落地的成本、效率与效果 模型压缩技术 模型压缩技术是大语言模型轻量化的关键。介绍了多种模型压缩方法,其中权重量化和模型稀疏化是两种主要的技术。 权重量化:权重…...

Facebook的开源项目解析:推动开发者社区的技术进步

Facebook&#xff0c;作为全球领先的社交平台之一&#xff0c;其在技术领域的创新不仅体现在产品功能的实现上&#xff0c;也积极推动开源社区的发展。开源项目已经成为Facebook技术战略的重要组成部分&#xff0c;通过开源&#xff0c;Facebook不仅加速了技术进步&#xff0c;…...

力扣--LCR 149.彩灯装饰记录I

题目 代码 /** Definition for a binary tree node. public class TreeNode { int val;TreeNode left;TreeNode right;TreeNode() {}TreeNode(int val) { this.val val; }TreeNode(int val, TreeNode left, TreeNode right) {this.val val;this.left left;this.right ri…...

Rust SQLx CLI 同步迁移数据库

上文我们介绍了SQLx及SQLite&#xff0c;并介绍了如何使用代码同步迁移数据库。本文介绍Sqlx cli 命令行工具&#xff0c;介绍如何安装、使用&#xff0c;利用其提供的命令实现数据表同步迁移。Java生态中有flyway, sqlx cli 功能类似&#xff0c;利用命令行工具可以和其他语言…...

批量生成不同用户的pdf 文件(html样式)

技术 selenium thymeleaf itextpdf chromedriver 使用thymeleaf 将动态数据替换 使用selenium chromedriver 进行js &#xff0c;css等逻辑运算后渲染视图 使用itextpdf 将html 转为pdf 文件 html模板 <!DOCTYPE html> <html xmlns:th"http://www.thymeleaf…...

混淆零碎知识点

minifyEnabled true //混淆开关 zipAlignEnabled true // Zipalign优化 shrinkResources true // 移除无用的resource文件 &#xff08;必须要混淆开了之后才才可以设置为true&#xff09; proguard-rules.pro 为混淆文件 //整个文件保留 不被混淆 -keep class com.cn…...

排序算法2

排序算法1-CSDN博客 排序算法1中提及的是较为基础(暴力实现&#xff0c;复杂度较高)的排序算法&#xff0c;不适合于数据量较大的场景&#xff0c;比如序列长度达到1e5 接下来以蓝桥另一道题目来理解其它的排序算法 蓝桥3226 蓝桥账户中心 样例 5 1 5 9 3 7 4、快速排序 快速排…...

【Web开发基础学习——corsheaders 应用的理解】

Web开发基础学习系列文章目录 第一章 基础知识学习之corsheaders 应用的理解 文章目录 Web开发基础学习系列文章目录前言一、使用1.1 安装1.2 配置 二、功能总结 前言 corsheaders 是一个 Django 第三方应用&#xff0c;用于处理跨域资源共享 (CORS)。CORS 是一种机制&#x…...

Redis和MySQL之间如何进行数据同步

原因 为什么要进行Redis和MySQL的数据同步&#xff1f; 性能优化&#xff1a;MySQL是关系型数据库&#xff0c;数据读取和存储相对复杂&#xff1b;Redis是内存数据库&#xff0c;读写速度极快&#xff0c;将热点数据存在Redis&#xff0c;可以大大提高系统的访问速度。 数据…...

css:转换

转换 移动 /* transform: translate(100px, 200px); */transform: translateX(100px);transform: translateY(100px); /*一个意思*/ 如果后面跟百分数的意思是移动盒子自身x/y方向长度的百分比&#xff0c;可以用作子绝父相控制盒子水平居中垂直居中 translate里的xy值是相对…...

状态管理与存储:Vuex 和 sessionStorage

1. sessionStorage 存储位置 sessionStorage 是浏览器提供的 Web Storage API 的一部分&#xff0c;用于在一个会话期间存储数据。数据保存在浏览器的 内存 中&#xff0c;而不是在硬盘上&#xff0c;且其生命周期仅限于当前浏览器标签页。数据在浏览器窗口或标签页关闭时会被…...

Redis和MySQL保持一致性的延迟双删(Delay Double Delete)策略

Redis和MySQL保持一致性的延迟双删&#xff08;Delay Double Delete&#xff09;策略&#xff0c;是一种在数据更新或删除时为了保证数据一致性而采取的方法。以下是延迟双删的过程和原理的详细解释&#xff1a; 一、过程 第一次删除缓存&#xff1a; 当需要更新数据库中的数据…...

快速理解微服务中Fegin的概念

一.由来 1.在传统的架构里面&#xff0c;我们是通过使用RestTemplate来访问其他的服务&#xff0c;但是这种方式就存在了一个很大的缺陷&#xff0c;也就是被调用方如果发生了服务的迁移(IP和端口发生了变化)&#xff0c;那么调用方也需要同步的在代码里面进行修改&#xff0c;…...

新增工作台模块,任务中心支持一键重跑,MeterSphere开源持续测试工具v3.5版本发布

2024年11月28日&#xff0c;MeterSphere开源持续测试工具正式发布v3.5版本。 在这一版本中&#xff0c;MeterSphere新增工作台模块&#xff0c;工作台可以统一汇总系统数据&#xff0c;提升测试数据的可视化程度并增强对数据的分析能力&#xff0c;为管理者提供测试工作的全局…...

快速搭建一个博客!!!“Halo框架深度优化:搭建你的个性化博客或网站”

目录 引言&#xff1a; 一. 首先服务器上去下载一个docker 1.可以参考官方地址&#xff1a; 2. 通过宝塔来一键安装&#xff01;&#xff01;&#xff01; 3.也可以自己下载&#xff01;&#xff01;&#xff01; 1.卸载旧版 2.配置Docker的yum库 3.安装Docker 4.启动和…...

009 STM32 HAL库介绍

STM32 HAL库&#xff08;Hardware Abstraction Layer&#xff09;是STMicroelectronics为STM32系列微控制器提供的一套硬件抽象层库&#xff0c;它旨在简化STM32的开发过程&#xff0c;提高代码的可移植性和可维护性。HAL库通过提供一组统一的API接口&#xff0c;使得开发者无需…...

【微服务】 Eureka和Ribbon

一、Eureka 服务调用出现的问题&#xff1a;在远程调用另一个服务时&#xff0c;我们采用的解决办法是发送一次http请求&#xff0c;每次环境的变更会产生新的地址&#xff0c;所以采用硬编码会出现很多麻烦&#xff0c;并且为了应对并发问题&#xff0c;采用分布式部署&#…...

6.算法移植第六篇 YOLOV5/rknn生成可执行文件部署在RK3568上

接上一篇文章best-sim.rknn模型生成好后&#xff0c;我们要将其转换成可执行文件运行在RK3568上&#xff0c;这一步需要在rknpu上进行&#xff0c;在强调一遍&#xff01;&#xff01;rknpu的作用是可以直接生成在开发板上运行的程序 退出上一步的docker环境 exit1.复制best-…...

element的el-table表格标题用css自定义是否必填,用添加伪类的方式标红色*

element的el-table表格标题用css自定义是否必填添加伪类红色 * 效果图如下&#x1f447; el-table组件的html部分 css部分 /deep/.el-table__header-wrapper{.el-table__header{.has-gutter tr .el-table__cell:nth-of-type(3) .cell:before{content: *;color:red}.has-gutte…...

数据仓库: 8- 数据仓库性能优化

CSDN 目录展示 目录 8- 数据仓库性能优化8.1 查询优化8.1.1 索引优化8.1.2 分区和分桶8.1.3 使用缓存8.1.4 查询简化与重写8.1.5 聚合优化8.1.6 并行化和分布式计算8.1.7 基于列存储的优化8.1.8 表的分区和数据清洗8.1.9 查询提示 (Hints)8.1.10 自动调优工具 8.2 索引设计8.2…...

可编程网络在分布式深度学习通信瓶颈控制中的应用与未来展望

目录 可编程网络在分布式深度学习通信瓶颈控制中的应用与未来展望 可编程网络在分布式深度学习通信瓶颈控制中的应用与未来展望 在分布式深度学习领域,随着模型规模的不断扩大,训练过程中的通信开销已成为制约性能提升的关键因素。传统的分布式训练方法面临高通信延迟和带宽…...

【论文笔记】Tool Learning with Foundation Models 论文笔记

Tool Learning with Foundation Models 论文笔记 文章目录 Tool Learning with Foundation Models 论文笔记摘要背景&#xff1a;工作&#xff1a; 引言工具学习的发展本文工作&#xff08;大纲&目录&#xff09; 背景2.1 工具使用的认知起源2.2 工具分类&#xff1a;用户界…...

Springfox迁移到 Springdoc OpenAPI 3

将项目从 Springfox 迁移到 Springdoc OpenAPI 3 时&#xff0c;主要的工作是将原先使用的 Springfox 注解替换为 Springdoc OpenAPI 3 中的对应注解。虽然 Springdoc OpenAPI 3 基于 OpenAPI 3 规范&#xff0c;并且有一些不同的命名方式和设计理念&#xff0c;但大部分注解的…...

DIY-Tomcat part 3 实现对动态资源的请求

实现ServletRequest package connector;import javax.servlet.RequestDispatcher; import javax.servlet.ServletInputStream; import javax.servlet.ServletRequest; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.i…...

3.10 内核 BUG_ON() at xfs_vm_writepage() -> page_buffers()

目录 前言 问题分析 page buffers创建 page buffers丢失 Write-Protect Dirty Page w/o Buffers 问题解决 前言 这个问题发生在3.10.0-514.el7上&#xff0c;并且在RHEL的知识库中快速找到了对应的案例以及解决方案&#xff0c;但是&#xff0c;理解问题如何发生和解决…...

海宁公司做网站/百度搜索网站排名

【一】 在新乐谱的第一小节开始添加一个全音符的中央C No.1 在New里新建一个插件 5/建中央C &#xff08;User copy&#xff09; No.2 双击打开 点run运行里输入代码 如图&#xff1a; No.3 点击ok 然后close关闭 No.4 点菜单栏的Plug-ins里 我新建的5插件 No.6 运行后就是这…...

河南网络洛阳网站建设河南网站建设/软文广告怎么写

在中国做企业&#xff0c;“人”永远都是绕不过去的一道坎&#xff0c;你不可能就事论事&#xff0c;也不可能把“事业”做的那么纯粹。中国企业最难逾越的不是企业本身&#xff0c;而是复杂的中国人性&#xff01;一个很古老的故事&#xff1a;从前有座山&#xff0c;山里有座…...

燕莎做网站/谷歌seo最好的公司

概述 basename 命令用于打印目录或者文件的基本名称。通常在 shell 脚本中用于获取文件名或目录名。 注&#xff1a;basename 命令不会关注路径是否真实有效&#xff0c;是给 basename 指定一个路径&#xff0c;basename 命令会删掉所有的前缀包括最后一个 ‘/’ 字符&#x…...

双语网站价格/安卓优化大师官方下载

转载 http://blog.csdn.net/lmj623565791/article/details/45059587&#xff1b; 本文出自:【张鸿洋的博客】 概述 RecyclerView出现已经有一段时间了&#xff0c;相信大家肯定不陌生了&#xff0c;大家可以通过导入support-v7对其进行使用。 据官方的介绍&#xff0c;该控件用…...

wordpress今日更新/广州网站外包

一下是我整理的asp.net的论坛列表&#xff1a; 1。 discuz --------http://nt.discuz.net 2. dvbbs------------http://bbs.dvbbs.net 3. dXbbs ----------http://www.dxbbs.net(它的源码要用Reflector反编译一下&#xff09;...

做网站一定要学java吗/网站推广计划书

为了方便读者朋友们自学桌面端编程&#xff0c;本文介绍了一些在线课程。桌面端编程方面的在线课程非常多&#xff0c;更新速度快&#xff0c;读者朋友们也可以在网上自行搜索&#xff0c;选择适合自己的在线课程进行学习。如需要打开课程的网站&#xff0c;请复制课程的网址到…...