自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

我們一起學(xué)習(xí) WebFlux 前置知識

開發(fā) 架構(gòu)
雖然 JDK8 發(fā)布距今已經(jīng)七八年了,但是相信還是有相當(dāng)多小伙伴用著 JDK8,寫著 JDK6 的代碼。所以我們有必要回顧一下 JDK8,也算是我們學(xué)習(xí) WebFlux 的一些前置知識。

 [[400435]]

最近太忙了,發(fā)文頻率有點不穩(wěn)定,理解萬歲。前面和大家說了要更 WebFlux,學(xué)習(xí) WebFlux 之前,我們先來學(xué)習(xí)一些前置知識。

Rome was not built in a day。

WebFlux 也不是一幫人拍腦門突然發(fā)明的,它是一個漫長的過程,WebFlux 本身在逐步完善,各種配套工具/理論也在逐步發(fā)展。

因此當(dāng)松哥想寫 WebFlux 的時候,發(fā)現(xiàn)沒法直接從 WebFlux 本身開始寫起,對于很多沒有接觸過函數(shù)式編程的人來說,上來就整 WebFlux 還是有一些挑戰(zhàn)的,想來想去,我覺得還是先來和大家捋一捋 JDK8 中的一些舊玩意。

雖然 JDK8 發(fā)布距今已經(jīng)七八年了,但是相信還是有相當(dāng)多小伙伴用著 JDK8,寫著 JDK6 的代碼。所以我們有必要回顧一下 JDK8,也算是我們學(xué)習(xí) WebFlux 的一些前置知識。

好啦,開整吧。

1.Lambda 表達(dá)式的四種寫法

JDK8 中引入了 Lambda,這個大家都知道,雖然現(xiàn)在 JDK 都出到 16 了,但是老實說,項目中的 Lambda 表達(dá)式似乎還是很少有人用。有的團(tuán)隊技術(shù)風(fēng)格激進(jìn),可能會見到很多 Lambda,但是大部分技術(shù)團(tuán)隊還是比較保守的。今天為了學(xué)習(xí) WebFlux,我們還是先來回顧一下 Lambda 表達(dá)式的幾種寫法。

