參考鏈接: 在Java中將預定義的類名用作類或變量名
花了一星期把學過的都整理一遍
?盡量易懂,從基礎到框架
?
?最新版大廠面經匯總出爐,持續更新中
?
?
??
?
?
?
??
?
?
?
??
?
?匯總完了上傳網盤,設計到后端架構師的一切知識
?
?
??
?
?如果沒更新就代表我死了
?一. Java基礎
?1. 基本數據類型
?基本數據類型分為三大類:
?數值型:
? 整數型:byte【-2^7,2^7-】,short【-2^15,2^15】,int【-2^31,2^31】,long【-2^64,2^64】
? 浮點型:float,double
?字符型:char
?布爾型:boolean
?2. 基本題
?2.1Java有沒有goto??
?java中的保留字,現在沒有在java中使用。
?2.2說說&和&&的區別。?
?&和&&都可以用作邏輯與的運算符,表示邏輯與(and),當運算符兩邊的表達式的結果都為true時,整個運算結果才為true,否則,只要有一方為false,則結果為false。
? &&還具有短路的功能,即如果第一個表達式為false,則不再計算第二個表達式,例如,對于if(str != null && !str.equals(“”))表達式,當str為null時,后面的表達式不會執行,所以不會出現NullPointerException如果將&&改為&,則會拋出NullPointerException異常。If(x==33 & ++y>0) y會增長,If(x==33 && ++y>0)不會增長
?&還可以用作位運算符,當&操作符兩邊的表達式不是boolean類型時,&表示按位與操作,我們通常使用0x0f來與一個整數進行&運算,來獲取該整數的最低4個bit位,例如,0x31 & 0x0f的結果為0x01。?
?2.3switch語句能否作用在byte上,能否作用在long上,能否作用在String上??
?在switch(expr1)中,expr1只能是一個整數表達式或者枚舉常量,整數表達式可以是int基本類型或Integer包裝類型,由于,byte,short,char都可以隱含轉換為int,所以,這些類型以及這些類型的包裝類型也是可以的。顯然,long和String類型都不符合switch的語法規定,并且不能被隱式轉換成int類型,所以,它們不能作用于swtich語句中。?
?2.4說一下"=="和equals方法究竟有什么區別?
?非常經典的一個面試題?先說清楚一個,再來說另一個?
?==用來判斷兩個變量之間的的值是否相等。變量就可以分為基本數據類型變量,引用類型。
?如果是基本數據類型的變量直接比較值而引用類型要比較對應的引用的內存的首地址。
?
?
??
?
?equals 用來比較兩個對象長得是否一
?2.5靜態變量和實例變量的區別?
?在語法定義上的區別:靜態變量前要加static關鍵字,而實例變量前則不加。
?在程序運行時的區別:實例變量屬于某個對象的屬性,必須創建了實例對象,其中的實例變量才會被分配空間,才能使用這個實例變量。靜態變量不屬于某個實例對象,而是屬于類,所以也稱為類變量,只要程序加載了類的字節碼,不用創建任何實例對象,靜態變量就會被分配空間,靜態變量就可以被使用了。總之,實例變量必須創建對象后才可以通過這個對象來使用,靜態變量則可以直接使用類名來引用。
?2.6是否可以從一個static方法內部發出對非static方法的調用?
? 不可以。因為非static方法是要與對象關聯在一起的,必須創建一個對象后,才可以在該對象上進行方法調用,而static方法調用時不需要創建對象,可以直接調用。也就是說,當一個static方法被調用時,可能還沒有創建任何實例對象,如果從一個static方法中發出對非static方法的調用,那個非static方法是關聯到哪個對象上的呢?這個邏輯無法成立,所以,一個static方法內部不可以發出對非static方法的調用。
?2.7java中實現多態的機制是什么??
?靠的是父類或接口定義的引用變量可以指向子類或具體實現類的實例對象,而程序調用的方法在運行期才動態綁定,就是引用變量所指向的具體實例對象的方法,也就是內存里正在運行的那個對象的方法,而不是引用變量的類型中定義的方法。
?2.8JVM
?(1) 基本概念:?
? JVM是可運行Java代碼的假想計算機 ,包括一套字節碼指令集、一組寄存器、一個棧、 一個垃圾回收,堆 和 一個存儲方法域。JVM 是運行在操作系統之上的,它與硬件沒有直接 的交互
?(2) 運行過程
?我們都知道 Java 源文件,通過編譯器,能夠生產相應的.Class 文件,也就是字節碼文件, 而字節碼文件又通過Java虛擬機中的解釋器,編譯成特定機器上的機器碼 。?
?也就是如下:?
? ① Java源文件—->編譯器—->字節碼文件?
? ② 字節碼文件—->JVM—->機器碼?
? 每一種平臺的解釋器是不同的,但是實現的虛擬機是相同的,這也就是 Java 為什么能夠 跨平臺的原因了 ,當一個程序從開始運行,這時虛擬機就開始實例化了,多個程序啟動就會 存在多個虛擬機實例。程序退出或者關閉,則虛擬機實例消亡,多個虛擬機實例之間數據不 能共享。
?1. JVM 內存區域
?JVM 內存區域主要分為線程私有區域【程序計數器、虛擬機棧、本地方法區】、線程共享區 域【JAVA堆、方法區】、直接內存。?
?線程私有數據區域生命周期與線程相同, 依賴用戶線程的啟動/結束 而 創建/銷毀(在 Hotspot VM 內, 每個線程都與操作系統的本地線程直接映射, 因此這部分內存區域的存/否跟隨本地線程的 生/死對應)。?
?線程共享區域隨虛擬機的啟動/關閉而創建/銷毀。?
?直接內存并不是JVM運行時數據區的一部分, 但也會被頻繁的使用: 在JDK 1.4引入的NIO提 供了基于 Channel 與 Buffer 的 IO 方式, 它可以使用 Native 函數庫直接分配堆外內存, 然后使用 DirectByteBuffer 對象作為這塊內存的引用進行操作(詳見: Java I/O 擴展), 這樣就避免了在 Java 堆和Native堆中來回復制數據, 因此在一些場景中可以顯著提高性能。?
?2.9.AVA 四種引用類型
?1. 強引用?
?在 Java 中最常見的就是強引用,把一個對象賦給一個引用變量,這個引用變量就是一個強引 用。當一個對象被強引用變量引用時,它處于可達狀態,它是不可能被垃圾回收機制回收的,即 使該對象以后永遠都不會被用到JVM也不會回收。因此強引用是造成Java內存泄漏的主要原因之 一。?
?2. 軟引用?
?軟引用需要用 SoftReference 類來實現,對于只有軟引用的對象來說,當系統內存足夠時它 不會被回收,當系統內存空間不足時它會被回收。軟引用通常用在對內存敏感的程序中。?
?3. 弱引用?
?弱引用需要用WeakReference 類來實現,它比軟引用的生存期更短,對于只有弱引用的對象 來說,只要垃圾回收機制一運行,不管JVM的內存空間是否足夠,總會回收該對象占用的內存。?
?4. 虛引用?
?虛引用需要PhantomReference類來實現,它不能單獨使用,必須和引用隊列聯合使用。虛 引用的主要作用是跟蹤對象被垃圾回收的狀態。
?3.0JVM 類加載機制
?JVM 類加載機制分為五個部分:加載,驗證,準備,解析,初始化
?1. 加載 加載是類加載過程中的一個階段,這個階段會在內存中生成一個代表這個類的java.lang.Class對 象,作為方法區這個類的各種數據的入口。注意這里不一定非得要從一個Class文件獲取,這里既 可以從ZIP包中讀取(比如從jar包和war包中讀取),也可以在運行時計算生成(動態代理), 也可以由其它文件生成(比如將JSP文件轉換成對應的Class類)。?
?2. 驗證 這一階段的主要目的是為了確保Class文件的字節流中包含的信息是否符合當前虛擬機的要求,并 且不會危害虛擬機自身的安全。?
?3. 準備 準備階段是正式為類變量分配內存并設置類變量的初始值階段,即在方法區中分配這些變量所使 用的內存空間。注意這里所說的初始值概念,比如一個類變量定義為:
?4.解析 解析階段是指虛擬機將常量池中的符號引用替換為直接引用的過程。符號引用就是class文件中 的
?5. 符號引用 ? 符號引用與虛擬機實現的布局無關,引用的目標并不一定要已經加載到內存中。各種虛擬 機實現的內存布局可以各不相同,但是它們能接受的符號引用必須是一致的,因為符號引 用的字面量形式明確定義在Java虛擬機規范的Class文件格式中。?
?6. 直接引用 ? 直接引用可以是指向目標的指針,相對偏移量或是一個能間接定位到目標的句柄。如果有 了直接引用,那引用的目標必定已經在內存中存在。?
?7. 初始化 初始化階段是類加載最后一個階段,前面的類加載階段之后,除了在加載階段可以自定義類加載 器以外,其它操作都由JVM主導。到了初始階段,才開始真正執行類中定義的Java程序代碼。?
?8. 類構造器<client> 初始化階段是執行類構造器<client>方法的過程。<client>方法是由編譯器自動收集類中的類變 量的賦值操作和靜態語句塊中的語句合并而成的。虛擬機會保證子<client>方法執行之前,父類 的<client>方法已經執行完畢,如果一個類中沒有對靜態變量賦值也沒有靜態語句塊,那么編譯 器可以不為這個類生成<client>()方法。
?3.包裝類型:
?包裝類型是對基本數據類型不足之處的補充,基本數據類型傳遞方式是值傳遞,而包裝類型是引用傳遞,同時提供了很多數據類型間轉換的方法?
?4.集合
?
?
??
?
?List:有序,可重復的。可以通過索引快速的查找,但是進行增刪操作時后續的數據需要移動,索引增刪速度慢。
?Set:無序,不可重復的
?Map:鍵值對,鍵唯一,值不唯一。根據鍵得到值,對map集合遍歷時先得到鍵的set集合,對set集合進行遍歷,得到相應的值。
?4.1ArrayList
?1)有序表 有序,查找效率高
?2)內部原理:object【】數組
?3)擴容方式是原長度的1.5倍
?(ArrayList 是最常用的 List 實現類,內部是通過數組實現的,它允許對元素進行快速隨機訪問。數 組的缺點是每個元素之間不能有間隔,當數組大小不滿足時需要增加存儲能力,就要將已經有數 組的數據復制到新的存儲空間中。當從 ArrayList 的中間位置插入或者刪除元素時,需要對數組進 行復制、移動、代價比較高。因此,它適合隨機查找和遍歷,不適合插入和刪除。)
?4.2linkedList
?1)鏈表,有序,插入和刪除效率高
?2)內部原理:雙鏈表
?3)默認是空節點
?(LinkedList是用鏈表結構存儲數據的,很適合數據的動態插入和刪除,隨機訪問和遍歷速度比較 慢。另外,他還提供了List接口中沒有定義的方法,專門用于操作表頭和表尾元素,可以當作堆 棧、隊列和雙向隊列使用。)
?4.3迭代器Iterator
?1)原理:邏輯上存在用來保存數組原始地址的模型,通過移動游標獲取元素的地址,從而快速的獲取元素
?2)作用:用于集合的遍歷
?4.4vector向量表
?1)內部原理:object【】
?2)默認空間10
?3)是線程安全
?4)擴容方式:擴容為原來的2倍
?(Vector與ArrayList一樣,也是通過數組實現的,不同的是它支持線程的同步,即某一時刻只有一 個線程能夠寫 Vector,避免多線程同時寫而引起的不一致性,但實現同步需要很高的花費,因此, 訪問它比訪問ArrayList慢。)
?4.5HashMap
?1)根據鍵的HashCode值存儲數據,根據鍵可以直接獲取它的值,具有很快的訪問速度
?2)遍歷時,取得數據的順序是完全隨機的,因為鍵對象不可以重復,最多只允許一條記錄的鍵為null,允許多條記錄的值為null
?3)非同步的
?(HashMap根據鍵的hashCode值存儲數據,大多數情況下可以直接定位到它的值,因而具有很快 的訪問速度,但遍歷順序卻是不確定的。 HashMap最多只允許一條記錄的鍵為null,允許多條記 錄的值為 null。HashMap 非線程安全,即任一時刻可以有多個線程同時寫 HashMap,可能會導 致數據的不一致。如果需要滿足線程安全,可以用 Collections 的 synchronizedMap 方法使 HashMap 具有線程安全的能力,或者使用 ConcurrentHashMap。我們用下面這張圖來介紹 HashMap 的結構。?
?(Java8 對 HashMap 進行了一些修改,最大的不同就是利用了紅黑樹,所以其由 數組+鏈表+紅黑 樹 組成。?
?根據 Java7 HashMap 的介紹,我們知道,查找的時候,根據 hash 值我們能夠快速定位到數組的 具體下標,但是之后的話,需要順著鏈表一個個比較下去才能找到我們需要的,時間復雜度取決 于鏈表的長度,為 O(n)。為了降低這部分的開銷,在 Java8 中,當鏈表中的元素超過了 8 個以后, 會將鏈表轉換為紅黑樹,在這些位置進行查找的時候可以降低時間復雜度為 O(logN)。)
?4.6 HashTable
?1)是線程安全的,但是效率低,支持線程同步,任意時刻只有一個線程能寫HashTable
?2)繼承自Dictionary類,不允許記錄的鍵或者值為null
?3)同步的
?(Hashtable 是遺留類,很多映射的常用功能與 HashMap 類似,不同的是它承自 Dictionary 類, 并且是線程安全的,任一時間只有一個線程能寫 Hashtable,并發性不如 ConcurrentHashMap, 因為 ConcurrentHashMap 引入了分段鎖。Hashtable 不建議在新代碼中使用,不需要線程安全 的場合可以用HashMap替換,需要線程安全的場合可以用ConcurrentHashMap替換。)
?4.7HashSet
?1)內部原理是HashMap,只是應用了hashmap的key值
?2)默認是空的集合
?TreeSet:內部原理是TreeMap,內部實現是二叉樹,插入有序,按照自然排序
?(哈希表邊存放的是哈希值。HashSet存儲元素的順序并不是按照存入時的順序(和List顯然不 同) 而是按照哈希值來存的所以取數據也是按照哈希值取得。元素的哈希值是通過元素的 hashcode方法來獲取的, HashSet首先判斷兩個元素的哈希值,如果哈希值一樣,接著會比較 equals方法 如果 equls結果為true ,HashSet就視為同一個元素。如果equals 為false就不是 同一個元素。?
?哈希值相同equals為false的元素是怎么存儲呢,就是在同樣的哈希值下順延(可以認為哈希值相 同的元素放在一個哈希桶中)。也就是哈希一樣的存一列。)
?4.8ArrayList和LinkedList有何區別
?1)ArrayList是基于動態數組的數據結構,LinkedList是基于鏈表的數據結構
?2)ArrayList通常用來做查詢,因為linkedlist要移動指針。
?3)linkedlist用來做增刪,因為在一個元素被插入到中間的時候, 涉及改變數組的大小,或更新索引
?4)LinkedList比ArrayList消耗更多的內存,因為LinkedList中的每個節點存儲了前后節點的引用。?
?4.9Hashmap和Hashtable的區別
?1)Hashmap允許空鍵值,hashtable不行
?2)Hashmap繼承自AbstractMap,Hashtable繼承自Dictionary類,兩者都實現了map接口
?3)Hashmap的方法不是同步的,hashtable是同步的
?4)hashmap是線程不安全的效率高,hashtable是線程安全的,效率低
?4.1Array和ArrayList有何不同,什么時候更適合用array
?4.10Array和ArrayList有何區別?什么時候更適合用Array?
? Array可以容納基本類型和對象,而ArrayList只能容納對象。
? Array是指定大小的,而ArrayList大小是固定的。
? Array沒有提供ArrayList那么多功能,比如addAll、removeAll和iterator等。。
?如果列表的大小已經指定,大部分情況下是存儲和遍歷它們。如果你要使用多維數組,使用[][]比List<List<>>更容易。
?4.11棧和隊列是什么,他們的區別
?棧和隊列都是用來存儲數據的,
?棧可以保存null值并且允許有重復值:push方法:將指定元素插入棧底,pop方法:彈出棧頂元素
?隊列表示先進后出的集合,也可以保存null值 并且允許重復:Enqueue方法:將指定元素插入隊尾,Dequeue方法:隊列首元素出列
?4.12List和Map區別
?一個是存儲單列數據的集合,另一個是存儲鍵和值這樣的雙列數據的集合,List中存儲的數據是由順序的,并且允許重復,Map中存儲的數據是沒有順序的,其鍵是不能重復的,它的值是可以重復的
?4.13ArrayList,vertor,LinkedList的存儲性和特性
?ArrayList和vertor都是使用數組方式存儲數據,都允許直接按序號索引元素,但是插入元素要涉及數組元素移動等內存操作,所有索引數據快而插入數據慢
?Vertor由于使用synchronized方法(線程安全),通常性能上比ArrayList差
?LinkedList使用雙向鏈表實現存儲,按序號索引數據需要進行前后遍歷,但是插入數據時只需要記錄本項的前后項即可,所有插入速度較快
?LinkedList也是線程不安全的,但是他提供了一些方法,使得LinkedList可以被當做堆棧和隊列來使用
?4.14棧和堆的區別
?棧內存是指應用程序進入一個方法時,會為這個方法單獨得劃分一個存儲空間,,用于存儲這個方法的函數和局部變量等,當這個方法結束時,這個方法中的棧會被釋放,棧中的函數和局部變量等也會被釋放
?堆一般用于存放不放在方法棧中的數據,例如,new一個對象就是放在堆中的,所有,它不會隨方法的消失而消失,方法中的局部變量被final修飾后的也是放在堆中
?5.多線程
?5.1多線程運行原理:
?CPU在做線程的時間片切換
?電腦在運行程序時不是在同時進行的。CPU復制程序的運行,而CPU在運行程序的過程中某個時間點上,它其實只能運行一個程序,cup它可以在多個線程中進行高速轉換,用我們肉眼看不到的速度,每個程序就是進程,而每個進程中就會有多線程,CPU就是在 這些線程之間進行轉換的
?5.2線程生命周期(狀態)
?
?
??
?
?新建狀態:一個新產生的線程從新建狀態開始了它的生命周期,它保持這個狀態直到程序start這個線程
?運行狀態:當一個新狀態的線程被start之后,線程就變成了可運行狀態,一個線程在此狀態下被認為是開始執行線程任務
?就緒狀態:當一個線程等待另一個線程執行一個任務時,該線程就進入就緒狀態。當另一個線程給就緒線程發送信號時,該線程重新切換到運行狀態。
?休眠狀態:由于一個線程的時間片用完了,該線程從運行狀態進入休眠狀態。當時間間隔到期或者等待時間發生了,該狀態的線程切換到運行狀態。
?終止狀態:一個運行狀態的線程完成任務或者其他終止條件發生時,該線程就切換到終止狀態。
?5.3線程和進程的區別:
?線程是進程的子集,一個進程可以有多個線程,每條線程并行執行不同的任務。
?不同的進程使用的內存空間不同,而所有的線程共享一片相同的內存空間
?每個線程讀都擁有單獨的棧內存來存儲本地數據
?5.4線程的幾種實現方式?啟動方式?區分方式?
?實現方式:1.通過繼承Thread類實現一個線程?
?繼承擴展性不強,因為Java只支持單繼承,如果一個類繼承了thread類就不能再繼承其他類了
? 2 實現Runnable接口
? 3.還可以實現callable接口
?啟動方式:啟動線程調用start方法,啟動之后再執行run方法
?區分方式:thread.setName(“線程名稱”),這是一種規范,在創建一個線程的完成后,都需要設置名稱
?5.5線程池
?線程池做的工作主要是控制運行的線程的數量,處理過程中將任務放入隊列,然后在線程創建后 啟動這些任務,如果線程數量超過了最大數量超出數量的線程排隊等候,等其它線程執行完畢, 再從隊列中取出任務來執行。他的主要特點為:線程復用;控制最大并發數;管理線程
?限制線程個數,以免線程過多導致系統運行緩慢或者崩潰
?線程池不需要每次使用時都去創建,節約了資源
?5.6多線程的優缺點
?優點:1.多線程技術使程序響應速度更快
?. 2.當前沒有進行處理的任務可以將處理器時間交給其他任務
? 3.占用大量處理時間的任務可以定期將處理器時間讓給其他任務
? 4.可以隨時停止任務
? 5.可以分別設置各個任務的優先級以及性能優化
?缺點:1.等待使用共享資源時造成程序的運行速度變慢
? 2.對線程進行管理需要額外的CPU開銷
? 3.可能出現線程死鎖的情況。即較長時間的等待或資源競爭以及死鎖等癥狀
?5.7start()方法和run()
?Start()方法:1.用start方法來啟動線程,真正實現了多線程運行,這時無需等待run方法體代碼執行完畢而繼續執行下面的代碼
? 2.通過調用thread類的start方法來啟動線程,這時線程處于就緒狀態,并沒有運行,需要得到CPU時間片后,就開始執行run方法
?Run()方法:run方法只是一個類的普通方法而已,如果直接調用run方法,程序中依然只有主線程這一個線程,其程序執行路徑還是只有一條。
?總結:1)調用start方法可啟動線程
? 2)而run方法只是thread的一個普通方法調用,還是在主線程里執行
? 3)把需要并行處理的代碼放在run方法中,start方法啟動線程將自動調用run方法,這是JVM的內存機制規定的
? 4)run方法必須是public的訪問權限,返回值類型是void
?5.8Runnable接口和Callable接口的相同點和不同點
?相同點:1.兩者都是接口 2.兩者都可以應用于Executors
?不同點:1.Callable要實現call方法,runnable要實現run方法
? 2.call方法可以返回值,可以拋出異常,run方法不能
?5.9怎么喚醒一個阻塞線程
?如果線程是調用wait,sleep或者join方法而導致的線程阻塞,可以中斷線程,并且通過拋出InterrupteException來喚醒它;如果線程遇到了IO阻塞,無能為力,因為IO是操作系統實現的,Java代碼沒有辦法直接接觸到操作系統
?5.10線程安全,vector是一個線程安全類嗎
?如果你的代碼所在的進程中有多個線程同時運行,而這些線程可能會 同時運行這段代碼,如果每次運行結果和單線程運行的結果是一樣的,而且其他的變量值也和預期是一樣的,就是線程安全。
?Vector是用同步方法來實現線程安全的,而ArrayList是線程不安全的
?5.11生產者和消費者模型的作用是什么
?1)通過平衡生產者的生產能力和消費者的消費能力來提示整個系統的運行效率。(這是生產者消費者模型最重要的作用)
?2)觸耦,這是生產者消費者附帶的作用,觸耦意味著生產者和消費者的聯系少,聯系越少越可以獨自發展而不需要收到相互的制約
?5.12同步和異步
?實現方式:同步代碼塊,同步函數,lock鎖
?同步和異步之間的區別
? 異步:當一個線程訪問資源時,值需要獲取時間片即可,如果時間片消耗完,任務未完成 暫時將任務保存,當下一次獲取時間片繼續執行。 當多個線程訪問資源時,每個線程只需要關注時間片即可
? 同步:當多個線程訪問共享資源時,獲取時間片的同時 , 還需要獲取鎖,而獲取鎖的線程如果任務未完成,其他線程都不能訪問該資源。因為鎖只有一個
?區別:線程同步(安全):數據安全
? 線程異步:執行效率高
?同步和異步有何異同:如果數據將在線程間共享。例如正在寫的數據以后可能被另一個線程讀到,或者在讀的數據可能已經被另一個線程寫到,那么這些數據就是共享數據,必須進行同步存取。當應用程序在對象上調用了一個需要花費很長時間來執行的方法,并且不希望讓程序等待方法返回時,就應該使用異步編程,在很多情況下采用異步往往效率跟高
?5.13線程的死亡
?線程會以下面三種方式結束,結束后就是死亡狀態。?
?正常結束
? 1. run()或call()方法執行完成,線程正常結束。?
?異常結束
? 2. 線程拋出一個未捕獲的Exception或Error。 調用 stop?
?3. 直接調用該線程的stop()方法來結束該線程—該方法通常容易導致死鎖,不推薦使用。
?5.14什么是死鎖
?兩個線程或者兩個以上線程都在等待對方執行完畢才繼續往下執行的時候就發生了死鎖,結果就是這些程序都陷入了無限的等待中
?1. 樂觀鎖 樂觀鎖是一種樂觀思想,即認為讀多寫少,遇到并發寫的可能性低,每次去拿數據的時候都認為 別人不會修改,所以不會上鎖,但是在更新的時候會判斷一下在此期間別人有沒有去更新這個數 據,采取在寫時先讀出當前版本號,然后加鎖操作(比較跟上一次的版本號,如果一樣則更新), 如果失敗則要重復讀-比較-寫的操作。?
?java 中的樂觀鎖基本都是通過 CAS 操作實現的,CAS 是一種更新的原子操作,比較當前值跟傳入 值是否一樣,一樣則更新,否則失敗。?
?2. 悲觀鎖 悲觀鎖是就是悲觀思想,即認為寫多,遇到并發寫的可能性高,每次去拿數據的時候都認為別人 會修改,所以每次在讀寫數據的時候都會上鎖,這樣別人想讀寫這個數據就會block直到拿到鎖。 java中的悲觀鎖就是Synchronized,AQS框架下的鎖則是先嘗試cas樂觀鎖去獲取鎖,獲取不到, 才會轉換為悲觀鎖,如RetreenLock。?
?3. 自旋鎖 自旋鎖原理非常簡單,如果持有鎖的線程能在很短時間內釋放鎖資源,那么那些等待競爭鎖 的線程就不需要做內核態和用戶態之間的切換進入阻塞掛起狀態,它們只需要等一等(自旋), 等持有鎖的線程釋放鎖后即可立即獲取鎖,這樣就避免用戶線程和內核的切換的消耗。
?Synchronized 同步鎖
?synchronized 它可以把任意一個非 NULL 的對象當作鎖。他屬于獨占式的悲觀鎖,同時屬于可重 入鎖。?
?Synchronized
?作用范圍
? 1. 作用于方法時,鎖住的是對象的實例(this); 2. 當作用于靜態方法時,鎖住的是Class實例,又因為Class的相關數據存儲在永久帶PermGen (jdk1.8 則是 metaspace),永久帶是全局共享的,因此靜態方法鎖相當于類的一個全局鎖, 會鎖所有調用該方法的線程; 3. synchronized 作用于一個對象實例時,鎖住的是所有以該對象為鎖的代碼塊。它有多個隊列, 當多個線程一起訪問某個對象監視器的時候,對象監視器會將這些線程存儲在不同的容器中。?
?Synchronized
?核心 組件
? 1) Wait Set:哪些調用wait方法被阻塞的線程被放置在這里; 2) Contention List:競爭隊列,所有請求鎖的線程首先被放在這個競爭隊列中; 3) Entry List:Contention List中那些有資格成為候選資源的線程被移動到Entry List中; 4) OnDeck:任意時刻,最多只有一個線程正在競爭鎖資源,該線程被成為OnDeck; 5) Owner:當前已經獲取到所資源的線程被稱為Owner; 6) !Owner:當前釋放鎖的線程。
?5.15wait與sleep,notify的區別
?1)Sleep方法來自thread類,不會釋放對象鎖,睡眠后不會讓出資源類
?2)wait方法來自object,會釋放對象鎖,可以讓其他線程占用CPU
?4)notify喚醒一個正在運行的線程處于睡眠狀態,注意在調用此方法的時候,并不能確切的喚醒某一個等待狀態的線程,而是由JVM確定喚醒哪個線程,而且不是按優先級
?5.16 四種線程池
?Java 里面線程池的頂級接口是 Executor,但是嚴格意義上講 Executor 并不是一個線程池,而 只是一個執行線程的工具。真正的線程池接口是ExecutorService。
?1. newCachedThreadPool? 創建一個可根據需要創建新線程的線程池,但是在以前構造的線程可用時將重用它們。對于執行 很多短期異步任務的程序而言,這些線程池通常可提高程序性能。調用 execute 將重用以前構造 的線程(如果線程可用)。如果現有線程沒有可用的,則創建一個新線程并添加到池中。終止并 從緩存中移除那些已有 60 秒鐘未被使用的線程。因此,長時間保持空閑的線程池不會使用任何資 源。?
?2. newFixedThreadPool? 創建一個可重用固定線程數的線程池,以共享的無界隊列方式來運行這些線程。在任意點,在大 多數 nThreads 線程會處于處理任務的活動狀態。如果在所有線程處于活動狀態時提交附加任務, 則在有可用線程之前,附加任務將在隊列中等待。如果在關閉前的執行期間由于失敗而導致任何 線程終止,那么一個新線程將代替它執行后續的任務(如果需要)。在某個線程被顯式地關閉之 前,池中的線程將一直存在。
?3. newScheduledThreadPool? 創建一個線程池,它可安排在給定延遲后運行命令或者定期地執行。
?4. newSingleThreadExecutor Executors.newSingleThreadExecutor()返回一個線程池(這個線程池只有一個線程),這個線程 池可以在線程死后(或發生異常時)重新啟動一個線程來替代原來的線程繼續執行下去!?
?5.17終止線程 4 種方式
?1. 正常運行結束?
? 程序運行結束,線程自動結束。?
?2. 使用退出標志退出線程?
?一般 run()方法執行完,線程就會正常結束,然而,常常有些線程是伺服線程。它們需要長時間的 運行,只有在外部某些條件滿足的情況下,才能關閉這些線程。使用一個變量來控制循環,例如: 最直接的方法就是設一個boolean類型的標志,并通過設置這個標志為true或false來控制while 循環是否退出
?3. Interrupt 方法結束線程
?4. stop 方法終止線程(線程不安全)
?不安全主要是: thread.stop()調用之后,創建子線程的線程就會拋出 ThreadDeatherror 的錯誤,并且會釋放子 線程所持有的所有鎖。一般任何進行加鎖的代碼塊,都是為了保護數據的一致性,如果在調用 thread.stop()后導致了該線程所持有的所有鎖的突然釋放(不可控制),那么被保護數據就有可能呈 現不一致性,其他線程在使用這些被破壞的數據時,有可能導致一些很奇怪的應用程序錯誤。因 此,并不推薦使用stop方法來終止線程
?http://6.IO流
?6.1對IO流的理解
?IO流主要用來處理輸入輸出問題,常用的IO流有InputStream和OutputStream,Reader,Writer等
?6.2JavaIO里常見的類,字節流,字符流,接口,實現類,方法阻塞
?輸入流就是從外部文件輸入到內存,輸出流就是從內存輸出到文件
?IO流主要分為字符流和字節流
?字符流中有抽象類:InputStream和OutputStream,子類:FileInputStream,FileOutputStream,BufferedOutputStream等其中BufferedReader和Writer等都實現了Closeable,Flushable,Appendable這些接口。程序中的輸入流輸出流都是以流的形式保存的,流中保存的實際上都是字節文件。
?Java中的阻塞式方法都是指在程序調用該方法時,必須等到輸入數據可用或者監測到輸入結束或者拋出異常,否則程序會一直停留在該語句上,不會執行下面的語句,比如read方法和readLine方法
?6.3字符流和字節流的區別
?底層設備永遠只接受字節數據,有時候要寫字符串到底層設備,需要將字符串轉換成字節再進行寫入,字符流是字節流的包裝,字符流則是直接接受字符串,它內部將串換成字節,再寫入底層設備
?6.4實現一個拷貝文件的工具類使用字節流還是字符流?
?我們拷貝的文件不確定是只包含字符流,有可能有字節流(圖片,聲音等),為考慮到通用性,要使用字節流
?6.5NIO
?NIO主要有三大核心部分:Channel(通道),Buffer(緩沖區), Selector。傳統IO 基于字節流和字 符流進行操作,而NIO基于 Channel和Buffer(緩沖區)進行操作,數據總是從通道讀取到緩沖區 中,或者從緩沖區寫入到通道中。Selector(選擇區)用于監聽多個通道的事件(比如:連接打開, 數據到達)。因此,單個線程可以監聽多個數據通道。
?NIO和傳統IO 之間第一個最大的區別是,IO是面向流的,NIO是面向緩沖區的。
?1. NIO的緩沖區?
?Java IO面向流意味著每次從流中讀一個或多個字節,直至讀取所有字節,它們沒有被緩存在任何 地方。此外,它不能前后移動流中的數據。如果需要前后移動從流中讀取的數據,需要先將它緩 存到一個緩沖區。NIO的緩沖導向方法不同。數據讀取到一個它稍后處理的緩沖區,需要時可在 緩沖區中前后移動。這就增加了處理過程中的靈活性。但是,還需要檢查是否該緩沖區中包含所 有您需要處理的數據。而且,需確保當更多的數據讀入緩沖區時,不要覆蓋緩沖區里尚未處理的 數據。?
?2. NIO的非阻塞?
?IO的各種流是阻塞的。這意味著,當一個線程調用read() 或 write()時,該線程被阻塞,直到有 一些數據被讀取,或數據完全寫入。該線程在此期間不能再干任何事情了。 NIO的非阻塞模式, 使一個線程從某通道發送請求讀取數據,但是它僅能得到目前可用的數據,如果目前沒有數據可 用時,就什么都不會獲取。而不是保持線程阻塞,所以直至數據變的可以讀取之前,該線程可以 繼續做其他的事情。 非阻塞寫也是如此。一個線程請求寫入一些數據到某通道,但不需要等待它 完全寫入,這個線程同時可以去做別的事情。 線程通常將非阻塞IO的空閑時間用于在其它通道上 執行IO操作,所以一個單獨的線程現在可以管理多個輸入和輸出通道(channel)。
?6.6字節流進行大量的從硬盤讀取,要用哪個流
?BufferedInputStream使用緩沖流能夠減少對硬盤的傷害
?6.7可序列化,如何實現可序列化
?把一個對象寫入數據源或者從一個數據源讀出來,使用可序列化,需要實現Serizlizable接口
?6.8所有的流可以分為幾大類,名字各代表什么
?字節輸入流InputStream
?字節輸出流:OutputStream
?字符輸入流:Reader
?字符輸出流:Wreter
?所有流都是這四個流的子類
?6.9流使用什么方法關閉,在哪里關閉比較好,處理流是怎么關閉的,多個流互相調用傳入怎么關閉
?流一旦打開必須關閉,使用close方法,放入finally語句塊中
?調用處理流就關閉處理流
?多個流互相調用只關閉最外層的流
?6.10對象序列化,反序列化,實現對象序列化需要做哪些工作
?對象序列化:將對象以二進制的形式保存在硬盤上
?反序列化:將二進制的文件轉換為對象讀取
?實現Serializable接口
?6.11節點流,處理流的用處,處理流的創建有什么特征
?節點流:直接與數據源相連,用于輸入或輸出
?處理流:在節點流的基礎上對之進行加工,進行一些功能的擴展
?處理流的構造器必須要傳入節點流的子類
?6.12 阻塞 IO 模型
?最傳統的一種IO模型,即在讀寫數據過程中會發生阻塞現象。當用戶線程發出IO 請求之后,內 核會去查看數據是否就緒,如果沒有就緒就會等待數據就緒,而用戶線程就會處于阻塞狀態,用 戶線程交出CPU。當數據就緒之后,內核會將數據拷貝到用戶線程,并返回結果給用戶線程,用戶線程才解除block狀態。典型的阻塞IO模型的例子為:data = socket.read();如果數據沒有就 緒,就會一直阻塞在read方法。
?6.13非阻塞 IO 模型
?當用戶線程發起一個read操作后,并不需要等待,而是馬上就得到了一個結果。如果結果是一個 error時,它就知道數據還沒有準備好,于是它可以再次發送read操作。一旦內核中的數據準備 好了,并且又再次收到了用戶線程的請求,那么它馬上就將數據拷貝到了用戶線程,然后返回。 所以事實上,在非阻塞IO模型中,用戶線程需要不斷地詢問內核數據是否就緒,也就說非阻塞IO 不會交出CPU,而會一直占用CPU
?6.14多路復用 IO 模型
?多路復用IO模型是目前使用得比較多的模型。Java NIO實際上就是多路復用IO。在多路復用IO 模型中,會有一個線程不斷去輪詢多個socket的狀態,只有當socket真正有讀寫事件時,才真 正調用實際的IO讀寫操作。因為在多路復用IO模型中,只需要使用一個線程就可以管理多個 socket,系統不需要建立新的進程或者線程,也不必維護這些線程和進程,并且只有在真正有 socket讀寫事件進行時,才會使用IO資源,所以它大大減少了資源占用。在Java NIO中,是通 過selector.select()去查詢每個通道是否有到達事件,如果沒有事件,則一直阻塞在那里,因此這 種方式會導致用戶線程的阻塞。多路復用IO 模式,通過一個線程就可以管理多個socket,只有當 socket真正有讀寫事件發生才會占用資源來進行實際的讀寫操作。因此,多路復用IO 比較適合連 接數比較多的情況。
?6.15信號驅動 IO 模型
?在信號驅動IO 模型中,當用戶線程發起一個IO請求操作,會給對應的socket注冊一個信號函 數,然后用戶線程會繼續執行,當內核數據就緒時會發送一個信號給用戶線程,用戶線程接收到 信號之后,便在信號函數中調用IO 讀寫操作來進行實際的IO 請求操作。
?6.16異步 IO 模型
?異步IO模型才是最理想的IO 模型,在異步IO 模型中,當用戶線程發起read操作之后,立刻就 可以開始去做其它的事。而另一方面,從內核的角度,當它受到一個asynchronous read之后, 它會立刻返回,說明read請求已經成功發起了,因此不會對用戶線程產生任何block。然后,內 核會等待數據準備完成,然后將數據拷貝到用戶線程,當這一切都完成之后,內核會給用戶線程 發送一個信號,告訴它read操作完成了。也就說用戶線程完全不需要實際的整個IO操作是如何 進行的,只需要先發起一個請求,當接收內核返回的成功信號時表示IO操作已經完成,可以直接 去使用數據了。
?7.異常
?7.1error和exception有什么區別
?Error表示系統級錯誤,是Java運行環境內部錯誤或者硬件問題,不能指望程序來處理這樣的問題,除了退出運行外別無選擇,他是JVM拋出的
?Exception表示程序需要捕捉,需要處理的異常,是由程序設計的不完善而出現的問題,程序必須處理的問題
?7.2運行時異常和一般異常有何不同
?Java提供了兩類主要異常:runtimeException和checkedException
?運行時異常:我們一般不處理,當出現這類異常時程序會由JVM接管,出現運行異常時,程序會將異常一直向上拋,一直拋到處理代碼
?一般異常:主要是指IO異常,SQL異常,對于這類異常,JVM要求我們必須進行cathc處理
?7.3Java異常處理機制的原理
?通過面向對象的方式對異常進行處理,Java把異常按照不同的類型進行分類,并提供了良好的接口,在Java中,每個異常都是一個對象,他都是Throwable,或其子類的實例,當一個方法出現異常后就會拋出一個異常對象,該對象包含異常信息,調用這個對象的方法可以捕獲到這個異常并對異常進行處理
?Java的異常處理是通過5個關鍵詞來實現的:try catch,throw,throws finally
?一般情況下是用try來執行一段程序,如果出現異常,系統會拋出,我們可以通過它的類型來捕獲它,或最后由缺省處理器來處理它
?Try:用來指定一塊預防所有異常的程序
?Catch:緊跟try后面,用來捕獲異常
?Throw:用來明確的拋出一個異常
?Throws:用來標明一個成員函數可能拋出的各種異常
?Finally:確保一段代碼無論發生什么異常都會被執行的一段代碼
?7.4項目中是怎樣對異常進行處理的
?1)盡量避免出現runtimeException,例如對于可能出現空指針的代碼,帶使用對象之前一定要判斷一下該對象是否為空,必要的時候對runtimeException也進行try catch 處理
?2)進行try catch處理的時候要在catch代碼塊中對異常信息進行記錄,通過調用異常類的相關方法獲取到異常的相關信息,返回帶web端,例如,以前做的一個項目,程序遇到異常頁面會顯示一個突破告訴用戶哪些操作導致程序出現了什么異常,同時突破上有一個按鈕用來點擊展示異常的詳細信息給程序員看
?7.5final,finally,finalize的區別
?Final:用于聲明變量,方法和類,分別表示變量值不可變,方法不可覆蓋,類不可以繼承
?Finally:是異常處理的一個關鍵字,表示finally里面的代碼一定要執行
?Finalize:是object類的一個方法,在垃圾回收的時候會調用被回收對象的此方法
?8.單例模式
?單例模式保證了對象唯一。分為懶漢式(在類加載的時不初始化)和餓漢式(在類加載時就完成了初始化,所有類加載比較慢,但獲取對象的速度快)兩種
?8.1單例模式實現步驟
?:私有化構造函數,創建一個靜態的私有對象,提供公共的訪問方法。
?8.2單例模式的特點
?1)某個類只能有一個實例
?2)必須自制件創建這個實例
?3)必須自行向整個系統提供這個實例
?應用情況:對于多個對象使用同一個配置信息時,就需要保證該對象的唯一性
?8.3如何保證對象的唯一性
?1)不允許其他程序用new創建該類對象
?2)在該類創建一個本類實例
?3)對外提供一個方法讓其他程序可以獲取該對象
?9.GC
?9.1GC是什么,為什么要有GC
?GC是垃圾收集的意思,負責清除對象并釋放內存。Java提供的GC功能可自動檢測對象是否超過作用域從而達到自動回收內存的目的,從而防止內存泄漏
?9.2GC的原理
?對于GC來說,當程序員創建對象時,GC就開始監控這個對象的地址,大小以及使用情況。通常GC采用有向圖的方式記錄和管理員中的所有對象。通過這種方式確定哪些對象是“可達的”,哪些是不可達的。當GC確定一些對象為不可達時,GC就有責任回收這些內存空間。程序員可以手動執行system。GC,通知GC運行,但是Java語言規范并不保證GC一定會執行
?9.3如何確定垃圾
?1.引用計數法 在 Java 中,引用和對象是有關聯的。如果要操作對象則必須用引用進行。因此,很顯然一個簡單 的辦法是通過引用計數來判斷一個對象是否可以回收。簡單說,即一個對象如果沒有任何與之關 聯的引用,即他們的引用計數都不為 0,則說明對象不太可能再被用到,那么這個對象就是可回收 對象。?
?2.可達性分析 為了解決引用計數法的循環引用問題,Java 使用了可達性分析的方法。通過一系列的“GC roots” 對象作為起點搜索。如果在“GC roots”和一個對象之間沒有可達路徑,則稱該對象是不可達的。要注意的是,不可達對象不等價于可回收對象,不可達對象變為可回收對象至少要經過兩次標記 過程。兩次標記后仍然是可回收對象,則將面臨回收。
?3. 標記清除算法(Mark-Sweep)?
?最基礎的垃圾回收算法,分為兩個階段,標注和清除。標記階段標記出所有需要回收的對象,清 除階段回收被標記的對象所占用的空間。如圖
?4.復制算法(copying)?
?為了解決Mark-Sweep算法內存碎片化的缺陷而被提出的算法。按內存容量將內存劃分為等大小 的兩塊。每次只使用其中一塊,當這一塊內存滿后將尚存活的對象復制到另一塊上去,把已使用 的內存清掉
?二.JavaWeb
?1.Ajax
?1.1什么是ajax
?Ajax是異步的JavaScript和xml
?原理:通過XmlHttpRequest對象來向服務器發送異步請求,從服務器獲得數據,然后用JavaScript來操作DOM而更像界面。最關鍵的異步就是從服務器獲得請求數據
?XmlHttpRequest是ajax的核心機制,它是在IE5中首先引進的,是一種支持異步請求的技術。就是JavaScript可以及時向服務器提出請求和處理響應,而不阻塞用戶,達到局部刷新的效果
?XMLHttpRequest:是一種支持異步請求,可以使用JavaScript向服務器提出請求并處理響應。而不阻塞用戶,通過這個對象,開發人員可以在頁面加載以后進行頁面的局部更新
?1.2ajax的幾種請求方式和優缺點,POST,GET
?常用的post,get,delete。不常用的copy,head,link等
?1) Post比get安全(因為post參數在請求體中,get參數在url上)
?2) Get傳輸速率比post快,根據傳參決定(因為post通過請求體傳參,后臺通過數據流接收,速度稍微慢點。而get通過url傳參可以直接獲取)
?3) Post傳輸文件理論上沒有限制,get傳輸文件大概在7-8K 左右 IE4K左右
?4) Get獲取數據 post上傳數據
?1.3ajax應用和傳統web應用有什么不同
?1)傳統的web前端與后端的交互中,瀏覽器直接訪問tomcat的servlet來獲取數據。Servlet通過轉發把數據 給瀏覽器
?2)當我們使用ajax之后,瀏覽器是先把請求發送到XMLHttpRequest異步對象之中,異步對象對請求進行封裝,然后再發送給服務器服務器并不是以轉發的方式響應,而是以流的方式把數據返回給瀏覽器
?3)XMLHttpRequest異步對象會不停的監聽服務器狀態的編號,得到服務器返回的數據,就寫到瀏覽器上
?1.4ajax的實現流程
?1)創建XMLHttpRequest對象
?2)創建一個新的HTTP請求,并指導該HTTP請求的方法,URL及驗證信息
?3)設置響應HTTP請求狀態變化的函數
?4)發送HTTP請求
?5)獲取異步調用返回的數據
?6)使用JavaScript和DOM實現局部刷新
?1.4jQuery的ajax和原生JS實現的ajax有什么關系
?jQuery中的ajax也是通過原生的JS封裝的,封裝完成后讓我們使用起來更加便利。不用考慮底層實現和兼容性處理
?如果采用原生JS實現ajax是非常麻煩的,并且每次都是一樣。如果我們不使用jQuery也要封裝ajax對象的方法和屬性
?2. jQuery
?2.1什么是jQuery
?是一個JavaScript庫,功能包括HTML元素選取和操作,CSS操作,HTML事件函數等,提供了大量插件
?2.2jQuery選擇器
?1、基本選擇器:直接根據id、css類名、元素名返回匹配的dom元素。
?2、層次選擇器:也叫做路徑選擇器,可以根據路徑層次來選擇相應的DOM元素。
?3、過濾選擇器:在前面的基礎上過濾相關條件,得到匹配的dom元素。
?2.1js和jQuery的關系
? jQuery是一個JS框架,封裝了JS的屬性和方法,并且增強了JS的功能
?使用原生JS是要處理很多兼容性問題,由于jQuery封裝了底層,就不用處理這些問題了
?原生的JS的DOM和事件綁定等操作麻煩
?3.轉發(forward)和重定向(redirect)的區別
?Forward是容器中控制權的轉向,是服務器請求資源,服務器直接訪問目標地址的URL,把那個URL的響應內容讀取過來,然后把這些內容在發給瀏覽器,瀏覽器根部不知道服務器發送的內容是從哪兒來的,所以它的地址欄還是原來的地址
?Redirect就是服務器端根據邏輯,發送一個狀態碼,告訴瀏覽器重新去請求那個地址,因此瀏覽器的地址欄中可以看到跳轉后的鏈接地址,很明顯redirect無法訪問到服務器保護起來資源,但是可以從一個網站重定向到其他網站
?4.轉發以及如何實現轉發
?轉發是一個 Web 組件(Servlet/JSP)將未完成的處理通過容器轉交給另外一個 Web 組件
?繼續完成.?
? 可以按照以下三個步驟來實現轉發:?
? 1.綁定數據到 request 對象,代碼如下:?
?request.setAttribute(String name,Object obj);?
? 2.獲得轉發器,代碼如下:?
?RequestDispatcher rd = request.getRequestDispatcher(String uri);?
? 3.轉發,代碼如下:?
?rd.forward(request,response);
?4. Session和cookie的區別
?兩者都是會話跟蹤技術
?Session:通過服務端記錄信息確定用戶身份,但是session的實現依賴于cookie,session把數據放在服務器上,登錄信息用session
?Cookie:通過客戶端記錄信息確定用戶身份,數據存放在客戶的瀏覽器上,不是很安全,單個保存的數據不能超過4K,購物車最好用cookie
?5. Servlet的生命周期
?servlet有良好的生存期的定義,包括加載和實例化、初始化、處理請求以及服務結束。這個生存期由javax.servlet.Servlet接口的init,service和destroy方法表達。
?Web容器加載servlet,生命周期開始,通過調用servlet的init方法進行servlet的初始化,通過調用service方法實現,根據不同調用不同的doget方法。結束服務,web容器調用servlet的destory方法
?6. web.xml文件可以配置哪些內容
?監聽器,過濾器,servlet相關參數,會話超時時間,安全驗證,錯誤頁面等
?7. doGet和doPost
?調用 :
?默認情況是調用doget方法,JSP頁面中的form表單的method屬性設置為post的時候,調用dopost,為get的時候調用doGet
?區別:
?1) get請求提交的數據會在地址欄顯示出來,而post不會
?2) 傳輸數據的大小:get請求由于瀏覽器對地址長度的限制導致傳輸的數據有限制,post不會
?3) 安全性:post比get安全性高,因為數據會在地址中呈現,可以通過歷史記錄找到密碼等關鍵信息
?7.JSP的九大內置對象和作用
?1)request:負責得到客戶端請求的信息
?2)response:負責向客戶端 發出響應
?3)session:負責保存同一個客戶端一次會話過程中的一些信息
?4)out:負責管理客戶端的輸出
?5)application:表示整個應用環境的信息
?6)config:表示servletConfig
?7)exception:表示頁面中發生的異常,可以通過它獲得頁面異常的信息
?8)pageContext:表示這個JSP頁面的上下文
?9)page:表示當前JSP頁面本身
?8.詳細描述MVC
?基于Java的web應用系統采用MVC設計模型,即用Model(模型)、View(視圖)和Controller(控制) 分離設計,這是目前web應用服務系統的主流設置方向
?Model:處理業務邏輯的模塊
?View:負責頁面顯示,顯示model的處理結果給用戶,主要實現數據到頁面的轉換過程
?Controller:負責每個請求的分發,把form數據傳遞給model進行處理,完成后把處理結果返回給相應的view顯示給用戶
?9.MVC的實現技術
?通過Model-View-Controlle這種設計模型把應用邏輯,處理過程和顯示邏輯分成不同的組件來實現,這些組件可以交互和重用r
?10.JSP和servlet的區別和聯系
?JSP是servlet的擴展,本質上是servlet的簡易方式,更強調應用的外表表達,翻譯后是類servlet
?Servlet和JSP最主要的不同在于,servlet的應用邏輯在Java文件中,并且完全從表示層的HTML里分離開,而JSP的情況是Java和HTML可以組合成一股擴展名為.jsp的文件。
?JSP偏重于視圖
?Servlet偏重于業務邏輯
?11.頁面間對象傳遞的方法
?Request,session,application,cookie
?12.JavaScript三種創建對象的方式
?1.創建對象的實例:使用 Object 對象,并封裝屬性和方法;?
? 2.創建對象的模板:定義構造函數,創建自定義對象并封裝屬性和方法;?
? 3.JSON:使用 JSON 的語法創建
?13Servlet 是否線程安全的,如何解決?
?Servlet 存在線程安全問題.容器收到請求之后,會啟動一個線程來進行相應的處
?理.?
? 默認情況下,容器只會為某個 Servlet 創建一個實例,如果同時有多個請求同時訪問某
?個 Servlet 則肯定會有多個線程訪問同一個 Servlet 實例.如果這些線程要修改 Servlet 實
?例的某個屬性,就有可能發生線程安全問題.?
? 可以使用 synchronized 對代碼加鎖來解決 Servlet 的安全問題
?14什么是監聽器
?Servlet 規范中定義的一種特殊的組件,用來監聽 Servlet 容器產生的事件并進行相應
?的處理.
?15 JSP 的四種范圍
?JSP 的四種范圍如下:?
? 1.page 是代表與一個頁面相關的對象和屬性.一個頁面由一個編譯好的 Java servlet
?類表示.這既包括 servlet 又包括被譯成 servlet 的 JSP 頁面;?
? 2.request 是代表與 Web 客戶機發出的一個請求相關的對象和屬性.一個請求可能跨越
?多個頁面,涉及多個 Web 組件;?
? 3.session 是代表與用于某個 Web 客戶機的一個用戶體驗相關的對象和屬性.一個 Web
?會話可以也經常會跨越多個客戶機請求;?
? 4.application是代表與整個Web應用程序相關的對象和屬性.這實質上是跨越整個Web
?應用程序,包括多個頁面,請求以及會話的一個全局作用域.?
?16四大域對象
?HttpSession:
?1) 使用:調用request.getSession方法
?2) 生命周期:在第一次調用requets.getSession方法時,服務器會檢查是否有對應的session存在,如果沒有就在內存中創建一個session并分配一個ID返回。當一段時間內session沒有被使用(默認是30分鐘),則服務器會銷毀session。如果服務器被非正常關閉,沒有到期的session也會被跟著銷毀,如果調用invalidate()方法,可以立即銷毀session
?ServletRequest:
?1) 使用:調用request方法
?2) 在service方法調用前由服務器創建,傳入service方法。整個請求結束,request生命結束
?ServletContext:
?1)使用:request.getSession().getServletContext
?2)什么周期:當web應用被加載進容器時創建代表整個web應用的servletContext對象,存在于全局當中,當服務器關閉或web應用被移除時,生命周期結束
?PageContext:
?當jsp請求時開始,響應結束后銷毀
?三.數據庫
?關鍵字:
?1)連接查詢:內連接,外連接,自然連接,交叉連接
? 內連接:基本語法:坐標【inner】join右表on左表.字段 = 右表.字段
? 從左表中取出每一條記錄,去右表中所有的記錄進行匹配
? 外連接:左邊left/right join 右表 on 左表.字段 = 右表.字段
? Left join:左外連接,以左表為主表
? Right join:右外連接,以右表為主表
?2)索引:索引(Index)是幫助 MySQL 高效獲取數據的數據結構。常見的查詢算法,順序查找,二分查找,二 叉排序樹查找,哈希散列法,分塊查找,平衡多路搜索樹B樹?
?常見索引原則有
?1. 選擇唯一性索引
? 唯一性索引的值是唯一的,可以更快速的通過該索引來確定某條記錄。?
?2. 為經常需要排序、分組和聯合操作的字段建立索引 :
?3 .為常作為查詢條件的字段建立 索引 。
?4 .限制索引的數目:
? 越多的索引,會使更新表變得很浪費時間。?
?盡量使用數據量少的索引
? 6. 如果索引的值很長,那么查詢的速度會受到影響。?
?盡量使用前綴來索引
? 7. 如果索引字段的值很長,最好使用值的前綴來索引。?
? 8.刪除不再使用或者很少使用的索引
?9. 最左前綴匹配原則,非常重要的原則。
?10 . 盡量選擇區分度高的列作為索引
? 區分度的公式是表示字段不重復的比例?
?11 . 索引列不能參與計算,保持列“干凈”:帶函數的查詢不參與索引。?
?12 . 盡量的擴展索引,不要新建索引
?3)數據庫引擎:InnoDB:支持事務處理,支持外鍵,支持崩潰修復能力和并發控制。如果需要對事務的完整性要求比較高(比如銀行),要求實現并發控制(比如售票),那選擇 InnoDB 有很大的優勢。如果需要頻繁的更新、刪除操作的數據庫,也可以選擇 InnoDB,因為支持事務的提交(commit)和回滾(rollback)。
?MyISAM:插入數據快,空間和內存使用比較低。如果表主要是用于插入新記錄和讀出記錄,那么選擇 MyISAM 能實現處理高效率。如果應用的完整性、并發性要求比較低,也可以使用。
?MEMORY:所有的數據都在內存中,數據的處理速度快,但是安全性不高。如果需要很快的讀寫速度,對數據的安全性要求較低,可以選擇 MEMOEY。它對表的大小有要求,不能建立太大的表。所以,這類數據庫只使用在相對較小的數據庫表。
?4) 存儲過程:
?一組為了完成特定功能的 SQL 語句集,存儲在數據庫中,經過第一次編譯后再次調用不需要再次 編譯,用戶通過指定存儲過程的名字并給出參數(如果該存儲過程帶有參數)來執行它。存儲過 程是數據庫中的一個重要對象
?存儲過程優化思路:
? 1. 盡量利用一些sql語句來替代一些小循環,例如聚合函數,求平均函數等。查找語句盡量不要放在循環內。
?2. 中間結果存放于臨時表,加索引。?
?3. 少使用游標。
? 4. 事務越短越好。sqlserver 支持并發操作。如果事務過多過長,或者隔離級別過高,都會造成 并發操作的阻塞,死鎖。導致查詢極慢,cpu占用率極低。
? 5. 使用try-catch處理錯誤異常。?
?5)MySQL的默認連接數是100;
?3.1JDBC編程的步驟
?1)注冊驅動
?2)獲取連接對象connection
?3)創建statement對象
?4)運行SQL語句
?5)處理結果
?6)關閉鏈接釋放資源
?3.2事務,事務的ACID是什么,事務并發會產生什么問題
?事務就是被綁定在一起作為一個邏輯單元的SQL語句
?ACID表示事務:原子性,隔離性,一致性,持久性
?原子性:事務中的各項操作要么全做要么全部做,任何一項操作的失敗都會導致整個事務的失敗
?隔離性:并發執行的事務無法彼此看到對方的狀態
?一致性:事務結束后系統狀態是一致的
?持久性:事務完成后所做的改動都會被持久化,即使災難性的失敗,通過日志和同步備份都可以在故障發生后重建數據
?事務并發會產生:臟讀,幻讀,不可重復讀
?臟讀:A事務讀取B事務尚未提交的數據并在此基礎上操作,而B事務執行回滾,那么A讀取到的數據就是臟數據
?幻讀:事務A重新執行一個查詢,返回一系列符合查詢條件的行,發現其中插入了被事務B提交的行
?不可重復讀:事務A重新讀取前面讀取過的數據,發現該數據已經被另一個以提交的事務B修改過
?3.3事務的隔離級別
?1) READ UNCOMMITTED 幻讀,不可重復讀和臟讀都允許.?
? 2) READ COMMITTED 允許幻讀,不可重復讀,不允許臟讀?
? 3) REPEATABLE READ 允許幻讀,不允許不可重復讀和臟讀?
? 4) SERIALIZABLE 幻讀,不可重復讀和臟讀都不允許
?3.4分頁查詢
?MySQL是使用關鍵字limit來進行也的,offset,size表示從多少索引去多少位
? 語句select * from t_employee limit 20,20;
?Oracle分頁是使用三層嵌套的語句:SELECT * FROM( SELECT A.*,ROWNUM RN FROM(SELECT * FROM t_employee) A WHERE ROWNUM <=40 ) WHERE RN >= 21
?3.5數據庫優化
?SQL優化:
?1) 盡量避免使用select *?
?2) 只查詢一條子記錄時使用limit 1
?3) 使用連接查詢代替子查詢
?4) 盡量使用一些能通過索引查詢的關鍵字
?表結構優化:
?1) 盡量使用數字類型字段,提高比對效率
?2) 長度不變且查詢速率要求比較高的數據可用考慮使用char,否則使用varchar
?其他優化:
?1) 對查詢頻率高的字段適當建立索引,提高效率,根據表的用途適當選擇數據庫引擎,讀寫分離
?3.6數據庫的三范式
?第一范式的目標是確保每列的原子性:如果每列都是不可再分的最小數據單元(也稱為最小的原子 單元),則滿足第一范式(1NF)
?首先滿足第一范式,并且表中非主鍵列不存在對主鍵的部分依賴。 第二范式要求每個表只描述一 件事情。
?第三范式定義是,滿足第二范式,并且表中的列不存在對非主鍵列的傳遞依賴。除了主鍵訂單編 號外,顧客姓名依賴于非主鍵顧客編號。.
?3.7數據庫連接池
?1)限制數據庫的字數,不會導致由于數據庫連接過多而系統崩潰或者運行緩慢
?2)數據庫連接不需要每次都去創建或銷毀,節約了資源
?3)響應時間更快
?3.8觸發器
?觸發器就是一種特殊的存儲過程,主要是通過事件來觸發而被執行的。它可以強化約束,來維護數據的完整性和一致性,可以跟蹤數據庫內的操作從而不允許未經許可的更新和變化,可以聯機運算
?使用場景:比如校內網、開心網、Facebook,你發一個日志,自動通知好友,其實就是在增加日志時做一個后觸發,再向通知表中寫入條目。因為觸發器效率高。而UCH沒有用觸發器,效率和數據處理能力都很低。
?03.9索引的作用和優缺點
?索引就是一種特殊的查詢表,數據庫的搜索引擎可以利用它加速對數據的檢索,索引可以是唯一的,創建索引允許指定單個列或者是多個行。缺點是它減慢了數據錄入的速度,同時也增加了數據庫的尺寸大小
?3.10視圖和游標是什么
?視圖:是一種虛擬的表,具有和物理表相同的功能,可以對視圖進行增,該,查等操作,視圖通常是由一個表或者多個表的行或列的子集,對視圖的修改不影響基本表,它使我們獲取數據更容易
?游標:是對查詢出來的結果集作為一個單元來有效的處理,游標可以定在該單元中的特定行,從結果集的當前檢索一行或多行,可以對結果集當前行做修改,一般不使用游標,但是需要逐條處理數據時候,游標很重要
?3.11數據庫并發策略
?1. 樂觀鎖 樂觀鎖認為一個用戶讀數據的時候,別人不會去寫自己所讀的數據;悲觀鎖就剛好相反,覺得自 己讀數據庫的時候,別人可能剛好在寫自己剛讀的數據,其實就是持一種比較保守的態度;時間 戳就是不加鎖,通過時間戳來控制并發出現的問題。?
?2. 悲觀鎖 悲觀鎖就是在讀取數據的時候,為了不讓別人修改自己讀取的數據,就會先對自己讀取的數據加 鎖,只有自己把數據讀完了,才允許別人修改那部分數據,或者反過來說,就是自己修改某條數 據的時候,不允許別人讀取該數據,只有等自己的整個事務提交了,才釋放自己加上的鎖,才允 許其他用戶訪問那部分數據。
?3. 時間戳 時間戳就是在數據庫表中單獨加一列時間戳,比如“TimeStamp”,每次讀出來的時候,把該字 段也讀出來,當寫回去的時候,把該字段加1,提交之前 ,跟數據庫的該字段比較一次,如果比數 據庫的值大的話,就允許保存,否則不允許保存,這種處理方法雖然不使用數據庫系統提供的鎖 機制,但是這種方法可以大大提高數據庫處理的并發量,?
?以上悲觀鎖所說的加“鎖”,其實分為幾種鎖,分別是:排它鎖(寫鎖)和共享鎖(讀鎖)。
?3.12數據庫鎖
?1. 行級鎖 行級鎖是一種排他鎖,防止其他事務修改此行;在使用以下語句時,Oracle會自動應用行級鎖:?
?1. INSERT、UPDATE、DELETE、SELECT … FOR UPDATE [OF columns] [WAIT n | NOWAIT]; 2. SELECT … FOR UPDATE語句允許用戶一次鎖定多條記錄進行更新 3. 使用COMMIT或ROLLBACK語句釋放鎖。?
?2. 表級鎖 表示對當前操作的整張表加鎖,它實現簡單,資源消耗較少,被大部分 MySQL 引擎支持。最常使 用的 MYISAM 與 INNODB 都支持表級鎖定。表級鎖定分為表共享讀鎖(共享鎖)與表獨占寫鎖 (排他鎖)。?
?3. 頁級鎖 頁級鎖是 MySQL 中鎖定粒度介于行級鎖和表級鎖中間的一種鎖。表級鎖速度快,但沖突多,行級 沖突少,但速度慢。所以取了折中的頁級,一次鎖定相鄰的一組記錄。BDB支持頁級鎖
?四.框架
?1.spring
?1.1spring的理解
?IOC和DI的區別:
?IOC是控制反轉,指將對象的創建權,反轉到spring容器
?DI是依賴注入,指spring創建對象的過程中,將對象依賴屬性通過配置進行注入
?Spring是一個IOC和AOP容器框架,主要核心是:
?1) 控制反轉(IOC):Spring 通過一個配置文件描述 Bean 及 Bean 之間的依賴關系,利用 Java 語言的反射功能實例化 Bean 并建立 Bean 之間的依賴關系。 Spring 的 IoC 容器在完成這些底層工作的基礎上,還提供 了 Bean 實例緩存、生命周期管理、 Bean 實例代理、事件發布、資源裝載等高級服務。
?2) 依賴注入(DI):spring使用javaBean對象的set方法或者帶參數的構造方法,為創建所需對象時將屬性自動設置所需要的值的過程。
?3) 面向切面編程(AOP):在面向對象編程中(OOP),我們將事務縱向抽象成一個個對象。而在面向切面編程中,我們將一個個對象某些類似方法橫向抽象成一個切面,對這個切面進行一些如權限驗證,事務管理,記錄日志等公用操作處理
?在spring中,所有管理的對象都是Javabean對象,而在beanfactory和ApplicationContext就是spring框架的兩個IOC容器,現在一般使用ApplicationContext,其不包含beanfactory的作用,同時進行更多的擴展
?1.2spring Bean生命周期
?Spring的生命周期:在配置<bean>元素,通過init-method指定bean的初始化方法,通過desstroy-method指定bean銷毀方法
?Bean生命周期:
?1)spring容器從XML文件讀取bean的定義,并實例化bean
?2)spring根據bean的定義填充所有實例
?3)如果bean實現了BeanNameAware接口,spring傳遞bean的ID到setBeanName方法
?4)如果bean實現了BeanFactoryAware接口,spring傳遞beanfactory給setBeanFactory方法
?5)如果有任何與bean相關聯的BeanPostProcessors,spring會在postProcessesBeforeInitialization方法調用他們
?6)如果bean實現了InitializingBean了,調用它的afterPropertySet方法,如果bean聲明了初始化,調用初始化方法
?7)如果有BeanPostProcessors和bean關聯,這些bean的postProcessAfterInitialization方法將被調用
?8)如果bean實現了DisposableBean,它將調用destory方法注意:
?有兩個重要的 bean 生命周期方法,第一個是 setup() , 它是在容器加載 bean 的時候被調用。第二個方法是 teardown() 它是在容器卸載類的時候被調用。
?The bean 標簽有兩個重要的屬性 init-method 和 destroy-method。使用它們你可以自己定制初始化和注銷方法。它們也有相應的注解@PostConstruct 和@PreDestroy。
?1.3spring注解
?如下配置:
?
?
??
?
?Context:annotion-config標簽
?1)@Required:該注解應用于設方法
?2)@Autowried:該注解應用于有值設值方法,非設值方法,構造方法和變量
?3)Qualifier:該注解和@Autowired注解搭配使用,用于消除特點bean自動裝配的歧義
?1.4spring事務
?1)編程式事務管理:通過編程的方式管理事務,帶來更大的靈活性,但難維護
?2)聲明式事務管理:可以將業務代碼和事務管理分離,只需用注解和XML配置來管理事務
?事務配置示例:
?
?
??
?
?1.5spring事務的隔離級別
?1) READ UNCOMMITTED 幻讀,不可重復讀和臟讀都允許.?
? 2) READ COMMITTED 允許幻讀,不可重復讀,不允許臟讀?
? 3) REPEATABLE READ 允許幻讀,不允許不可重復讀和臟讀?
? 4) SERIALIZABLE 幻讀,不可重復讀和臟讀都不允許
?1.6BeanFactory接口和ApplicationContext接口的區別
?1)ApplocationContext接口繼承了BeanFactory,spring的核心工廠是BeanFactory,BeanFactory采用延時加載,第一個getBean時才會初始化Bean,ApplicationContext是會在加載配置文件時初始化Bean
?2)ApplicationContext是對BeanFactory的擴展,可以進行國際化處理,事務傳遞和Bean自動裝配以及各種不同應用層的Context實現,開發中基本都使用Application,web項目中使用WebApplictionContext,很少使用beanfactory
?1.7spring配置bean實例化的三種方式
?1)使用類構造器(默認無參數)
?<bean id="bean1" class="cn.itcast.spring.b_instance.Bean1"></bean>
?2) 使用靜態工廠(簡單工廠模式)
?//下面這段配置的含義:調用Bean2Factory的getBean2方法得到bean2
?<bean id="bean2" class="cn.itcast.spring.b_instance.Bean2Factory" factory-method="getBean2">
?</bean>
?3) 使用實例化工廠(工廠方法模式)
?//先創建工廠實例bean3Facory,再通過工廠實例創建目標bean實例
?<beanid="bean3Factory" class="cn.itcast.spring.b_instance.Bean3Factory"></bean>
?<bean id="bean3" factory-bean="bean3Factory" factory-method="getBean3"></bean>
?1.8bean注入的3種方式
?1)接口注入
?2)構造器注入:通過<constructor-arg>元素完成注入
?3)set注入:通過<property>元素完成注入
?1.9 Spring 依賴注入四種方式
?1.構造器注入
?(/*帶參數,方便利用構造器進行注入*/ public CatDaoImpl(String message){ this. message = message; } <bean id="CatDaoImpl" class="com.CatDaoImpl"> <constructor-arg value=" message "></constructor-arg> </bean>)
?2. setter方法 注入
?通過<property>元素完成注入
?3. 靜態工廠注入
?靜態工廠顧名思義,就是通過調用靜態工廠的方法來獲取自己需要的對象,為了讓 spring 管理所 有對象,我們不能直接通過"工程類.靜態方法()"來獲取對象,而是依然通過 spring 注入的形式獲 取
?4. 實例工廠
?實例工廠的意思是獲取對象實例的方法不是靜態的,所以你需要首先 new 工廠類,再調用普通的 實例方法
?2.0 5 種不同方式的自動裝配
?Spring裝配包括手動裝配和自動裝配,手動裝配是基于 xml裝配、構造方法、setter方法等?
?自動裝配有五種自動裝配的方式,可以用來指導Spring容器用自動裝配方式來進行依賴注入。?
?1. no:默認的方式是不進行自動裝配,通過顯式設置ref 屬性來進行裝配。
?2. byName:通過參數名 自動裝配,Spring容器在配置文件中發現bean的autowire屬性被設 置成byname,之后容器試圖匹配、裝配和該bean的屬性具有相同名字的bean。?
?3. byType:通過參數類型自動裝配,Spring 容器在配置文件中發現 bean 的 autowire 屬性被 設置成byType,之后容器試圖匹配、裝配和該bean的屬性具有相同類型的bean。如果有多 個bean符合條件,則拋出錯誤。?
?4. constructor:這個方式類似于 byType, 但是要提供給構造器參數,如果沒有確定的帶參數 的構造器參數類型,將會拋出異常。?
?5. autodetect:首先嘗試使用constructor來自動裝配,如果無法工作,則使用byType方式。
?2.1 Spring APO 原理
?AOP主要應用場景有
?1. Authentication 權限 2. Caching 緩存 3. Context passing 內容傳遞 4. Error handling 錯誤處理 5. Lazy loading 懶加載 6. Debugging 調試 7. logging, tracing, profiling and monitoring 記錄跟蹤 優化 校準 8. Performance optimization 性能優化 9. Persistence 持久化 10. Resource pooling 資源池 11. Synchronization 同步 12. Transactions 事務?
?2. AOP 核心概念 1、切面(aspect):類是對物體特征的抽象,切面就是對橫切關注點的抽象?
?2、橫切關注點:對哪些方法進行攔截,攔截后怎么處理,這些關注點稱之為橫切關注點。?
?3、連接點(joinpoint):被攔截到的點,因為 Spring 只支持方法類型的連接點,所以在 Spring 中連接點指的就是被攔截到的方法,實際上連接點還可以是字段或者構造器。?
?4、切入點(pointcut):對連接點進行攔截的定義?
?5、通知(advice):所謂通知指的就是指攔截到連接點之后要執行的代碼,通知分為前置、后置、 異常、最終、環繞通知五類。?
?6、目標對象:代理的目標對象?
?7、織入(weave):將切面應用到目標對象并導致代理對象創建的過程?
?8、引入(introduction):在不修改代碼的前提下,引入可以在運行期為類動態地添加一些方法 或字段
?AOP 兩種代理方式
?JDK動態 接口 代理
?1. JDK 動態代理主要涉及到 java.lang.reflect 包中的兩個類:Proxy 和 InvocationHandler。 InvocationHandler是一個接口,通過實現該接口定義橫切邏輯,并通過反射機制調用目標類 的代碼,動態將橫切邏輯和業務邏輯編制在一起。Proxy 利用 InvocationHandler 動態創建 一個符合某一接口的實例,生成目標類的代理對象。
?2. CGLib
?動態代理
?CGLib全稱為Code Generation Library,是一個強大的高性能,高質量的代碼生成類庫, 可以在運行期擴展 Java 類與實現 Java 接口,CGLib 封裝了 asm,可以再運行期動態生成新 的 class。和 JDK 動態代理相比較:JDK 創建代理有一個限制,就是只能為接口創建代理實例, 而對于沒有通過接口定義業務方法的類,則可以通過CGLib創建動態代理。?
?2.springMVC
?2.1springMVC的執行流程
?1)用戶發送請求到前端控制器
?2)前端控制器收到請求后調用處理器映射器
?3)處理器映射器找到具體的處理器,生成處理器對象及攔截器一起返回給給前端控制器
?4)前端控制器調用處理器適配器
?5)處理器適配器經過適配調用具體的處理器
?6)處理器執行完成返回ModelAndView對象
?7)處理器適配器將controller執行結果ModelAndView返回給前端控制器
?8)前端控制器將ModelAndView傳給視圖解析器
?9)視圖解析器解析后返回具體的view
?10)前端控制器根據view進行視圖渲染
?11)前端控制器響應用戶
?2.2springMVC的優點
?1)可以支持各種視圖技術,而不僅僅局限于JSP
?2)與spring框架集成(IOC容器,AOP等)
?3)清晰的角色分配:前端控制器,處理器映射器,處理器適配器,視圖解析器
?4)支持各種請求資源的映射策略
?2.3springMVC的主要組件
?1)前端控制器(不需要程序員開發)
?2)處理器映射器(不需要程序員開發)
?3)處理器適配器
?4)視圖解析器(不需要程序員開發)
?5)處理器(需要程序員開發)
?6)視圖(需要程序員開發JSP)
?2.4springMVC設定轉發和重定向
?1)轉發:在返回值前面加forward,例如:forward:user.do?name=method
?2)重定向:在返回值前面加redirect,例如:redirect:http://www.baidu.caom
?2.5springMVC和Struts對比
?機制:SpringMVC的入口是servlet,而Struts是filter
?性能:spring比Struts快一點。SpringMVC是基于方法的設計,Struts是基于類,
?參數傳遞:Struts是在接受參數的時候,可以用屬性來接受參數,參數是讓多個方法共享的
?設計思想:Struts更符合OOP的編程思想,spring比較嚴謹,在servlet上擴展
?2.6springMVC和ajax的相互調用
?1)加入Jackson.jar
?2)在配置文件中配置json的映射
?3)在接受ajax方法里面可以直接返回object,list等,但在方法前面要加數@ResponseBody注解
?2.7springMVC的post和get請求亂碼問題
?1)post:在web.xml中配置一個CharacterEncodingFilter過濾器,設置為utf-8
?2)get:修改tomcat配置文件添加編碼與工程編碼一致,或對參數重新進行編譯
?2.8SpringMVC的異常處理
?可以把異常拋給Spring,由Spring框架處理;我們只需要配置簡單的異常處理器,在異常處理器中添加視圖頁面即可
?2.9SpringMVC常用的注解
?1)@RequestMapping:用于處理請求URL映射的注解,可用在類和方法上。用在類上,則表示類中的所有響應請求的方法都是以該地址作為父路徑
?2)@RequestBody:接受http請求的json數據,將json轉換為Java數據
?3)@ResponseBody:將conreoller方法返回對象轉化為json對象響應給客戶
?2.10SpringMVC的控制器注解一般使用哪個
?一般用@Conntroller注解,表示在表現層,不能用別的注解代替
?2.11攔截請求中,攔截get方式提交的方法
?可以在@RequestMapping注解加上method=RequestMapping.get
?2.12方法里得到request和session
?直接在方法的形參上聲明request,SpringMVC就自動把request對象傳入
?2.13SpringMVC的函數返回值
?函數返回值有很多類型,例如:string,modelAndView。ModelAndView類把視圖和數據合并到一起,但一般使用string就行
?2.14攔截的方法里得到從前臺傳入的參數
?直接在形參里聲明這個參數,名字必須和傳過來的參數名一樣
?2.15SpringMVC從后臺向前臺傳遞數據
?通過ModelMap對象,可以在這個對象里調用put方法,把對象加到里面,前臺就可以通過el表達式拿到
?2.16ModelMap數據放入session里
?可以在類上面加上@SessionAttributes注解,里面包含的字符串就是要放入session里面的key
?2.17SpringMVC的攔截器寫法
?1)實現HandlerInterceptor接口
?2)繼承適配器類,然后再接口方法中,實現處理邏輯,然后再配置文件中配置攔截器就行
?2.15注解原理
?注解本質是繼承了Annotation的特殊接口,具體實現類是Java運行時生成的動態代理類。通過反射獲取注解時,返回的是Java運行時生成的動態代理對象,通過代理對象調用自定義注解的方法,最終調用invoke方法。
?2.16攔截器和過濾器的區別
?1、攔截器是基于java反射機制的, 不依賴于servlet容器。只能對Action請求起作用,可以訪問Action上下文、值棧里的對象,在Action的生命周期中,攔截器可以多次調用2、過濾器是基于函數回調的,依賴于servlet容器,過濾器則可以對幾乎所有請求起作用。只能在容器初始化時被調用一次
?3.Mybatis
?支持定制化SQL,存儲過程以及高級映射的優秀持久層框架。Mybatis幾乎避免了所有的JDBC代碼和手工設置參數以及抽取結果集。使用簡單的XML或注解來配置和映射基本體,將接口和Java的POJOS映射成數據庫中的記錄
?3.1Mybatis的優點
?2)簡單易學。本身小且簡單,沒有第三方的依賴
?2)靈活,不會對應用程序或者數據庫的現有設計強加影響
?3)解除SQL與程序代碼耦合
?4)提供XML標簽,支持編寫動態SQL
?5)提供對象關系映射標簽
?3.2mybatis緩存
?1)一級緩存:一級緩存的作用域是session,當openSession后,如果執行相同的SQL,mybatis不進行執行SQL,而是從緩存中返回
?2)二級緩存:作用域是一個mapper的nameSpace,同一個nameSpace中查詢SQL可以從緩存中命中。二級緩存可以跨session
?3.3mybatis的編程步驟
?1)創建sqlsessionFactory
?2)通過SqlsessionFactory創建SqlSession
?3)通過Sqlsession執行數據庫操作
?4)調用session.commit方法提交事務
?5)調用session.close關閉會話
?3.4mapper編寫的幾種方式
?1)接口實現類繼承SqlSessionDaoSupport:在SqlMapConfig.xml中配置mapper.xml的位置,然后定義mapper接口,實現類繼承SqlSessionDaoSupport
?2)使用mapper掃描器
?3.5Mybatis動態sql
?Mybatis動態sql可以在Xml映射文件內,以標簽的形式編寫動態sql,執行原理是根據表達式的值 完成邏輯判斷并動態拼接sql的功能。
?Mybatis提供了9種動態sql標簽:trim | where | set | foreach | if | choose | when | otherwise | bind。
?3.6MyBatis與Hibernate有哪些不同?
?(1)Mybatis和hibernate不同,它不完全是一個ORM框架,因為MyBatis需要程序員自己編寫Sql語句。
?(2)Mybatis直接編寫原生態sql,可以嚴格控制sql執行性能,靈活度高,非常適合對關系數據模型要求不高的軟件開發,因為這類軟件需求變化頻繁,一但需求變化要求迅速輸出成果。但是靈活的前提是mybatis無法做到數據庫無關性,如果需要實現支持多種數據庫的軟件,則需要自定義多套sql映射文件,工作量大。?
?(3)Hibernate對象/關系映射能力強,數據庫無關性好,對于關系模型要求高的軟件,如果用hibernate開發可以節省很多代碼,提高效率。?
?3.7Mybatis是如何進行分頁的?分頁插件的原理是什么?
? Mybatis使用RowBounds對象進行分頁,它是針對ResultSet結果集執行的內存分頁,而非物理分頁。可以在sql內直接書寫帶有物理分頁的參數來完成物理分頁功能,也可以使用分頁插件來完成物理分頁。
? 分頁插件的基本原理是使用Mybatis提供的插件接口,實現自定義插件,在插件的攔截方法內攔截待執行的sql,然后重寫sql,根據dialect方言,添加對應的物理分頁語句和物理分頁參數。
?3.8為什么說Mybatis是半自動ORM映射工具?它與全自動的區別在哪里?
?Hibernate屬于全自動ORM映射工具,使用Hibernate查詢關聯對象或者關聯集合對象時,可以根據對象關系模型直接獲取,所以它是全自動的。而Mybatis在查詢關聯對象或關聯集合對象時,需要手動編寫sql來完成,所以,稱之為半自動ORM映射工具。
?3.9簡述 MyBatis 的體系結構?
? MyBatis 體系結構主要由以下幾個關鍵部分;?
? 1.加載配置?
? 配置有兩種形式,一種是 XML 配置文件,另一種是 Java 代碼的注解.MyBatis 將 SQL 的配
?置信息加載成為一個個的MappedStatement對象(包括了傳入參數映射配置,執行的SQL語句,
?結果映射配置),并將其存儲在內存中.?
? 2.SQL 解析?
? 當 API 接口層接收到調用請求時,會接收到傳入 SQL 的 ID 和傳入對象(可以使
?Map,JavaBean 或者基本數據類型),MyBatis 會根據 SQL 的 ID 找到對應的 MappedStatement,
?然后根據傳入參數對象對 MappedStatement 進行解析,解析后可以得到最終要執行的 SQL 語
?句和參數.?
?3.SQL 執行?
? 將最終得到的 SQL 和參數拿到數據庫進行執行,得到操作數據庫的結果.?
? 4.結果映射?
? 將操作數據庫的結果按照映射的配置進行轉換,可以轉換成 HashMap,JavaBean 或者基
?本數據類型,并將最終結果返回.?
?3.10 ORM
?對象關系映射(ORM),是為了解決面向對象與關系型數據庫存在不匹配的技術。
?通過使用描述對象和數據庫之間映射的元數據,將程序中的對象自動持久化到關系數據庫中。
?ORM可以采用映射元數據來描述對象關系的映射,使得ORM中間件能在任何一個應用的業務邏輯層和數據庫層之間當橋梁。Java典型的ORM框架有:Hibernate,ibatis(mybatis),speedframework。
?ORM的方法論基于三個核心原則:
?1) 簡單:以最基本的形式建模數據
?2) 傳達性:數據庫結構被任何人都能理解的語言文檔化
?3) 精確性:基于數據模型創建正確標準化了的結構
?4.SpringBoot
?.4.1原理
?1. 創建獨立的 Spring 應用程序?
?2. 嵌入的 Tomcat,無需部署 WAR 文件?
?3. 簡化 Maven 配置?
?4. 自動配置 Spring?
?5. 提供生產就緒型功能,如指標,健康檢查和外部配置?
?6. 絕對沒有代碼生成和對 XML 沒有要求配置 [1]
?4.2 JPA 原理
?1. 事務 事務是計算機應用中不可或缺的組件模型,它保證了用戶操作的原子性 ( Atomicity )、一致性 ( Consistency )、隔離性 ( Isolation ) 和持久性 ( Durabilily )。?
?2. 本地事務 緊密依賴于底層資源管理器(例如數據庫連接 ),事務處理局限在當前事務資源內。此種事務處理 方式不存在對應用服務器的依賴,因而部署靈活卻無法支持多數據源的分布式事務
?5.SSM框架搭建
?1.建maven web項目。導入maven需要引入的JAR包
?2. 建立JDBC屬性文件,建立spring-mybatis.xml配置文件,再進行Log4j的配置,進行Junit測試,創建測試用表,利用MyBatis Generator自動創建代碼
?建立service接口和實現類,建立測試類,整合springMVC,配置springMVC.xml,配置web.xml文件,新建JSP頁面進行測試,建立UserController類,最后部署項目
?整理不易,給個贊吧。。。
?日后還會不斷完善