Java工程師技術棧筆記

一、基礎

1. 修飾符

1.1 幾個修飾符

訪問修飾符

  1. default (即缺省,什麼也不寫): 在同一包內可見,不使用任何修飾符。使用對象:類、接口、變量、方法。
  2. private : 在同一類內可見。使用對象:變量、方法。 注意:不能修飾類(外部類)
  3. public : 對所有類可見。使用對象:類、接口、變量、方法
  4. protected : 對同一包內的類和所有子類可見。使用對象:變量、方法。 注意:不能修飾類(外部類)。
  5. 父類中聲明爲 public 的方法在子類中也必須爲 public。
  6. 父類中聲明爲 protected 的方法在子類中要麼聲明爲 protected,要麼聲明爲 public,不能聲明爲 private。
  7. 父類中聲明爲 private 的方法,不能夠被繼承。

非訪問修飾符

  1. static 修飾符,用來修飾類方法和類變量。
  2. final 修飾符,用來修飾類、方法和變量,final 修飾的類不能夠被繼承,修飾的方法不能被繼承類重新定義,修飾的變量爲常量,是不可修改的。
  3. abstract 修飾符,用來創建抽象類和抽象方法。
  4. synchronized 和 volatile 修飾符,主要用於線程的編程。

【eg】:
在Java中 ++i、i++並不是線程安全的,要想線程安全,就用使用volatile修飾符完善的AtomicInteger

1.2 Java類加載原理與順序

歸類總結爲:加載、鏈接、初始化
連接過程包括 驗證,準備、解析三個階段
【加載】:指的是把class字節碼文件從各個來源通過類加載器裝載入內存中。

【字節碼來源】:一般的加載來源包括從本地路徑下編譯生成的.class文件,從jar包中的.class文件,從遠程網絡,以及動態代理實時編譯
【類加載器】:一般包括啓動類加載器,擴展類加載器,應用類加載器,以及用戶的自定義類加載器。

【驗證】:保證加載進來的字節流符合虛擬機規範,不會造成安全錯誤
【準備】:主要是爲類變量(注意,不是實例變量)分配內存,並且賦予初值。
【解析】:將常量池內的符號引用替換爲直接引用的過程。

符號引用。即一個字符串,但是這個字符串給出了一些能夠唯一性識別一個方法,一個變量,一個類的相關信息,直接引用。可以理解爲一個內存地址,或者一個偏移量。比如類方法,類變量的直接引用是指向方法區的指針;
而實例方法,實例變量的直接引用則是從實例的頭指針開始算起到這個實例變量位置的偏移量

【初始化】:主要是對類變量初始化,是執行類構造器的過程,另說只對static修飾的變量或語句進行初始化
可以參考如下圖:Java類聲明週期簡單分析
當初始化完成後,就可以使用了,在使用完之後,會在方法區GC的過程中對其進行卸載。至此Java的的整合生命週期也完成。參考

2集合

關於Map的算法分析

2. web容器

2.1 tomcat

2.2 jetty

3. 多線程

多線程能滿足程序員編寫高效率的程序來達到充分利用 CPU 的目的。
一條線程指的是進程中一個單一順序的控制流,一個進程中可以併發多個線程,每條線程並行執行不同的任務。
多線程是多任務的一種特別的形式,但多線程使用了更小的資源開銷。

Java 三種創建線程的方法:
通過實現 Runnable 接口;
通過繼承 Thread 類本身;
通過 Callable 和 Future 創建線程。

4. JVM

4.1 JVM介紹

JVM是Java Virtual Machine的縮寫,JVM是一種用於計算設備的規範,它是一個虛構出來的計算機,是通過在實際的計算機上仿真模擬各種計算機功能來實現的。
Java語言的一個非常重要的特點就是與平臺的無關性。而使用JVM是實現這一特點的關鍵。
Java語言使用jvm屏蔽了與具體平臺相關的信息,使得Java語言編譯程序只需生成在jvm上運行的目標代碼(字節碼),就可以在多種平臺上不加修改地運行。Java虛擬機在執行字節碼時,把字節碼解釋成具體平臺上的機器指令執行。這就是Java的能夠“一次編譯,到處運行”的原因。
如圖在這裏插入圖片描述
JVM在它的生存週期中有一個明確的任務,那就是運行Java程序,因此當Java程序啓動的時候,就產生JVM的一個實例;當程序運行結束的時候,該實例也跟着消失了。下面我們從JVM的體系結構和它的運行過程這兩個方面來對它進行比較深入的研究。

4.2 JVM內存結構

JVM都包含:堆內存、棧內存、方法區、本地方法棧、指令計數器及其他隱含寄存器

【堆內存】:所有通過new創建的對象和數組的內存都在堆中分配,堆內存中的實體不再被應用時,JVM啓動垃圾回收機制,自動清除,是GC的主要區域,同樣是線程共享的內存區域。堆被所有線程共享,堆區中不存放基本類型和對象引用,只存放對象本身。

其大小可以通過-Xmx和-Xms來控制

