spring ioc和aop原理
Spring核心容器的主要組件是Bean工廠(BeanFactory),Bean工廠使用控制反轉(IoC)模式來降低程序代碼之間的耦合度,並提供了面向切面編程(AOP)的實現。
IOC不通過程序代碼直接控制。控制從應用程序代碼傳輸到外部控制器,控制轉移稱爲反向。
AOP稱爲面向方面編程,它使用一種稱爲“橫切”的技術,並將影響多個類的公共行爲包裝到可重用模塊中,並將其命名爲“Aspect”,即“方面”。簡單的說,它是封裝與業務無關的邏輯或職責,但是由業務模塊一起調用,例如日誌記錄,這樣可以減少系統的重複代碼,減少模塊之間的耦合,並簡化未來的運作性和可維護性。
AOP有兩個明顯的特徵:良好的隔離性和源代碼無關性。
AOP應用範圍:debugging調試、synchronization同步、logging記錄跟蹤等。
Spring依賴注入的方式主要有四個,基於註解注入方式、set注入方式、構造器注入方式、靜態工廠注入方式。推薦使用基於註解注入方式,配置較少,比較方便。
spring事務
七種傳播機制:
1、PROPAGATION_REQUIRED(若當前存在事務,則加入該事務,若不存在事務,則新建一個事務。)
2、PAOPAGATION_REQUIRE_NEW(若當前沒有事務,則新建一個事務。若當前存在事務,則新建一個事務,新老事務相互獨立。外部事務拋出異常回滾不會影響內部事務的正常提交。)
3、PROPAGATION_NESTED(如果當前存在事務,則嵌套在當前事務中執行。如果當前沒有事務,則新建一個事務,類似於REQUIRE_NEW。)
4、PROPAGATION_SUPPORTS(支持當前事務,若當前不存在事務,以非事務的方式執行。)
5、PROPAGATION_NOT_SUPPORTED(以非事務的方式執行,若當前存在事務,則把當前事務掛起。)
6、PROPAGATION_MANDATORY(強制事務執行,若當前不存在事務,則拋出異常)
7、PROPAGATION_NEVER(以非事務的方式執行,如果當前存在事務,則拋出異常。)
四大特性:
1、原子性:操作要麼全部成功,要麼全部失敗回滾。
2、一致性:事務執行前和執行後處於一致性狀態。例如,轉賬前A、B共5000元,A、B之間轉賬後,兩者之和仍應該是5000元。
3、隔離性:事務之間互不干擾。
4、持久性:事務一旦提交,數據的改變是永久性的,即使這時候數據庫發生故障,數據也不會丟失。
隔離級別:
1、讀未提交:隔離級別最差,髒讀、不可重複讀、幻讀都不能避免。
2、讀已提交:可避免髒讀,不可重複讀、幻讀無法避免。
3、可重複讀:可避免髒讀、不可重複讀,幻讀無法避免。
4、序列化:事務順序執行,可避免髒讀、不可重複讀、幻讀,但效率最差。因爲A事務執行時,其他事務必須等待。
注:
1、髒讀:A事務對一條記錄進行修改,尚未提交,B事務已經看到了A的修改結果。若A發生回滾,B讀到的數據就是錯誤的,這就是髒讀。
2、不可重複讀:A事務對一條記錄進行修改,尚未提交,B事務第一次查詢該記錄,看到的是修改之後的結果,此時A發生回滾,B事務又一次查詢該記錄,看到的是回滾後的結果。同一個事務內,B兩次查詢結果不一致,這就是不可重複讀。
3、幻讀:A事務對所有記錄進行修改,尚未提交,此時B事務創建了一條新記錄,A、B都提交。A查看所有數據,發現有一條數據沒有被修改,因爲這是B事務新增的,就想看到了幻象一樣,這就是幻讀。
RabbitMQ如何保證消息不丟失
https://www.cnblogs.com/flyrock/p/8859203.html
1、mybatis以及預編譯,sql注入
MyBatis框架作爲一款半自動化的持久層框架,其SQL語句都要我們自己手動編寫,這個時候當然需要防止SQL注入。其實,MyBatis的SQL是一個具有“輸入+輸出”的功能,類似於函數的結構,如下:
<select id="getBlogById" resultType="Blog" parameterType=”int”>
SELECT id,title,author,content
FROM blog WHERE id=#{id}
</select>
這裏,parameterType表示了輸入的參數類型,resultType表示了輸出的參數類型。迴應上文,如果我們想防止SQL注入,理所當然地要在輸入參數上下功夫。上面代碼中黃色高亮即輸入參數在SQL中拼接的部分,傳入參數後,打印出執行的SQL語句,會看到SQL是這樣的:
SELECT id,title,author,content FROM blog WHERE id = ?
不管輸入什麼參數,打印出的SQL都是這樣的。這是因爲MyBatis啓用了預編譯功能,在SQL執行前,會先將上面的SQL發送給數據庫進行編譯;執行時,直接使用編譯好的SQL,替換佔位符“?”就可以了。因爲SQL注入只能對編譯過程起作用,所以這樣的方式就很好地避免了SQL注入的問題。
【底層實現原理】MyBatis是如何做到SQL預編譯的呢?其實在框架底層,是JDBC中的PreparedStatement類在起作用,PreparedStatement是我們很熟悉的Statement的子類,它的對象包含了編譯好的SQL語句。這種“準備好”的方式不僅能提高安全性,而且在多次執行同一個SQL時,能夠提高效率。原因是SQL已編譯好,再次執行時無需再編譯。
話說回來,是否我們使用MyBatis就一定可以防止SQL注入呢?當然不是,請看下面的代碼:
<select id="getBlogById" resultType="Blog" parameterType=”int”>
SELECT id,title,author,content
FROM blog WHERE id=${id}
</select>
仔細觀察,內聯參數的格式由“#{xxx}”變爲了“${xxx}”。如果我們給參數“id”賦值爲“3”,將SQL打印出來是這樣的:
SELECT id,title,author,content FROM blog WHERE id = 2
<select id="orderBlog" resultType="Blog" parameterType=”map”>
SELECT id,title,author,content
FROM blog ORDER BY ${orderParam}
</select>
仔細觀察,內聯參數的格式由“#{xxx}”變爲了“${xxx}”。如果我們給參數“orderParam”賦值爲“id”,將SQL打印出來是這樣的:
SELECT id,title,author,content FROM blog ORDER BY id
顯然,這樣是無法阻止SQL注入的。在MyBatis中,“${xxx}”這樣格式的參數會直接參與SQL編譯,從而不能避免注入攻擊。但涉及到動態表名和列名時,只能使用“${xxx}”這樣的參數格式。所以,這樣的參數需要我們在代碼中手工進行處理來防止注入。
【結論】在編寫MyBatis的映射語句時,儘量採用“#{xxx}”這樣的格式。若不得不使用“${xxx}”這樣的參數,要手工地做好過濾工作,來防止SQL注入攻擊。
#{}:相當於JDBC中的PreparedStatement
${}:是輸出變量的值
簡單說,#{}是經過預編譯的,是安全的;${}是未經過預編譯的,僅僅是取變量的值,是非安全的,存在SQL注入。
2、java反射
1、通過Object類的getClass方法獲取
2、使用.class的方法(類名.class)
3、使用Class.forName方法
存儲過程和函數的區別
1、返回值不同。函數有一個返回值,而存儲過程是通過參數返回的,可以有多個或沒有;
2、調用不同。函數可在查詢語句中直接調用,而存儲過程必須單獨調用。
varchar和nvarchar區別
1、varchar是非Unicode編碼,nvarchar是Unicode編碼;
2、varchar的最大值是8000,nvarchar是4000;
3、varchar能存儲的字節數是它的長度,nvarchar能存儲的字節數是它長度的2倍;
4、varchar比nvarchar更省空間。
表單重複提交解決辦法?
前端:設置按鈕只觸發一次,提交按鈕變灰。
後端:使用token+session
第一步,用戶調用後臺接口;
第二步,後臺生成sessionToken傳到前端;
第三步,前端將sessionToken傳到後臺;
第四步,後臺將第一次生成的sessionToken和前端傳來的sessionToken進行對比,如果一致就可以提交表單,不一致就表示表單重複提交了。
mysql大數據量存儲
按規則進行分庫分表
JDK1.8中HashMap的變化
1.8之前:HashMap處理“碰撞”的時候,都採用鏈表來存儲,當碰撞的節點很多時,查詢時間是O(n).
1.8中:HashMap處理“碰撞”增加了紅黑樹數據結構,當碰撞節點較少時,採用紅黑樹存儲,當較大時(>8個),採用紅黑樹存儲。
Redis緩存的優勢
1、讀寫性能很高;
2、redis支持多種數據類型。存儲的是key-value格式的數據,其中key是字符串,value的數據類型有String、list、set、hash(哈希)、有序集合zset(sorted set);
3、非關係型數據庫;
4、持久化:redis的持久化方式有rdb和aof兩種;rdb是將內存中的數據壓縮後寫入到硬盤上,aof是將日誌整理寫到硬盤中,並設置不同的持久化方式,有效的額減輕了服務器的壓力,同時在很大程度上防止了數據的丟失。
3、SpringCloud
組件:
Eureka(註冊中心):各個服務啓動時,Eureka Client都會將服務註冊到Eureka Server,並且Eureka Client還可以反過來從Eureka Server拉取註冊表,從而知道其他服務在哪裏。由服務端和客戶端組成;服務端:做服務註冊中心,客戶端:用來處理服務註冊與發現;在應用啓動時,客戶端向服務端註冊自己的服務信息,同時將服務端的服務信息緩存到本地,客戶端會和服務端週期性的進行心跳交互,以更新服務租約和服務信息。
Ribbon(客服端負載均衡):服務間發起請求的時候,基於Ribbon做負載均衡,從一個服務的多臺機器中選擇一臺。
Feign:基於Feign的動態代理機制,根據註解和選擇的機器,拼接請求URL地址,發起請求
Hystrix(斷路器):起請求是通過Hystrix的線程池來走的,不同的服務走不同的線程池,實現了不同服務調用的隔離,避免了服務雪崩的問題。
Netflix Zuul(服務網關):如果前端、移動端要調用後端系統,統一從Zuul網關進入,由Zuul網關轉發請求給對應的服務。
Spring Cloud Config(分佈式配置):配置管理,提供服務器端和客戶端。
服務間通信方式:feign方式(http Message),內部使用了負載均衡。
詳細講解可以查看:https://blog.csdn.net/yeyazhishang/article/details/84344402
4、表結構及索引優化
1、分庫分表、讀寫分離;
2、爲字段選擇合適的數據類型;
3、將字段多的表分解成多個表,增加中間表;
4、混用範式和反範式,適當冗餘;
5、爲查詢創建必要索引,但避免濫用;
6、列字段儘量設置爲not null。
SQL優化
1、尋找最需要優化的語句:分析滿查詢日誌;
2、利用分析工具:explain、profile;
3、避免使用select * ,只取需要的列;
4、使用索引掃描排序;
5、避免where子句對字段進行null值判斷;
6、避免where子句使用 !=、<>操作符和or連接條件;
7、連續的數值,能用between就不要用in
建表三範式:原子性、主鍵唯一性、減少表與表之間的字段冗餘
補充:
創建索引注意事項
1、增刪改操作較多的表不要創建索引;
2、不要在大的文本字段或超長字段建立索引;
3、不要在取值朝一個方向增加的字段(如:日期)上創建索引
索引何時失效
1、like未使用最左前綴,如where A like "%China";
2、搜索一個索引而在另一個索引上做order by;
3、or會使索引失效;
4、若列是字符串類型,要使用引號
JDBC連接數據庫的步驟
1、加載驅動;
2、創建數據庫連接;
3、創建Statement對象,執行SQL語句;
4、獲取結果集,遍歷結果集;
5、關閉資源,關閉數據庫。
Servlet生命週期
首先:加載servlet的class,實例化servlet;
然後:初始化servlet調用init()方法;
其次:調用服務的service的方法處理doGet()和doPost()方法;
最後:關閉容器時調用destroy()銷燬方法。
JAVA特性
封裝:將對象的屬性私有化,對外提供get,set方法,隱藏具體的實現
繼承:子類繼承父類的屬性和方法,並根據需要擴展新的屬性和方法,提高了代碼的複用性
多態:一種事物的不同表現形態。例如:重寫和重載
Throwable
Throwable繼承自Object類,子類主要是Error和Exception類。
Error:程序無法處理的錯誤,只能重啓系統。
Exception:運行時異常和非運行時異常;
運行時異常:只有運行時纔會出錯,所以不需要try catch捕獲,由虛擬機幫我們捕獲;
非運行時異常:寫代碼的時候出錯會提醒我們try catch或throws;
常見的運行時異常:
1、ClassCastException;
2、ClassNotFoundException;
3、IndexOutBoundsException;
4、NullPointerException;
5、ArrayStoreException;
6、SQLException;
7、ArithmeticException;
8、NumberFormatException
常見的非運行時異常:
1、IOException;
2、FileNotFoundException
Nginx(負載均衡器)
是一個高性能的WEB服務器和反向代理服務,最常用的軟件負載均衡器。(網易、淘寶、騰訊、新浪等等互聯網公司)
核心概念:用戶請求先到Nginx,再由Nginx轉發請求到後面的應用服務器(如:Tomcat)
Nginx常用作Http反向代理(接收和轉發請求)
Http請求的處理包括解析和封裝Http內容
負載均衡算法:1、輪循均衡,2、權重輪循均衡,3、隨機均衡
LVS-負載均衡器
核心概念:原本是請求LVS服務器的數據包,被LVS軟件篡改了數據包的目的地,將流量轉移到了Nginx所在的機器IP,從而實現負載均衡
LVS屬於七層協議中的第四層-傳輸層,使用的協議(如TCP)內容比Http簡單,解析和組裝所消耗的CPU、內存等資源比Nginx要低,所以LVS比Nginx快,另外Nginx支持1W~10W併發,而LVS支持10W~50W併發
常用組合:Nginx+Tomcat或者LVS+Nginx+Tomcat
Dubbo
dubbo是一個由阿里巴巴開源的、分佈式的RPC(Remote Procedure Call Protocol-遠程過程調用)和微服務架構,現爲Apache頂級項目
Dubbo提供了三個關鍵功能:
- 基於接口的遠程調用;
- 容錯和負載均衡;
- 服務自動註冊與發現
Dubbo結構圖:
Container:服務運行容器;
Provider:暴露服務的服務提供方;
Registry:服務註冊與發現的註冊中心;
Consumer:調用遠程服務的服務消費方;
Monitor:統計服務的調用次數和調用時間的監控中心
通信方式:RPC
5、SpringMVC
請求處理流程圖:
①:DispatcherServlet是springmvc中的前端控制器(front controller),負責接收request並將request轉發給對應的處理組件.
②:HanlerMapping是springmvc中完成url到controller映射的組件.DispatcherServlet接收request,然後從HandlerMapping查找處理request的controller.
③:Cntroller處理request,並返回ModelAndView對象,Controller是springmvc中負責處理request的組件(類似於struts2中的Action),ModelAndView是封裝結果視圖的組件.
④ ⑤ ⑥:視圖解析器解析ModelAndView對象並返回對應的視圖給客戶端.
線程
實現線程的三種常用方法:繼承Thread、實現Runnable或Callable接口
多線程實現同步的方法:synchronized關鍵字、wait()和notify()方法、Lock
具體實現:
public class MyThread extends Thread{
public void run(){//重寫run方法
//需要執行的線程體
}
}
public class MyThread implements Runnable{
public void run(){//重寫run方法
//需要執行的線程體
}
}
public class MyThread implements Callable{
public int call(){//重寫call方法,可有返回值,可拋出異常
//需要執行的線程體
}
}
兩個常用的方法:sleep()和wait()
sleep():線程的方法,休眠不釋放鎖,到時間自動喚醒;
wait():Object的方法,會釋放鎖,需要通過調用notify()或notifyAll()喚醒
多線程的5種狀態
- 新建:新建線程;
- 就緒:調用start()方法並有返回;
- 運行:獲取CPU,調用run()方法;
- 阻塞:1、sleep()休眠,2、線程要獲取同步鎖,而該鎖正在被其他線程佔用
- 死亡:1、run()正常運行結束,2、exception,3、error
死鎖的產生:兩個或兩個以上線程執行中,因爭奪資源產生的一種互相等待的現象;例如:小明有筆,小紅有本;小明拿着筆等小紅把本給他,小紅拿着本等小明把筆給她
解決辦法:
第一種:代碼避免
通過構造方法共享數據,並使用(等待-喚醒)機制實現線程通信。
等待喚醒機制:A:生產者-先看是否有數據,有就等待,沒有就生產,然後通知消費者消費;
B:消費者-先看是否有數據,有就消費,消費完通知生產者生產,沒有就等待
第二種:信號量
通過信號量設置線程的訪問數量,當一個線程獲取到鎖後,會有一個時間限制,當時間耗盡時,該線程就會釋放鎖由其他線程獲取
6、設計模式
1.單例:餓漢式和懶漢式
餓漢式
public class Singleton{
private static Singleton single = new Singleton();
private Singleton(){}
public static Singleton getInstance(){
return single;
}
}
懶漢式
public calss Singleton{
private static Singleton single;
private Singleton(){}
public static Singleton getInstance(){
if(single == null){
single = new Singleton();
}
return single;
}
}
//Double checked 雙重檢查 線程安全
public class Singleton{
private static volatile Singleton single;
private Singleton(){}
public static Singleton getInstance(){
if(single == null){
synchronized(Singleton.class){
if(single == null){
single = new Singleton();
}
}
}
return single;
}
}
懶漢式:第一次使用實例的時候創建;
餓漢式:在加載類的時候就會創建類的單例,並保存在類中。
2.裝飾設計模式
概念:通過“裝飾”一個類,增強它的功能。例如:買一輛車,想爲新車裝一個倒車雷達,這就相當於爲這輛汽車增加新的功能。
應用:IO流中字節緩衝流(BufferedInputStream和BufferedOutputStream)
3.工廠模式
應用:spring容器(IOC)中對象的管理應用了工廠模式,對象的生成應用了單例模式;
AOP:動態代理(JDK、CGLIB)、靜態代理(靜態織入)
7、算法
冒泡排序:
int[] a = {5,2,8,6,4,9};
for(int i=0;i<a.length;i++){
for(int j=0;j<a.length-i-1;j++){
if(a[j]>a[j+1]){
int temp = a[j];
a[j]=a[j+1];
a[j+1]=temp;
}
}
}
快速排序:
public static void sort(int a[], int low, int hight) {
int i, j, index;
if (low > hight)return;
i = low;
j = hight;
index = a[i]; // 用子表的第一個記錄做基準
while (i < j) { // 從表的兩端交替向中間掃描
while (i < j && a[j] >= index)
j--;
if (i < j)
a[i++] = a[j];// 用比基準小的記錄替換低位記錄
while (i < j && a[i] < index)
i++;
if (i < j) // 用比基準大的記錄替換高位記錄
a[j--] = a[i];
}
a[i] = index;// 將基準數值替換回 a[i]
sort(a, low, i - 1); // 對低子表進行遞歸排序
sort(a, i + 1, hight); // 對高子表進行遞歸排序
}
public static void quickSort(int a[]) {
sort(a, 0, a.length - 1);
}
public static void main(String[] args) {
int a[] = { 49, 38, 65, 97, 76, 13, 27, 49 };
quickSort(a);
System.out.println(Arrays.toString(a));
}
二叉樹:
排序規則:前序遍歷(根、左、右),中序遍歷(左、中、根),後序遍歷(左、右、根)
遍歷結果如下:
前序遍歷:ABCDEFGHK
中序遍歷:BDCAEHGKF
後序遍歷:DCBHKGFEA
遞歸算法:
public static int factorial(int m) {
if (m < 0){
return 0;
}else if (m == 1){
return 1;
}else{
return m * factorial(m - 1);
}
}
TCP和UDP
TCP:面向連接,傳輸的數據量大,可靠,傳輸比較慢(三次握手)
UDP:面向非連接,傳輸數據量小,不可靠,傳輸比較快
TCP佔包問題:
原因:數據發送頻繁
解決方法:1、發送固定長度數據
2、把數據大小與數據同時發送
3、用特殊標記進行標記
Servlet九大內置對象
request:請求對象
response:響應對象
page:頁面對象
exception:例外對象
pageContext:頁面上下文對象
session:會話對象
out:輸出對象
application:應用程序對象
config:配置對象
zookeeper
集羣的搭建原則:容災原理(創建奇數臺)
應用:名字服務、配置管理、提供分佈式同步和集羣管理
數據類型
1、基本數據類型:
byte:1字節
short:2字節
int:4字節
long:8字節
char:2字節
float:4字節
double:8字節
boolean
注:1字節=8bit(位)
2、引用數據類型:
類:class
接口:interface
數組:[ ]
sql語句插入一條記錄同時獲取剛插入的id
使用output關鍵字輸出,inserted爲已插入的臨時表
例如:insert into student(name,studentno,sex,age)
output inserted.id values("張三","10000",'男',22)
集合
Connection接口:
List:有序,可重複性
- ArrayList
優點: 底層數據結構是數組,查詢快,增刪慢。
缺點: 線程不安全,效率高 - Vector
優點: 底層數據結構是數組,查詢快,增刪慢。
缺點: 線程安全,效率低 - LinkedList
優點: 底層數據結構是鏈表,查詢慢,增刪快。
缺點: 線程不安全,效率高
Set:無序,不可重複
- HashSet
- 底層數據結構是哈希表。(無序,唯一)
- 如何來保證元素唯一性?
- 1.依賴兩個方法:hashCode()和equals()
- LinkedHashSet
- 底層數據結構是鏈表和哈希表。(FIFO插入有序,唯一)
- 1.由鏈表保證元素有序
- 2.由哈希表保證元素唯一
- TreeSet
- 底層數據結構是紅黑樹。(唯一,有序)
- 1. 如何保證元素排序的呢?
- 自然排序
- 比較器排序
Map接口有三個比較重要的實現類,分別是HashMap、TreeMap和HashTable。
- TreeMap是有序的,HashMap和HashTable是無序的。
- Hashtable的方法是同步的,HashMap的方法不是同步的。
- Hashtable是線程安全的,HashMap是非線程安全的。
- Hashtable效率低,HashMap效率高。
- LinkedHashMap記錄了數據插入順序,TreeMap能夠把保存的記錄根據鍵排序
HashMap底層
1、什麼是HashMap?
HashMap接受null鍵null值,但Hashtable不能;
HashMap是非線程安全的,但效率快;
HashMap儲存的是鍵值對
2、工作原理
HashMap是基於hashing原理,我們使用put(key,value)儲存對象到HashMap中,使用get(key)從HashMap中獲取對象;當我們給put()方法傳遞鍵和值時,我們先調用hashCode()方法,返回的hashCode用於找到bucket位置來儲存Entry對象
詳細講解可參考:https://blog.csdn.net/suifeng629/article/details/82179996
補充:
ConcurrentHashMap:採用了鎖分段技術保證線程安全。但計算其長度的時候是不安全的。
鎖分段技術:首先將數據分成一段一段的存儲,然後給每一段數據配一把鎖,當一個線程佔用鎖訪問其中一個段數據的時候,其他段的數據也能被其他線程訪問。
紅黑樹特性:1、每個節點或是黑色,或是紅色;
2、根節點是黑色;
3、每個葉子節點是黑色;
4、如果一個節點是紅色的,則它的子節點必須是黑色的;
5、從一個節點到該節點的子孫節點的所有路徑上包含相同數目黑節點數。
MyBatis的一級緩存和二級緩存
一級緩存:sqlSession級別,自動開啓
二級緩存:mapper級別,手動開啓(配置),開啓二級緩存後,需要將緩存的pojo實現序列化
Spring和MyBatis整合時,每次查詢後要關閉sqlSession,關閉後數據會被清空,所以Spring整合後,若無事務,一級緩存無意義,開啓二級緩存後,會把sqlSession一級緩存中的數據添加到二級緩存。
總結:查詢多commit少,且對查詢實時性要求不高,採用MyBatis二級緩存降低數據庫訪問量,提高查詢效率。
二級緩存應用場景:對於訪問多的查詢請求且用戶對查詢結果實時性要求不高,此時可採用mybatis二級緩存技術降低數據庫訪問量,提高訪問速度,業務場景比如:耗時較高的統計分析sql、電話賬單查詢sql等。mybaits的二級緩存區域以mapper爲單位劃分的。多個sqlSession可以共享一個mapper中的二級緩存區域。
JVM體系結構
補充:
JVM用永久代(PermanetGeneration)來存放方法區。
JVM分別對新生代和舊生代採用不同的垃圾回收機制:
新生代:複製算法;
老年代:標記-清除算法
堆和方法區是所有線程共有的,堆內存可分爲:新生代和老年代
JVM GC
範圍:只回收堆區和方法區內的對象
回收判定:1、對象沒有引用
2、程序在作用域正常執行完畢
3、程序調用System.exit()
4、程序發生意外終止(被殺線程等)
Minor GC:最新創建的對象在新生代區域中很快變得不可達,然後消失的過程
Full GC:對象從老年代區域消失的過程
生產者消費者模式解決了哪些問題
1、解耦
2、支持併發
Http
1請求:
請求頭:
1. 請求方式(Post、Get)
2. url
3. 協議:http/1.0,2.0
4. 頭參數:host,cookie,connection,user-Agent
請求體:Post(有),Get(無)
2響應:
1. 響應類型:文字、圖片等
2. 長度
3. 狀態碼:200(成功),302(在其他地址發現請求),403(禁止訪問),404(資源不存在),500(服務器內部錯誤)
4. 響應體:代碼
3狀態:
cookie,session 連接狀態
4安全/攻擊
附加:
1開頭:信息,服務器收到請求;
2開頭:成功;
3開頭:重定向,要進一步操作完成請求;
4開頭:客戶端錯誤,請求包含語法錯誤或無法完成請求;
5開頭:服務器錯誤,服務器在處理請求的過程中發生了錯誤
http和https的區別:http://www.360doc.com/content/18/0710/19/44130189_769384412.shtml
過濾器
過濾器應用到了責任鏈模式
多個過濾器的執行順序是按web.xml的配置順序執行的。
IO流
Thread類常用方法
這裏列舉幾個
- start()啓動線程
- getId()獲得線程ID
- getName()獲得線程名字
- getPriority()獲得優先權
- getState()獲得線程狀態
- sleep()休眠線程
- interrupt()中斷線程
- currentThread()獲得正在執行的線程對象
Maven的功能
- 通過maven內置的Tomcat啓動項目;
- 利用maven直接把maven項目打成war包;
- 使用maven對項目進行熱部署
內存泄漏和內存溢出
內存溢出:out of memory,指程序在申請內存時,沒有足夠的內存空間供其使用
內存泄漏:memory leak,指程序在申請內存後,無法釋放已申請的內存空間
補充:
JVM內存溢出原因:
- 內存中加載的數據量過大;
- 代碼中存在死循環;
- 集合類中有對對象的引用,使用完未清空,使JVM不能回收;
- 啓動參數內存值設定過小
分佈式鎖的實現方式
這裏列出三種:基於數據庫實現分佈式鎖、基於緩存(Redis等)實現分佈式鎖、基於Zookeeper實現分佈式鎖
第一種【基於數據庫實現分佈式鎖】:在數據庫中創建一個表,表中包含方法名等字段,並在方法名字段上創建唯一索引,想要執行某個方法,就使用這個方法名向表中插入數據,成功插入則獲取鎖,執行完成後刪除對應的行數據釋放鎖
第二種【基於Redis的實現方式】:
- 獲取鎖的時候,使用set加鎖,並使用expire命令爲鎖添加一個超時時間,超過該時間則自動釋放鎖,鎖的value值爲一個隨機生成的UUID,通過此在釋放鎖的時候進行判斷;
- 獲取鎖的時候還設置一個獲取的超時時間,若超過這個時間則放棄獲取鎖;
- 釋放鎖的時候,通過UUID判斷是不是該鎖,若是該鎖,則執行delete進行鎖釋放。
選取原因:Redis有很高的性能;Redis命令對此支持性好,實現起來比較方便
補充說明:
加鎖代碼:
jedis.set(String key, String value, String nxxx, String expx, int time);
第一個爲key,我們使用key來當鎖,因爲key是唯一的。
第二個爲value,我們傳的是requestId,很多童鞋可能不明白,有key作爲鎖不就夠了嗎,爲什麼還要用到value?原因就是我們在上面講到可靠性時,分佈式鎖要滿足第四個條件解鈴還須繫鈴人,通過給value賦值爲requestId,我們就知道這把鎖是哪個請求加的了,在解鎖的時候就可以有依據。requestId可以使用UUID.randomUUID().toString()方法生成。
第三個爲nxxx,這個參數我們填的是NX,意思是SET IF NOT EXIST,即當key不存在時,我們進行set操作;若key已經存在,則不做任何操作;
第四個爲expx,這個參數我們傳的是PX,意思是我們要給這個key加一個過期的設置,具體時間由第五個參數決定。
第五個爲time,與第四個參數相呼應,代表key的過期時間。
第三種【基於Zookeeper實現分佈式鎖】:
- 創建一個目錄mylock;
- 線程A想獲取鎖就在mylock目錄下創建臨時順序節點;
- 獲取mylock目錄下所有的子節點,然後獲取比自己小的兄弟節點,如果不存在,則說明當前線程順序號最小,獲得鎖;
- 線程B獲取所有節點,判斷自己不是最小節點,設置監聽比自己次小的節點;
- 線程A處理完,刪除自己的節點,線程B監聽到變更事件,判斷自己是不是最小的節點,如果是則獲得鎖。
優點:具備高可用、可重入、阻塞鎖特性,可解決失效死鎖問題。
缺點:因爲需要頻繁的創建和刪除節點,性能上不如Redis方式。
數據庫連接池
使用了連接池可以帶來諸多便利,下面列出幾點主要的供大家看:
- 資源重用:由於數據庫連接得到重用,避免了頻繁創建、釋放連接引起的大量性能開銷。在減少系統消耗的基礎上,另一方面也增進了系統運行環境的平穩性(減少內存碎片以及數據庫臨時進程/線程的數量)。
- 更快的系統響應速度:數據庫連接池在初始化過程中,往往已經創建了若干數據庫連接置於池中備用。此時連接的初始化工作均已完成。對於業務請求處理而言,直接利用現有可用連接,避免了數據庫連接初始化和釋放過程的時間開銷,從而縮減了系統整體響應時間。
- 新的資源分配手段:對於多應用共享同一數據庫的系統而言,可在應用層通過數據庫連接的配置,實現數據庫連接池技術,幾年錢也許還是個新鮮話題,對於目前的業務系統而言,如果設計中還沒有考慮到連接池的應用,那麼…….快在設計文檔中加上這部分的內容吧。某一應用最大可用數據庫連接數的限制,避免某一應用獨佔所有數據庫資源。
- 統一的連接管理,避免數據庫連接泄漏:在較爲完備的數據庫連接池實現中,可根據預先的連接佔用超時設定,強制收回被佔用連接。從而避免了常規數據庫連接操作中可能出現的資源泄漏。
想對數據庫連接池做更深入的學習,可以點擊下面鏈接:https://cloud.tencent.com/developer/news/312412
md5加密、 3-DES加密、 base64編碼、 URLEncoder編碼
- md5加密,該加密算法是單向加密,即加密的數據不能再通過解密還原。相關類包含在java.security.MessageDigest包中。
- 3-DES加密,該加密算法是可逆的,解密方可以通過與加密方約定的密鑰匙進行解密。相關類包含在javax.crypto.*包中。
- base64編碼,是用於傳輸8bit字節代碼最常用的編碼方式。相關類在sun.misc.BASE64Decoder 和sun.misc.BASE64Encoder 中。
- URLEncoder編碼,是一種字符編碼,保證被傳送的參數由遵循規範的文本組成。相關類在java.net.URLEncoder包中。
synchronized
在JVM中,對象在內存中的佈局分爲三塊區域:對象頭、實例變量、填充數據。
java對象頭是實現synchronized鎖對象的基礎。JVM可以從方法常量池中的方法表結構(method_info Structure) 中的 ACC_SYNCHRONIZED 訪問標誌區分一個方法是否同步方法。當方法調用時,調用指令將會 檢查方法的 ACC_SYNCHRONIZED 訪問標誌是否被設置,如果設置了,執行線程將先持有monitor, 然後再執行方法,最後再方法完成時釋放monitor。
補充:如何保證多線程讀寫數據時數據的一致性?
同步:使用synchronized關鍵字,或使用鎖對象;
使用volatile關鍵字,它能使變量在值發生改變時儘快讓其他線程知道。
區別:1、volatile能實現變量的修改可見性,但不具備原子性;
2、volatile使用在變量級別,synchronized可使用在變量和方法;
3、volatile不會造成線程阻塞,synchronized可能會造成線程阻塞。
分佈式微服務化架構
- 容易開發和實現
- 經常發佈,部署複雜
- 響應時間慢,吞吐量大
- 擴展性好
- 模塊化後,重用性變高
Linux常用命令
創建文件夾:mkdir abc(文件夾名)
打包並壓縮gzip:tar -zcvf abc.tar.gz abc
解壓:tar -zxvf abc.tar.gz
創建空的文件:touch a(文件名)
刪除文件夾所有文件:rm -rf abc
刪除空文件夾:rmdir abc
刪除文件:rm a
查詢文件:在查詢的文件夾下才能查找 find a
查看日誌:tail -f a(文件名)
查看指定行數:tail -fn 10 a
查看文件所有內容:tail a
查看端口占用情況:lsof -i:8080
查看端口進程情況:netstat -tunlp |grep 8080
磁盤佔用情況:du -sh abc
服務器內存使用情況:free
查看當前所有程序用戶的線程:ps -ef
查看tomcat當前線程情況:ps -ef|grep tomcat
某個進程使用情況:top | grep 'xxx'
查看cpu情況:cat /proc/cpuinfo
推薦:https://blog.csdn.net/xinzhifu1/article/details/59109792/
Spring事務
特性:原子性、一致性、隔離型、持久性
隔離級別:讀未提交、讀已提交、可重複讀、串行化
讀未提交:髒讀,一個事務可以讀取另一個事務未提交的內容;
讀已提交:不可重複讀,不同的事務重複讀了一條記錄會出問題;
可重複讀:一個事務在讀取了記錄之後,這條記錄不能再被修改,也就是把這一行記錄給鎖住了,不允許其他的事物染指此行記錄
串行化:一個事務必須等待另一個事務執行完纔可以執行
Dubbo的配置分類
抽象類和接口類
抽象類 | 接口類 |
有方法的具體實現 | 只能有抽象方法 |
成員變量可以是任意類型的 | 成員變量只能是public static final類型的 |
可以有靜態代碼塊和靜態方法 | 不可以 |
一個類只能繼承一個抽象類 | 一個類可以實現多個接口 |
注意:JDK8之後,接口可以有默認方法和靜態方法。
高併發
- 緩存
- 讀寫分離
- 數據庫鎖
Git
克隆 | git clone SSH/HTTPS路徑 |
查看遠程的所有分支列表 | git branch -a |
查看本地的git分支 | git branch |
切換分支 | git checkout 分支名 |
提交項目 | git add . |
git commit -m '說明' | |
git push origin 主支/分支名 | |
更新所有遠程分支的本地分支 | git fetch |
合併分支 | git merge |
更新後自動合併到本地分支(相當於前面兩個命令) | git pull |
放棄本地修改,使遠程庫內容強制覆蓋本地代碼(HEAD指向最新版本) | git reset --hard origin/master |
查看提交歷史 | git log |
使用圖形化工具來解決衝突 | git mergetool |
刪除本地跟蹤,避免合併衝突 | git rm -r --cached WEB-INF/classes |
git rm -r --cached .bpmn/* | |
git rm -r --cached .externalToolBuilders | |
git rm -r --cached .settings/* | |
git rm -r --cached .classpath | |
git rm -r --cached .mymetdata | |
git rm -r --cached target/* |
想學習更多,請進入https://www.liaoxuefeng.com/廖雪峯網站,進行學習