先來說說,如果要用 Lambda,必須是只有一個需要強制實現(xiàn)方法的接口,我們可以使用 @FunctionalInterface 注解去標(biāo)記該接口:

  1. @FunctionalInterface 
  2. interface ICalculator{ 
  3.     int square(int i); 

此時如果該接口中有多個空方法,編譯期間就會報錯。

現(xiàn)在我們建議盡量將一個接口設(shè)計的小一些,這樣也滿足單一職責(zé)原則。

不過 JDK8 中引入了 default 方法,就是自帶默認(rèn)實現(xiàn)的那種,自帶默認(rèn)實現(xiàn)的方法可以有多個,這個并不影響 Lambda,并且 @FunctionalInterface 注解也不會去檢查默認(rèn)方法的數(shù)量。

1.1 單個參數(shù)的

如果只是一個參數(shù),那么直接寫參數(shù)即可,例如如下代碼:

  1. interface ICalculator{ 
  2.     int square(int i); 
  3. public class LambdaDemo01 { 
  4.     public static void main(String[] args) { 
  5.         ICalculator ic = i -> i * i; 
  6.         int square = ic.square(5); 
  7.         System.out.println("square = " + square); 
  8.     } 

當(dāng)函數(shù)只有一個參數(shù)的時候,直接寫即可,不需要添加 ()。

1.2 多個參數(shù)

多個參數(shù)的話,就需要寫上 () 了,以 Spring Security 中登錄成功的回調(diào)為例(不了解 Spring Security 的小伙伴可在公號后臺回復(fù) ss):

  1. .defaultLogoutSuccessHandlerFor((req,resp,auth)->{ 
  2.     resp.setContentType("application/json;charset=utf-8"); 
  3.     Map<String, Object> result = new HashMap<>(); 
  4.     result.put("status", 200); 
  5.     result.put("msg""使用 logout1 注銷成功!"); 
  6.     ObjectMapper om = new ObjectMapper(); 
  7.     String s = om.writeValueAsString(result); 
  8.     resp.getWriter().write(s); 
  9. },new AntPathRequestMatcher("/logout1","GET")) 
  10. .defaultLogoutSuccessHandlerFor((req,resp,auth)->{ 
  11.     resp.setContentType("application/json;charset=utf-8"); 
  12.     Map<String, Object> result = new HashMap<>(); 
  13.     result.put("status", 200); 
  14.     result.put("msg""使用 logout2 注銷成功!"); 
  15.     ObjectMapper om = new ObjectMapper(); 
  16.     String s = om.writeValueAsString(result); 
  17.     resp.getWriter().write(s); 
  18. },new AntPathRequestMatcher("/logout2","POST")) 
  19. .and() 
  20. .csrf().disable(); 

這種情況,方法有多個參數(shù),此時使用 Lambda 表達(dá)式就需要加上 ()。

1.3 要寫參數(shù)類型的

正常來說用 Lambda 時候不需要寫上參數(shù)類型,但是如果你需要寫,就要加上 (),還是上面那個例子,如下:

  1. interface ICalculator{ 
  2.     int square(int i); 
  3. public class LambdaDemo01 { 
  4.     public static void main(String[] args) { 
  5.         ICalculator ic = (int i) -> i * i; 
  6.         int square = ic.square(5); 
  7.         System.out.println("square = " + square); 
  8.     } 

1.4 方法體不止一行的

如果方法體不止一行,需要用上 {},如果方法體只有一行,則不需要 {},參考上面 2、3。

2.函數(shù)接口

JDK8 中自帶了函數(shù)式接口,使用起來也非常方便。

2.1基本應(yīng)用

我們先來看一個簡單的例子。

假設(shè)我有一個打招呼的接口 SayHello,SayHello 接口中只有一個 sayHello 方法,然后在 User 類中調(diào)用該接口對應(yīng)的方法,最終用法如下:

  1. @FunctionalInterface 
  2. interface SayHello { 
  3.     String sayHello(String name); 
  4.  
  5. class User { 
  6.     private String username; 
  7.  
  8.     public String getUsername() { 
  9.         return username; 
  10.     } 
  11.  
  12.     public void setUsername(String username) { 
  13.         this.username = username; 
  14.     } 
  15.  
  16.     public String say(SayHello sayHello) { 
  17.         return sayHello.sayHello(this.username); 
  18.     } 
  19.  
  20. public class LambdaDemo02 { 
  21.     public static void main(String[] args) { 
  22.         User user = new User(); 
  23.         user.setUsername("javaboy"); 
  24.         String say = user.say((username) -> "hello " + username); 
  25.         System.out.println("say = " + say); 
  26.     } 

分析 main 方法中的調(diào)用過程之后,我們發(fā)現(xiàn),在調(diào)用時最核心的是如下一行代碼:

  1. (username) -> "hello " + username 

在這段代碼中,我們只關(guān)心方法的輸入和輸出,其他的都不是我所考慮的,為了一個簡單的輸入輸出,我還要額外定義一個接口,這顯然不太劃算。

JDK8 中提供了函數(shù)接口,可以幫助我們簡化上面的接口定義。如下:

  1. class User2 { 
  2.     private String username; 
  3.  
  4.     public String getUsername() { 
  5.         return username; 
  6.     } 
  7.  
  8.     public void setUsername(String username) { 
  9.         this.username = username; 
  10.     } 
  11.  
  12.     public String say(Function<String,String> sayHello) { 
  13.         return sayHello.apply(this.username); 
  14.     } 
  15. public class LambdaDemo03 { 
  16.     public static void main(String[] args) { 
  17.         User2 user2 = new User2(); 
  18.         user2.setUsername("javaboy"); 
  19.         String say = user2.say((username) -> "hello " + username); 
  20.         System.out.println("say = " + say); 
  21.     } 

可以用 Function<String,String> 代替我們前面的接口定義,這里有兩個泛型,第一個泛型表示接口輸入的參數(shù)類型,第二個泛型表示接口輸出的參數(shù)類型,而且大家注意,我們最終 main 方法中的調(diào)用方式是不變的。有了 Function 函數(shù)之后,以后我們就不需要定義一些簡單的接口了。

而且 Function 函數(shù)還支持鏈?zhǔn)讲僮鳎缦拢?/p>

  1. public class LambdaDemo03 { 
  2.     public static void main(String[] args) { 
  3.         User2 user2 = new User2(); 
  4.         user2.setUsername("javaboy"); 
  5.         Function<String, String> func = (username) -> "hello " + username; 
  6.         String say = user2.say(func.andThen(s -> "你好 " + s)); 
  7.         System.out.println("say = " + say); 
  8.     } 

2.2 其他函數(shù)接口

  1. 接口  輸入?yún)?shù)    返回類型    說明 
  2. UnaryOperator   T   T   一元函數(shù),輸入輸出類型相同 
  3. Predicate   T   boolean 斷言 
  4. Consumer    T   /   消費一個數(shù)據(jù),只有輸入沒有輸出 
  5. Function<T,R>   T   R   輸入 T 返回 R,有輸入也有輸出 
  6. Supplier    /   T   提供一個數(shù)據(jù),沒有輸入只有輸出 
  7. BiFunction<T,U,R>   (T,U)   R   兩個輸入?yún)?shù) 
  8. BiPredicate<L, R>   (L,R)   boolean 兩個輸入?yún)?shù) 
  9. BiConsumer<T, U>    (T,U)   void    兩個輸入?yún)?shù) 
  10. BinaryOperator  (T,T)   T   二元函數(shù),輸入輸出類型相同 

接下來我們來看看這些函數(shù)接口。

2.2.1 UnaryOperator

當(dāng)輸入輸出類型相同時,可以使用 UnaryOperator 函數(shù)接口,例如我們上面的代碼,修改之后如下:

  1. class User2 { 
  2.     private String username; 
  3.  
  4.     public String getUsername() { 
  5.         return username; 
  6.     } 
  7.  
  8.     public void setUsername(String username) { 
  9.         this.username = username; 
  10.     } 
  11.  
  12.     public String say(UnaryOperator<String> sayHello) { 
  13.         return sayHello.apply(this.username); 
  14.     } 
  15. public class LambdaDemo03 { 
  16.     public static void main(String[] args) { 
  17.         User2 user2 = new User2(); 
  18.         user2.setUsername("javaboy"); 
  19.         UnaryOperator<String> func = (username) -> "helloo " + username; 
  20.         String say = user2.say(func); 
  21.         System.out.println("say = " + say); 
  22.     } 

2.2.2 Predicate

Predicate 輸入一個 T 類型的參數(shù),輸出一個 boolean 類型的值。

舉一個簡單的例子,例如如下代碼,我們定義一個 List 集合中存放著用戶姓名,現(xiàn)在要過濾出所有姓張的用戶,代碼如下:

  1. public class LambdaDemo04 { 
  2.     public static void main(String[] args) { 
  3.         List<String> names = Arrays.asList("張三""里斯""張五"); 
  4.         List<String> list = names.stream().filter(s -> s.startsWith("張")).collect(Collectors.toList()); 
  5.         for (String s : list) { 
  6.             System.out.println("s = " + s); 
  7.         } 
  8.     } 

filter 中傳入的就是一個 Predicate 函數(shù)接口,這個接口接收 String 類型的數(shù)據(jù),返回一個 boolean。

注意

一些常用類型的函數(shù)接口,JDK 中直接提供了相關(guān)的類供我們使用,例如 Predicate 可以用 IntPredicate 代替;Consumer 可以用 IntConsumer 代替。

2.2.3 Consumer

看名字就知道,這個是消費數(shù)據(jù),只有輸入沒有輸出。

例如集合的遍歷就可以使用 Consumer 函數(shù)接口。

  1. public class LambdaDemo04 { 
  2.     public static void main(String[] args) { 
  3.         List<String> names = Arrays.asList("張三""里斯""張五"); 
  4.         names.stream().forEach(s -> System.out.println(s)); 
  5.     } 

2.2.4 Supplier

Supplier 剛好和 Consumer 相反,它只有輸出沒有輸入。有的時候我們的工廠方法沒有輸入只有輸出,這個時候就可以考慮使用 Supplier(如果有輸入?yún)?shù),則可以考慮使用 Function 函數(shù)接口)。

  1. Supplier<Connection> supplier = ()->{ 
  2.     Connection con = null
  3.     try { 
  4.         con = DriverManager.getConnection(""""""); 
  5.     } catch (SQLException e) { 
  6.         e.printStackTrace(); 
  7.     } 
  8.     return con; 
  9. }; 
  10. Connection connection = supplier.get(); 

3.小結(jié)

其實 WebFlux 前置知識還是蠻多的,今天先聊這些吧,我們后面繼續(xù)。

本文轉(zhuǎn)載自微信公眾號「江南一點雨」,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請聯(lián)系江南一點雨公眾號。

 

責(zé)任編輯:武曉燕 來源: 江南一點雨
相關(guān)推薦

2021-06-01 10:41:11

WebFlux 數(shù)據(jù)Backpressur

2022-02-14 10:16:22

Axios接口HTTP

2021-11-26 09:44:42

鏈表節(jié)點定位

2022-12-01 09:59:57

內(nèi)核觀測性方法

2021-05-20 07:15:34

RSA-PSS算法簽名

2023-03-28 07:32:37

2023-03-26 12:45:52

Linux內(nèi)核頭文件

2023-11-13 18:36:04

知識抽取NER

2021-10-11 10:25:33

排列nums數(shù)組

2021-03-18 00:04:13

C# 類型數(shù)據(jù)

2023-08-04 08:20:56

DockerfileDocker工具

2021-01-12 05:08:49

DHCP協(xié)議模型

2021-08-27 07:06:09

DubboDocker技術(shù)

2022-03-31 18:59:43

數(shù)據(jù)庫InnoDBMySQL

2022-05-24 08:21:16

數(shù)據(jù)安全API

2023-08-10 08:28:46

網(wǎng)絡(luò)編程通信

2022-10-18 07:33:57

Maven構(gòu)建工具

2023-09-10 21:42:31

2023-06-30 08:18:51

敏捷開發(fā)模式

2021-08-27 07:06:10

IOJava抽象
點贊
收藏

51CTO技術(shù)棧公眾號