【棧內存】:棧內存保存基本數據類型、局部變量,對象的引用變量都是在棧內存中的。棧內存中的數據,沒有默認初始化值,用完就消失。
【方法區】:保存方法代碼(編譯後的java代碼)和符號表;存放要加載的類信息、靜態變量、final類型的常量、屬性和方法信息。類信息是由類加載器從類文件中提取出來的。

JVM用持久代(Permanet Generation)來存放方法區,可通過-XX:PermSize和-XX:MaxPermSize來指定最小值和最大值。

【本地方法棧】:用於支持native方法的執行,存儲了每個native方法調用的狀態。

結構示意圖如下:

jvm結構示意圖

5.GC

5.1 GC介紹

GC是垃圾收集的意思,Java提供的GC功能可以自動監測對象是否超過作用域從而達到自動回收內存的目的,Java語言沒有提供釋放已分配內存的顯式操作方法。GC可以有效的防止內存泄露,提高可使用的內存的使用效率。
在HotSpot虛擬機中,主要有:
Minor GC:新生代GC,指發生在新生代的垃圾收集動作,所有的Minor GC都會觸發全世界的暫停(stop-the-world),停止應用程序的線程,不過這個過程非常短暫。
Major GC/Full GC:老年代GC,指發生在老年代的GC。

5.2 GC算法

Java堆是被所有線程共享的一塊內存區域,所有對象實例和數組都在堆上進行內存分配。爲了進行高效的垃圾回收,虛擬機把堆內存劃分成新生代(Young Generation)、老年代(Old Generation)和永久代(Permanent Generation)3個區域。
JVM針對新生代,主要採用複製算。針對老年代,通常採用標記-清除算法或者標記-整理算法來進行回收。

【複製算法】:新生代由 Eden 與 Survivor Space(S0,S1)構成,Survivor 倖存區是將內存分成大小相等的兩塊區域,每次使用其中的一塊。當這一塊的內存用完了,就將還存活的對象複製到另一塊區域上,然後對該塊進行內存回收。大小通過-Xmn參數指定,Eden 與 Survivor Space 的內存大小比例默認爲8:1,可以通過-XX:SurvivorRatio 參數指定,比如新生代爲10M 時,Eden分配8M,S0和S1各分配1M

【標記算法】:老年代對象存活的時間比較長、比較穩定,因此採用標記(Mark)算法來進行回收,所謂標記就是掃描出存活的對象,然後再進行回收未被標記的對象,回收後對用空出的空間要麼進行合併、要麼標記出來便於下次進行分配,目的就是要減少內存碎片帶來的效率損耗
老年代的空間大小即-Xmx 與-Xmn 兩個參數之差,用於存放經過幾次Minor GC之後依舊存活的對象。當老年代的空間不足時,會觸發Major GC/Full GC。

說明:事實證明,90%以上的新生代對象存活時間很短暫。使用複製算法實現簡單,運行效率高,壞處是每次只能使用一半內存,內存的利用率不高;
標記整理算法,涉及兩個過程,運行效率慢,且整理之後會產生不連續的內存空間

5.3 jvm調優

JVM參數調優

6. I/o

7. java8

7.1 Java8新特新

【Lambda 表達式】 − Lambda允許把函數作爲一個方法的參數(函數作爲參數傳遞進方法中。
【方法引用】 − 方法引用提供了非常有用的語法,可以直接引用已有Java類或對象(實例)的方法或構造器。與lambda聯合使用,方法引用可以使語言的構造更緊湊簡潔,減少冗餘代碼。
【默認方法】 − 默認方法就是一個在接口裏面有了一個實現的方法。
【Stream API】 −新添加的Stream API(java.util.stream) 把真正的函數式編程風格引入到Java中。
【Date Time API】 − 加強對日期與時間的處理。
【Optional 類】 − Optional 類已經成爲 Java 8 類庫的一部分,用來解決空指針異常。
【Base64編碼】內置了 Base64 編碼的編碼器和解碼器。
【Nashorn, JavaScript 引擎】 − Java 8提供了一個新的Nashorn javascript引擎,它允許我們在JVM上運行特定的javascript應用。
Java8新特新
Java9新特性

二、Spring

1. spring

1.1spring介紹

spring的核心是一個輕量級的容器(Container),它是實現IoC(Inversion of Control)容器和非侵入性(No intrusive)的框架,並提供AOP(Aspect-oriented Programming)的實現方式,提供對持久層(Persistence)、事務(Transcation)的支持;提供MVC Web框架的實現,並對一些常用的企業服務API提供了一致的模型封裝,是一個全方位的應用程序框架,除此之外,對現存的各種框架(Structs、JSF、hibernate、Ibatis、Webwork等),Spring也提供了與他們相整合的方案。

【細節列表】:
1、Spring的核心是一個輕量級(Lightweight)的容器(Container)。
2、Spring是實現IoC(Inversion of Control)容器和非入侵性(No intrusive)的框架。
3、Spring提供AOP(Aspect-oriented programming)的實現方式,把應用業務邏輯和系統服務分開。
4、Spring提供對持久層(Persistence)、事物(Transcation)的支持。
5、Spring供MVC Web框架的實現,並對一些常用的企業服務API(Application Interface)提供一致的模型封裝。
6、Spring提供了對現存的各種框架(Structs、JSF、Hibernate、Ibatis、Webwork等)相整合的方案。
總之,Spring是一個全方位的應用程序框架。

1.2 spring核心IOC和AOP

【控制反轉/IoC】:指的是程序中的一些對象或者變量的控制權,在傳統的程序中都是由應用程序自己控制對象創建或者變量賦值,這是一種主動式的控制,導致組件之間的完全耦合;現在將一些對象或者變量的創建控制權交給一個叫做Ioc容器的東西,由這個容器來控制應用程序中所需要的資源,這樣就變成了被動的控制,對組件之間的關係進行解耦,所以所謂的反轉就是將控制權由應用程序轉交到Ioc容器
【依賴注入/DI】:注入就是IoC容器嚮應用程序中進行注入應用程序所需要的資源,由應用程序主動裝配對象的依賴變應用程序被動接受依賴,所以IoC容器也叫DI容器
【AOP(面向切面編程)】:將具體的通用的應用從業務邏輯中分離出來,各自做各自專業的事情。

1.3 Srping加載bean的原理

(1)創建一個上下文context = createApplicationContext;
(2)context中都會有一個BeanFactory(默認是DefaultListableBeanFactory),在該類的子類類xmlBeanFactory中進行xml文件的解析;
(3)在類XmlBeanDefinitionParser 中用Dom解析xml文件(DefaultXmlBeanDefinitionParser),解析xml文件中所有bean,並將bean放到BeanDefinitionHolder中,封裝成BeanDefinition;
(4)再進行bean的註冊,具體在BeanDefinitionReaderUtils類調用DefaultListableBeanFactory類的registerBeanDefinition進行bean的註冊,在這裏用了一HashMap存放bean,其中用Beanname作爲鍵值,其封裝好的beanDefinition作爲值。還有用一個List存放所有的bean的名字

1.4 springBean的自動裝配模式

【no】: spring默認的設置,在該設置下自動裝配是關閉的,開發者需要在配置文件中用標籤明確依賴關係;
【byName】: 該選項可以根據bean名稱設置依賴關係。當向一個bean中自動裝配一個屬性時,容器將根據bean的名稱自動在在配置文件中查詢一個匹配的bean。如果找到的話,就裝配這個屬性,如果沒找到的話就報錯。
【byType】: 該選項可以根據bean類型設置依賴關係。當向一個bean中自動裝配一個屬性時,容器將根據bean的類型自動在在配置文件中查詢一個匹配的bean。如果找到的話,就裝配這個屬性,如果沒找到的話就報錯。
【constructor】: 構造器自動裝載,僅僅適用於與有構造器相同參數的bean,如果在容器中沒有找到與構造器參數類型一致的bean,那麼將會拋出異常。
【autodetect】: 該模式自動探測使用構造器自動裝配或者byType自動裝配。先嚐試找合適的帶參數的構造函數,若沒有則自動選擇byType的自動裝配模式。

基於註解的自動裝配,spring默認是關閉註解模式的,所以需要在配置文件中設置

1.5 spring的事件類型

  1. 上下文更新事件(ContextRefreshedEvent):該事件會在ApplicationContext被初始化或者更新時發佈,也可以在調用ConfigurableApplicationContext接口中的refresh()方法時被觸發。
  2. 上下文開始事件(ContextStartedEvent): 當容器調用ConfigurableApplicationContext的Start()方法開始/重新開始容器時被觸發。
  3. 上下文停止事件(ContextStoppedEvent): 當容器調用ConfigurableApplicationContext的Stop()方法停止容器時觸發該事件。
  4. 上下文關閉事件(ContextClosedEvent): 當ApplicationContext被關閉時觸發該事件。容器被關閉時,其管理的所有單例Bean都被銷燬。
  5. 請求處理事件(RequestHandledEvent): 在Web應用中,當一個http請求(request)結束觸發該事件。

1.6 Spring的七種事務傳播特性

propagation_requierd:如果當前沒有事務,就新建一個事務,如果已存在一個事務中,加入到這個事務中,這是最常見的選擇。
propagation_supports:支持當前事務,如果沒有當前事務,就以非事務方法執行。
propagation_mandatory:使用當前事務,如果沒有當前事務,就拋出異常。
propagation_required_new:新建事務,如果當前存在事務,把當前事務掛起。
propagation_not_supported:以非事務方式執行操作,如果當前存在事務,就把當前事務掛起。
propagation_never:以非事務方式執行操作,如果當前事務存在則拋出異常。
propagation_nested:如果當前存在事務,則在嵌套事務內執行。如果當前沒有事務,則執行與propagation_required類似的操作

1.7 Spring中設計模式

1.【工廠模式】在各種BeanFactory以及ApplicationContext創建中都用到了;
2.【模版模式】各種BeanFactory以及ApplicationContext實現中也都用到了;
3.【代理模式】在Aop實現中用到了JDK的動態代理;
4.【單例模式,這個比如在創建bean的時候。
5.【Tomcat中有很多場景都使用到了外觀模式,因爲Tomcat中有很多不同的組件,每個組件需要相互通信,但又不能將自己內部數據過多地暴露給其他組件。用外觀模式隔離數據是個很好的方法。
6.【策略模式】Comparator這個接口簡直就是爲策略模式而生的。Comparable和Comparator的區別一文中,詳細講了Comparator的使用。比方說Collections裏面有一個sort方法,因爲集合裏面的元素有可能是複合對象,複合對象並不像基本數據類型,可以根據大小排序,複合對象怎麼排序呢?基於這個問題考慮,Java要求如果定義的複合對象要有排序的功能,就自行實現Comparable接口或Comparator接口.
7.【原型模式】:使用原型模式創建對象比直接new一個對象在性能上好得多,因爲Object類的clone()方法是一個native方法,它直接操作內存中的二進制流,特別是複製大對象時,性能的差別非常明顯。
8.【迭代器模式】:Iterable接口和Iterator接口 這兩個都是迭代相關的接口,可以這麼認爲,實現了Iterable接口,則表示某個對象是可被迭代的;Iterator接口相當於是一個迭代器,實現了Iterator接口,等於具體定義了這個可被迭代的對象時如何進行迭代的
資料

2 springMvc

Spring MVC 提供了一種分離式的方法來開發 Web 應用。通過運用像 DispatcherServelet,MoudlAndView 和 ViewResolver 等一些簡單的概念,開發 Web 應用將會變的非常簡單。

3 Springboot

3.1 springboot的說明

Spring Boot 是 Spring 開源組織下的子項目,是 Spring 組件一站式解決方案,主要是簡化了使用 Spring 的難度,簡省了繁重的配置,提供了各種啓動器,開發者能快速上手。

3.2 springboot的優點

獨立運行、簡化配置、自動配置、無代碼生成和XML配置、應用監控、上手容易

3.3 springboot自動配置原理

註解 @EnableAutoConfiguration, @Configuration, @ConditionalOnClass 就是自動配置的核心,首先它得是一個配置文件,其次根據類路徑下是否有這個類去自動配置。

啓動類上面的註解是@SpringBootApplication,它有三部分組成:
@SpringBootConfiguration:組合了 @Configuration 註解,實現配置文件的功能。
@EnableAutoConfiguration:打開自動配置的功能,也可以關閉某個自動配置的選項,如關閉數據源自動配置功能: @SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })。
@ComponentScan:Spring組件掃描。

資料

4 mybaties

在這裏插入圖片描述
資料

三、中間件

1. MQ

2.RPC

3.JDBC/ODBC

四、數據庫

4.1 表設計原則

  1. 同一張表只能有一個主鍵,但能有多個唯一約束;
  2. 主鍵字段值不能爲NULL,唯一約束字段值可以爲NULL;
  3. 主鍵字段可以做爲其他表的外鍵,唯一約束字段不可以做爲其他表的外鍵;
  4. SQLServer默認爲主鍵字段創建聚集索引,爲唯一約束字段創建非聚集索引;

MySQL|Redis|MongoDB對比    資料二

1. mysql

2. oracle

3. redis

4. mongodb

5. sql的優化

5.1sql慢查詢

一般指超過指定查詢時間的查詢稱之爲慢查詢你,導致慢查詢的原因有一些幾點:

  1. SQL編寫問題
  2. 業務實例互相干擾對IO/CPU 資源爭用
  3. 服務器硬件限制
  4. DB本身的BUG(概率小)
mysql> show variables like "long%";
+-----------------+----------+
| Variable_name   | Value    |
+-----------------+----------+
| long_query_time | 0.000100 |
+-----------------+----------+

------設置慢查詢時間:
mysql> set long_query_time=0.0001;

開啓慢查詢記錄設置:
mysql> show variables like "slow%";
+---------------------+------------------------------------+
| Variable_name       | Value                              |
+---------------------+------------------------------------+
| slow_launch_time    | 2                                  |
| slow_query_log      | OFF                                |
| slow_query_log_file | /opt/mysql/data/localhost-slow.log |
+---------------------+------------------------------------+
---slow_query_log 全局變量設置爲“ON”狀態
mysql> set global slow_query_log=ON;

4.2 Sql的優化方案

sql的優化方向主要有兩方面:索引和操作
【索引相關規則】索引相關有如下使用的注意事項:

  1. 字段類型轉換導致不用索引,如字符串類型的不用引號,數字類型的用引號等,這有可能會用不到索引導致全表掃描;
  2. mysql 不支持函數轉換,所以字段前面不能加函數,否則這將用不到索引;
  3. 不要在字段前面加減運算;
  4. 字符串比較長的可以考慮索引一部份減少索引文件大小,提高寫入效率;
  5. like % 在前面用不到索引;
  6. 根據聯合索引的第二個及以後的字段單獨查詢用不到索引;
  7. 不要使用 select *;
  8. 排序請儘量使用升序 ;
  9. or 的查詢儘量用 union 代替 (Innodb);
  10. 複合索引高選擇性的字段排在前面;
  11. order by / group by 字段包括在索引當中減少排序,效率會更高。

【操作相關】:

  1. 儘量規避大事務的 SQL,大事務的 SQL 會影響數據庫的併發性能及主從同步;
  2. 分頁語句 limit 的問題;
  3. 刪除表所有記錄請用 truncate,不要用 delete;
  4. 不讓 mysql 幹多餘的事情,如計算;
  5. 輸寫 SQL 帶字段,以防止後面表變更帶來的問題,性能也是比較優的 ( 涉及到數據字典解析,請自行查詢資料);
  6. 在 Innodb上用 select count(*),因爲 Innodb 會存儲統計信息;
  7. 慎用 Oder by rand()。

4.3 數據庫縱向與橫向拆分

1、垂直(縱向)切分
垂直切分常見有垂直分庫和垂直分表兩種。
垂直分庫就是根據業務耦合性,將關聯度低的不同表存儲在不同的數據庫。做法與大系統拆分爲多個小系統類似,按業務分類進行獨立劃分。與"微服務治理"的做法相似,每個微服務使用單獨的一個數據庫
垂直分表是基於數據庫中的"列"進行,某個表字段較多,可以新建一張擴展表,將不經常用或字段長度較大的字段拆分出去到擴展表中。在字段很多的情況下(例如一個大表有100多個字段),通過"大表拆小表",更便於開發與維護,也能避免跨頁問題,MySQL底層是通過數據頁存儲的,一條記錄佔用空間過大會導致跨頁,造成額外的性能開銷。另外數據庫以行爲單位將數據加載到內存中,這樣表中字段長度較短且訪問頻率較高,內存能加載更多的數據,命中率更高,減少了磁盤IO,從而提升了數據庫性能。

2、水平(橫向)切分
當一個應用難以再細粒度的垂直切分,或切分後數據量行數巨大,存在單庫讀寫、存儲性能瓶頸,這時候就需要進行水平切分了。
水平切分分爲庫內分表和分庫分表,是根據表內數據內在的邏輯關係,將同一個表按不同的條件分散到多個數據庫或多個表中,每個表中只包含一部分數據,從而使得單個表的數據量變小,達到分佈式的效果
庫內分表只解決了單一表數據量過大的問題,但沒有將表分佈到不同機器的庫上,因此對於減輕MySQL數據庫的壓力來說,幫助不是很大,大家還是競爭同一個物理機的CPU、內存、網絡IO,最好通過分庫分表來解決。

五、網絡

1 、OSI參考模型

應用層、表示層、會話層、網絡層、傳輸層、數據鏈路層、物理層七大部分

2、 TCP/UDP

TCP提供IP環境下的數據可靠傳輸,它提供的服務包括數據流傳送、可靠性、有效流控、全雙工操作和多路複用。通過面向連接、端到端和可靠的數據包發送。通俗說,它是事先爲所發送的數據開闢出連接好的通道,然後再進行數據發送;
UDP則不爲IP提供可靠性、流控或差錯恢復功能。一般來說,TCP對應的是可靠性要求高的應用,而UDP對應的則是可靠性要求低、傳輸經濟的應用。

TCP支持的應用協議主要有:Telnet、FTP、SMTP等;
UDP支持的應用層協議主要有:NFS(網絡文件系統)、SNMP(簡單網絡管理協議)、DNS(主域名稱系統)、TFTP(通用文件傳輸協議)等。

3 、http/https

3.1 http

http是一個無狀態協議,既是對事務沒有狀態支持。對應的解決方式有cookie等技術

3.2 https

一、首先HTTP請求服務端生成證書,客戶端對證書的有效期、合法性、域名是否與請求的域名一致、證書的公鑰(RSA加密)等進行校驗;
二、客戶端如果校驗通過後,就根據證書的公鑰的有效, 生成隨機數,隨機數使用公鑰進行加密(RSA加密);
三、消息體產生的後,對它的摘要進行MD5(或者SHA1)算法加密,此時就得到了RSA簽名;
四、發送給服務端,此時只有服務端(RSA私鑰)能解密。
五、解密得到的隨機數,再用AES加密,作爲密鑰(此時的密鑰只有客戶端和服務端知道)。
https通信原理
HTTPS在HTTP的基礎上加入了SSL協議,SSL依靠證書來驗證服務器的身份,併爲瀏覽器和服務器之間的通信加密。
https比http更加適合用來傳遞比較敏感的信息,如證件信息,密碼等等。

六、操作系統

1. Linux

七、系統設計

1 面向對象設計原則

  1. 【開閉原則】(Open Close Principle):對擴展開放,對修改關閉。在程序需要進行拓展的時候,不能去修改原有的代碼,實現一個熱插拔的效果。簡言之,是爲了使程序的擴展性好,易於維護和升級。想要達到這樣的效果,我們需要使用接口和抽象類,後面的具體設計中我們會提到這點。
  2. 【里氏代換原則】(Liskov Substitution Principle):任何基類可以出現的地方,子類一定可以出現。LSP 是繼承複用的基石,只有當派生類可以替換掉基類,且軟件單位的功能不受到影響時,基類才能真正被複用,而派生類也能夠在基類的基礎上增加新的行爲。里氏代換原則是對開閉原則的補充。實現開閉原則的關鍵步驟就是抽象化,而基類與子類的繼承關係就是抽象化的具體實現,所以里氏代換原則是對實現抽象化的具體步驟的規範。
  3. 【依賴倒轉原則】(Dependence Inversion Principle):DIP是開閉原則的基礎,具體內容:針對接口編程,依賴於抽象而不依賴於具體
  4. 【接口隔離原則】(Interface Segregation Principle):ISP 使用多個隔離的接口,比使用單個接口要好。它還有另外一個意思是:降低類之間的耦合度。由此可見,其實設計模式就是從大型軟件架構出發、便於升級和維護的軟件設計思想,它強調降低依賴,降低耦合。總結:要爲各個類建立它們需要的專用接口,而不要試圖去建立一個很龐大的接口供所有依賴它的類去調用
  5. 【迪米特法則】(Demeter Principle):又稱最少知道原則。是指:一個實體應當儘量少地與其他實體之間發生相互作用,使得系統功能模塊相對獨立。
  6. 【合成複用原則】(Composite Reuse Principle):合成複用原則是指:儘量使用合成/聚合的方式,而不是使用繼承。通俗就是通過將已有的對象納入新對象中,作爲新對象的成員對象來實現的,新對象可以調用已有對象的功能,從而達到複用。
  7. 【單一職責】Single Responsibility Principle,SRP):單一職責原則規定一個類應該有且僅有一個引起它變化的原因,否則類應該被拆分
    面向對象設計

2. 設計模式

又稱設計模式,是一套被反覆使用、多數人知曉的、經過分類編目的、代碼設計經驗的總結。
應用設計模式的目的是爲了提高代碼的可重用性、代碼的可讀性和代碼的可靠性

1.1 設計模式的意義

1)可以提高程序員的思維能力、編程能力和設計能力。
2)使程序設計更加標準化、代碼編制更加工程化,使軟件開發效率大大提高,從而縮短軟件的開發週期。
3)使設計的代碼可重用性高、可讀性強、可靠性高、靈活性好、可維護性強。

1.2 GoF的設計模式

  1. 單例(Singleton)模式:某個類只能生成一個實例,該類提供了一個全局訪問點供外部獲取該實例,其拓展是有限多例模式。
    原型(Prototype)模式:將一個對象作爲原型,通過對其進行復制而克隆出多個和原型類似的新實例。
  2. 廠方法(Factory Method)模式:定義一個用於創建產品的接口,由子類決定生產什麼產品。
  3. 抽象工廠(AbstractFactory)模式:提供一個創建產品族的接口,其每個子類可以生產一系列相關的產品。
  4. 建造者(Builder)模式:將一個複雜對象分解成多個相對簡單的部分,然後根據不同需要分別創建它們,最後構建成該複雜對象。
  5. 代理(Proxy)模式:爲某對象提供一種代理以控制對該對象的訪問。即客戶端通過代理間接地訪問該對象,從而限制、增強或修改該對象的一些特性。
  6. 適配器(Adapter)模式:將一個類的接口轉換成客戶希望的另外一個接口,使得原本由於接口不兼容而不能一起工作的那些類能一起工作。
  7. 橋接(Bridge)模式:將抽象與實現分離,使它們可以獨立變化。它是用組合關係代替繼承關係來實現,從而降低了抽象和實現這兩個可變維度的耦合度。
  8. 裝飾(Decorator)模式:動態的給對象增加一些職責,即增加其額外的功能。
  9. 外觀(Facade)模式:爲多個複雜的子系統提供一個一致的接口,使這些子系統更加容易被訪問。
  10. 享元(Flyweight)模式:運用共享技術來有效地支持大量細粒度對象的複用。
  11. 組合(Composite)模式:將對象組合成樹狀層次結構,使用戶對單個對象和組合對象具有一致的訪問性。模板方法(TemplateMethod)模式:定義一個操作中的算法骨架,而將算法的一些步驟延遲到子類中,使得子類可以不改變該算法結構的情況下重定義該算法的某些特定步驟。
  12. 策略(Strategy)模式:定義了一系列算法,並將每個算法封裝起來,使它們可以相互替換,且算法的改變不會影響使用算法的客戶。
  13. 命令(Command)模式:將一個請求封裝爲一個對象,使發出請求的責任和執行請求的責任分割開。
  14. 職責鏈(Chain of Responsibility)模式:把請求從鏈中的一個對象傳到下一個對象,直到請求被響應爲止。通過這種方式去除對象之間的耦合。
  15. 狀態(State)模式:允許一個對象在其內部狀態發生改變時改變其行爲能力。
  16. 觀察者(Observer)模式:多個對象間存在一對多關係,當一個對象發生改變時,把這種改變通知給其他多個對象,從而影響其他對象的行爲。
  17. 中介者(Mediator)模式:定義一箇中介對象來簡化原有對象之間的交互關係,降低系統中對象間的耦合度,使原有對象之間不必相互瞭解。
  18. 迭代器(Iterator)模式:提供一種方法來順序訪問聚合對象中的一系列數據,而不暴露聚合對象的內部表示。
  19. 訪問者(Visitor)模式:在不改變集合元素的前提下,爲一個集合中的每個元素提供多種訪問方式,即每個元素有多個訪問者對象訪問。
  20. 備忘錄(Memento)模式:在不破壞封裝性的前提下,獲取並保存一個對象的內部狀態,以便以後恢復它。
  21. 解釋器(Interpreter)模式:提供如何定義語言的文法,以及對語言句子的解釋方法,即解釋器。
    設計模式資料
    資料二

八、容器

1 web容器

1.1 tomcat、

其他的web容器
Weblogic
JBOSS
Coldfusion
Websphere
GlassFish

1.2 jetty、

1.3 nginx

2 docker

九、算法

1. 排序算法

2. 遞歸算法

3.查找算法

4.BFS和DFS

  1. BFS:Breadth-First-Search,寬度優先搜索;

  2. DFS:Depth-first search,深度優先搜索。
    DFS和BFS主要是運用於對於圖和樹的搜索,但是絕大部分問題模型都是可以建模變成一個圖或者樹的,所以差不多不少問題都會涉及到這兩個。

    方式 實現方法 基本思想 解決問題 N規模
    DFS 棧、回溯法 一次訪問一條路,更接近人的思維方式 所有解問題,或連通性問題 不能太大,<=200
    BFS 隊列 分治限界法,一次訪問多條路,每一層需要存儲大量信息 最優解問題,如最短路徑 可以比較大,因爲可以用隊列解決, <=100

DFS主要的特性是深度優先,總是不停的往下找,走到沒路才罷休。
BFS則是從root開始擴展,每一層都是精密的搜索完整了才下一個。

十、數據結構

數據結構比較常見的有,散列(集合)、鏈表(單向鏈表、雙向鏈表、循環鏈表)、線性表(隊列,棧)、樹、圖。
三種數據結構的區別:

  1. 【線性表】:數據元素之間僅有線性關係,每個數據元素只有一個直接前驅和一個直接後繼
  2. 【樹形結構】:數據元素之間有明顯的層次關係,並且每一層上的數據元素可能和下一層中多個元素(即其孩子結點)相關,但只能和上一層中一個元素(即其雙親結點)相關。
  3. 【 圖形結構】:結點之間的關係可以是任意的,圖中任意兩個數據元素之間都可能相關

1.鏈表

2.數組

3.樹

有個經典的應用HashMap,HashMap的數據結構用到了數組、鏈表、紅黑樹
在這裏插入圖片描述
HashMap數據結構算法分析

4. 圖

存圖就是對於每個點u,記錄他能到的所有點就行
存儲一個圖的三種方法:

  1. 鄰接矩陣:直接開一個N×N的二維數組E,然後 E[i][j] 爲1的時候表示 i 和 j 之間有一條邊,0的時候就沒有。
    缺點:這樣很方便簡單,但是有幾個缺陷,首先是效率問題,超過1000個點一般不管是空間還是時間都不允許了。然後就是如果從 3 到 5 有兩條邊的話,就沒法表示了。
  2. 鄰接鏈表:使用鏈表的方式保存一個結點的所有邊,就是每個點都有一個鏈表。一般使用vector數組
  3. 前向星:他和鏈表幾乎沒什麼區別,就是每次添加新的邊的時候往開頭加,而不是往最後加

5. 常用的幾種數據結構

  1. 數組
    在程序設計中,爲了處理方便, 把具有相同類型的若干變量按有序的形式組織起來。這些按序排列的同類數據元素的集合稱爲數組。在C語言中, 數組屬於構造數據類型。一個數組可以分解爲多個數組元素,這些數組元素可以是基本數據類型或是構造類型。因此按數組元素的類型不同,數組又可分爲數值數組、字符數組、指針數組、結構數組等各種類別。

  2. 是只能在某一端插入和刪除的特殊線性表。它按照先進後出的原則存儲數據,先進入的數據被壓入棧底,最後的數據在棧頂,需要讀數據的時候從棧頂開始彈出數據(最後一個數據被第一個讀出來)。
  3. 隊列
    一種特殊的線性表,它只允許在表的前端(front)進行刪除操作,而在表的後端(rear)進行插入操作。進行插入操作的端稱爲隊尾,進行刪除操作的端稱爲隊頭。隊列是按照“先進先出”或“後進後出”的原則組織數據的。隊列中沒有元素時,稱爲空隊列。
  4. 鏈表
    是一種物理存儲單元上非連續、非順序的存儲結構,它既可以表示線性結構,也可以用於表示非線性結構,數據元素的邏輯順序是通過鏈表中的指針鏈接次序實現的。鏈表由一系列結點(鏈表中每一個元素稱爲結點)組成,結點可以在運行時動態生成。每個結點包括兩個部分:一個是存儲數據元素的數據域,另一個是存儲下一個結點地址的指針域。

  5. 是包含n(n>0)個結點的有窮集合K,且在K中定義了一個關係N,N滿足 以下條件:
    (1)有且僅有一個結點 K0,他對於關係N來說沒有前驅,稱K0爲樹的根結點。簡稱爲根(root)。  (2)除K0外,K中的每個結點,對於關係N來說有且僅有一個前驅。
    (3)K中各結點,對關係N來說可以有m個後繼(m>=0)。

  6. 圖是由結點的有窮集合V和邊的集合E組成。其中,爲了與樹形結構加以區別,在圖結構中常常將結點稱爲頂點,邊是頂點的有序偶對,若兩個頂點之間存在一條邊,就表示這兩個頂點具有相鄰關係。

  7. 在計算機科學中,堆是一種特殊的樹形數據結構,每個結點都有一個值。通常我們所說的堆的數據結構,是指二叉堆。堆的特點是根結點的值最小(或最大),且根結點的兩個子樹也是一個堆。
  8. 散列表
    若結構中存在關鍵字和K相等的記錄,則必定在f(K)的存儲位置上。由此,不需比較便可直接取得所查記錄。稱這個對應關係f爲散列函數(Hash function),按這個思想建立的表爲散列表。

數據結構

十一、容器

10.1 容器的感念

容器就是將軟件打包成標準化單元,以用於開發、交付和部署。
容器鏡像是輕量的、可執行的獨立軟件包 ,包含軟件運行所需的所有內容:代碼、運行時環境、系統工具、系統庫和設置。
容器化軟件適用於基於Linux和Windows的應用,在任何環境中都能夠始終如一地運行。
容器賦予了軟件獨立性,使其免受外在環境差異(例如,開發和預演環境的差異)的影響,從而有助於減少團隊間在相同基礎設施上運行不同軟件時的衝突。

10.1 Docker容器

Docker 是世界領先的軟件容器平臺。
Docker 使用 Google 公司推出的 Go 語言 進行開發實現,基於 Linux 內核 的cgroup,namespace,以及AUFS類的UnionFS等技術,對進程進行封裝隔離,屬於操作系統層面的虛擬化技術。 由於隔離的進程獨立於宿主和其它的隔離的進 程,因此也稱其爲容器。Docke最初實現是基於 LXC.
Docker 能夠自動執行重複性任務,例如搭建和配置開發環境,從而解放了開發人員以便他們專注在真正重要的事情上:構建傑出的軟件。
用戶可以方便地創建和使用容器,把自己的應用放入容器。容器還可以進行版本管理、複製、分享、修改,就像管理普通的代碼一樣。

爲什麼要用 Docker ?

Docker 的鏡像提供了除內核外完整的運行時環境,確保了應用運行環境一致性,從而不會再出現 “這段代碼在我機器上沒問題啊” 這類問題;——一致的運行環境
可以做到秒級、甚至毫秒級的啓動時間。大大的節約了開發、測試、部署的時間。——更快速的啓動時間
避免公用的服務器,資源會容易受到其他用戶的影響。——隔離性
善於處理集中爆發的服務器使用壓力;——彈性伸縮,快速擴展
可以很輕易的將在一個平臺上運行的應用,遷移到另一個平臺上,而不用擔心運行環境的變化導致應用無法正常運行的情況。——遷移方便
使用 Docker 可以通過定製應用鏡像來實現持續集成、持續交付、部署。——持續交付和部署
總結,docker提供了一致的運行環境、優良的隔離性、彈性部署、可持續交付與部屬
docker部署springboot工程

十二、分佈式事務

十三、冪等

1 概念 什麼是冪等

一個冪等操作的特點是其任意多次執行所產生的影響均與一次執行的影響相同。冪等函數,或冪等方法,是指可以使用相同參數重複執行,並能獲得相同結果的函數。這些函數不會影響系統狀態,也不用擔心重複執行會對系統造成改變。例如,“getUsername()和setTrue()”函數就是一個冪等函數.更復雜的操作冪等保證是利用唯一交易號(流水號)實現。

1 如何保證冪等

保證冪等性一般有三點:

  1. 對於每個請求必須有一個唯一的標識,比如:訂單支付請求,肯定得包含訂單id,一個訂單id最多支付一次。
  2. 每次處理完請求之後,必須有一個記錄標識這個請求處理過了,比如說常見的方案是在mysql中記錄個狀態啥的,比如支付之前記錄一條這個訂單的支付流水,而且支付流水採、
  3. 每次接收請求需要進行判斷之前是否處理過的邏輯處理,比如說,如果有一個訂單已經支付了,就已經有了一條支付流水,那麼如果重複發送這個請求,則此時先插入支付流水,orderId已經存在了,唯一鍵約束生效,報錯插入不進去的。然後你就不用再扣款了。
    還有一種方法,比如說redis用orderId作爲唯一鍵。只有成功插入這個支付流水,纔可以執行實際的支付扣款。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章