平臺無關性、垃圾回收javascript
封裝、繼承、多態css
含有abstract修飾符的class即爲抽象類,abstract類不能建立的實例對象。含有abstract方法的類必須定義爲abstract class,abstract class類中的方法沒必要是抽象的。abstract class類中定義抽象方法必須在具體(Concrete)子類中實現,因此,不能有抽象構造方法或抽象靜態方法。若是的子類沒有實現抽象父類中的全部抽象方法,那麼子類也必須定義爲abstract類型。html
接口(interface)能夠說成是抽象類的一種特例,接口中的全部方法都必須是抽象的。接口中的方法定義默認爲public abstract類型,接口中的成員變量類型默認爲public static final。java
下面比較一下二者的語法區別:mysql
有抽象方法不必定是抽象類,也多是接口。抽象類不必定有抽象方法,能夠有非抽象的普通方法。linux
在運行狀態中,對於任意一個類,都可以知道這個類的全部屬性和方法;對於任意一個對象,都可以調用它的任意一個方法和屬性;這種動態獲取的信息以及動態調用對象的方法的功能稱爲Java語言的反射機制。web
反射的核心是JVM在運行時才動態加載類或調用方法/訪問屬性,它不須要事先知道運行對象是誰。redis
不能同時使用,this和super不能同時出如今一個構造函數裏面,由於this必然會調用其它的構造函數,其它的構造函數必然也會有super語句的存在,因此在同一個構造函數裏面有相同的語句,就失去了語句的意義,編譯器也不會經過。算法
默認的hashCode方法會利用對象的地址來計算hashcode值,不一樣對象的hashcode值是不同的。spring
public boolean equals(Object obj) { return (this == obj); }
能夠看出Object類中的equals方法與「==」是等價的,也就是說判斷對象的地址是否相等。Object類中的equals方法進行的是基於內存地址的比較。
通常對於存放到Set集合或者Map中鍵值對的元素,須要按須要重寫hashCode與equals方法,以保證惟一性。
public final class String implements java.io.Serializable, Comparable<string>, CharSequence { /** The value is used for character storage. */ private final char value[]; /** Cache the hash code for the string */ private int hash; // Default to 0</string>
String 的底層實現是依靠 char[] 數組,既然依靠的是基礎類型變量,那麼他必定是可變的, String 之因此不可變,是由於 Java 的開發者經過技術實現,隔絕了使用者對 String 的底層數據的操做。
String不能夠繼承,由於String被final修飾,而final修飾的類是不能被繼承的。
String爲不可變的,每次String對象作累加時都會建立StringBuilder對象。
// 程序編譯期即加載完成對象s1爲"ab" String s1 = "a" + "b"; // 這種方式,JVM會先建立一個StringBuilder,而後經過其append方法完成累加操做 String s1 = "a"; String s2 = "b"; String s3 = s1 + s2; // 等效於 String s3 = (new StringBuilder(s1)).append(s2).toString();
List:
Set:
Map:
有,LinkedHashSet和TreeSet
HashSet中add()中調用了HashMap的put(),將一個key-value對放入HashMap中時,首先根據key的hashCode()返回值決定該Entry的存儲位置,若是兩個key的hash值相同,那麼它們的存儲位置相同。若是這個兩個key的equals比較返回true。那麼新添加的Entry的value會覆蓋原來的Entry的value,key不會覆蓋。所以,若是向HashSet中添加一個已經存在的元素,新添加的集合元素不會覆蓋原來已有的集合元素。
IO,其實意味着:數據不停地搬入搬出緩衝區而已(使用了緩衝區)。
BIO:同步阻塞式IO,服務器實現模式爲一個鏈接一個線程,即客戶端有鏈接請求時服務器端就須要啓動一個線程進行處理,若是這個鏈接不作任何事情會形成沒必要要的線程開銷,固然能夠經過線程池機制改善。
NIO:同步非阻塞式IO,服務器實現模式爲一個請求一個線程,即客戶端發送的鏈接請求都會註冊到多路複用器上,多路複用器輪詢到鏈接有I/O請求時才啓動一個線程進行處理。
Java是一種多線程編程語言,咱們可使用Java來開發多線程程序。 多線程程序包含兩個或多個可同時運行的部分,每一個部分能夠同時處理不一樣的任務,從而能更好地利用可用資源,特別是當您的計算機有多個CPU時。多線程使您可以寫入多個活動,能夠在同一程序中同時進行操做處理。
兩個或者多個線程之間相互等待,致使線程都沒法執行,叫作線程死鎖。
wait和notify方法定義在Object類中,所以會被全部的類所繼承。 這些方法都是final的,即它們都是不能被重寫的,不能經過子類覆寫去改變它們的行爲。 而sleep方法是在Thread類中是由native修飾的,本地方法。
當線程調用了wait()方法時,它會釋放掉對象的鎖。
另外一個會致使線程暫停的方法:Thread.sleep(),它會致使線程睡眠指定的毫秒數,但線程在睡眠的過程當中是不會釋放掉對象的鎖的。
由於wait方法會釋放鎖,因此調用該方法時,當前的線程必須擁有當前對象的monitor,也即lock,就是鎖。要確保調用wait()方法的時候擁有鎖,即wait()方法的調用必須放在synchronized方法或synchronized塊中。
synchronized鎖住了
新建、就緒、運行、阻塞、死亡
互斥同步:推薦使用 synchronized 關鍵字進行同步, 在 concurrent包中有ReentrantLock類, 實現效果差很少. 仍是推薦原生態的synchronized.
非阻塞同步:須要硬件指令完成.經常使用的指令有:
Test-and-Set
Fetch-and-Increment
Swap
Compare-and-Swap (CAS)
Load-Linked/Store-Conditional (LL/SC)
典型的應用在 AtomicInteger 中
無同步方案:將變量保存在本地線程中,就不會出現多個線程併發的錯誤了。
java中主要使用的就是ThreadLocal這個類。
重量級鎖、顯式鎖、併發容器、併發同步器、CAS、volatile、AQS等
可重入公平鎖獲取流程
在獲取鎖的時候,若是當前線程以前已經獲取到了鎖,就會把state加1,在釋放鎖的時候會先減1,這樣就保證了同一個鎖能夠被同一個線程獲取屢次,而不會出現死鎖的狀況。這就是ReentrantLock的可重入性。
對於非公平鎖而言,調用lock方法後,會先嚐試搶佔鎖,在各類判斷的時候會先忽略等待隊列,若是鎖可用,就會直接搶佔使用。
悲觀鎖:假定會發生併發衝突,則屏蔽一切可能違反數據完整性的操做
樂觀鎖:假定不會發生併發衝突,只在數據提交時檢查是否違反了數據完整性(不能解決髒讀問題)
CountDownLatch 同步計數器,主要用於線程間的控制,但計數沒法被重置,若是須要重置計數,請考慮使用 CyclicBarrier 。
(線程池的排隊策略)
核心線程數
這個類是一個同步計數器,主要用於線程間的控制,當CountDownLatch的count計數>0時,await()會形成阻塞,直到count變爲0,await()結束阻塞,使用countDown()會讓count減1。CountDownLatch的構造函數能夠設置count值,當count=1時,它的做用相似於wait()和notify()的做用。若是我想讓其餘線程執行完指定程序,其餘全部程序都執行結束後我再執行,這時能夠用CountDownLatch,但計數沒法被重置,若是須要重置計數,請考慮使用 CyclicBarrier 。
java中的線程分爲兩種:守護線程(Daemon)和用戶線程(User)。
任何線程均可以設置爲守護線程和用戶線程,經過方法Thread.setDaemon(bool on);true則把該線程設置爲守護線程,反之則爲用戶線程。Thread.setDaemon()必須在Thread.start()以前調用,不然運行時會拋出異常。
惟一的區別是判斷虛擬機(JVM)什麼時候離開,Daemon是爲其餘線程提供服務,若是所有的User Thread已經撤離,Daemon 沒有可服務的線程,JVM撤離。也能夠理解爲守護線程是JVM自動建立的線程(但不必定),用戶線程是程序建立的線程;好比JVM的垃圾回收線程是一個守護線程,當全部線程已經撤離,再也不產生垃圾,守護線程天然就沒事可幹了,當垃圾回收線程是Java虛擬機上僅剩的線程時,Java虛擬機會自動離開。
程序計數器:記錄正在執行的虛擬機字節碼指令的地址(若是正在執行的是本地方法則爲空)。
Java虛擬機棧:每一個 Java 方法在執行的同時會建立一個棧幀用於存儲局部變量表、操做數棧、常量池引用等信息。每個方法從調用直至執行完成的過程,就對應着一個棧幀在 Java 虛擬機棧中入棧和出棧的過程。
本地方法棧:與 Java 虛擬機棧相似,它們之間的區別只不過是本地方法棧爲本地方法服務。
Java堆:幾乎全部對象實例都在這裏分配內存。是垃圾收集的主要區域("GC 堆"),虛擬機把 Java 堆分紅如下三塊:
新生代又可細分爲Eden空間、From Survivor空間、To Survivor空間,默認比例爲8:1:1。
方法區:方法區(Method Area)與Java堆同樣,是各個線程共享的內存區域。Object Class Data(類定義數據)是存儲在方法區的,此外,常量、靜態變量、JIT編譯後的代碼也存儲在方法區。
運行時常量池:運行時常量池是方法區的一部分。Class 文件中的常量池(編譯器生成的各類字面量和符號引用)會在類加載後被放入這個區域。除了在編譯期生成的常量,還容許動態生成,例如 String 類的 intern()。這部分常量也會被放入運行時常量池。
直接內存:直接內存(Direct Memory)並非虛擬機運行時數據區的一部分,也不是Java虛擬機規範中定義的內存區域,可是這部份內存也被頻繁地使用,並且也可能致使OutOfMemoryError 異常出現。避免在Java堆和Native堆中來回複製數據。
HotSpot虛擬機中,對象在內存中的佈局分爲三塊區域:對象頭、實例數據和對齊填充。
對象頭包括兩部分:Mark Word 和 類型指針。
Mark Word:Mark Word用於存儲對象自身的運行時數據,如哈希碼(HashCode)、GC分代年齡、鎖狀態標誌、線程持有的鎖、偏向線程ID、偏向時間戳等等,佔用內存大小與虛擬機位長一致。
類型指針:類型指針指向對象的類元數據,虛擬機經過這個指針肯定該對象是哪一個類的實例。
/** * 快速排序 * * @param array * @param _left * @param _right */ private static void quickSort(int[] array, int _left, int _right) { int left = _left;// int right = _right; int pivot;//基準線 if (left < right) { pivot = array[left]; while (left != right) { //從右往左找到比基準線小的數 while (left < right && pivot <= array[right]) { right--; } //將右邊比基準線小的數換到左邊 array[left] = array[right]; //從左往右找到比基準線大的數 while (left < right && pivot >= array[left]) { left++; } //將左邊比基準線大的數換到右邊 array[right] = array[left]; } //此時left和right指向同一位置 array[left] = pivot; quickSort(array, _left, left - 1); quickSort(array, left + 1, _right); } }
遞歸
public int TreeDepth(TreeNode root) { if (root == null) { return 0; } return Math.max(TreeDepth(root.left) + 1, TreeDepth(root.right) + 1); }
非遞歸,層次遍歷
public int TreeDepth_2(TreeNode root) { if (root == null) { return 0; } Queue<TreeNode> queue = new LinkedList<>(); queue.offer(root); int start = 0; int end = 1; int depth = 0; while (!queue.isEmpty()) { TreeNode temp = queue.poll(); start++; if (temp.left != null) { queue.offer(temp.left); } if (temp.right != null) { queue.offer(temp.right); } if (start == end) { start = 0; end = queue.size(); depth++; } } return depth; }
public void levelOrder(TreeNode root) { //使用隊列,先進先出 Queue<TreeNode> queue = new LinkedList<>(); queue.add(root); while (!queue.isEmpty()) { TreeNode temp = queue.poll(); System.out.print(temp.val + " "); if (temp.left != null) { queue.offer(temp.left); } if (temp.right != null) { queue.offer(temp.right); } } }
從下往上遍歷,若是子樹是平衡二叉樹,則返回子樹高度,不然返回-1
public boolean IsBalanced_Solution(TreeNode root) { return MaxDepth(root) != -1; } public int MaxDepth(TreeNode root) { if (root == null) { return 0; } int leftHeight = MaxDepth(root.left); if (leftHeight == -1) { return -1; } int rightHeight = MaxDepth(root.right); if (rightHeight == -1) { return -1; } return Math.abs(leftHeight - rightHeight) > 1 ? -1 : 1 + Math.max(leftHeight, rightHeight); }
將當前節點和下一節點保存起來,而後將當前節點反轉。
public ListNode ReverseList(ListNode head) { //head爲當前節點,若是當前節點爲空的話,那就什麼也不作,直接返回null ListNode pre = null;//pre爲當前節點的前一節點 ListNode next = null;//next爲當前節點的下一節點 //須要pre和next的目的是讓當前節點從pre.head.next1.next2變成pre<-head next1.next2 //即pre讓節點能夠反轉所指方向,但反轉以後若是不用next節點保存next1節點的話,此單鏈表就此斷開了 //因此須要用到pre和next兩個節點 //1.2.3.4.5 //1<-2<-3 4.5 //作循環,若是當前節點不爲空的話,始終執行此循環,此循環的目的就是讓當前節點從指向next到指向pre while (head != null) { //先用next保存head的下一個節點的信息,保證單鏈表不會由於失去head節點的原next節點而就此斷裂 next = head.next; //保存完next,就可讓head從指向next變成指向pre了 head.next = pre; //head指向pre後,就繼續依次反轉下一個節點 //讓pre,head,next依次向後移動一個節點,繼續下一次的指針反轉 pre = head; head = next; } //若是head爲null的時候,pre就爲最後一個節點了,可是鏈表已經反轉完畢,pre就是反轉後鏈表的第一個節點 //直接輸出pre就是咱們想要獲得的反轉後的鏈表 return pre; }
利用遞歸走到鏈表的末端,而後再更新每個節點的next值 ,實現鏈表的反轉。
public ListNode ReverseList(ListNode head) { //若是鏈表爲空或者鏈表中只有一個元素 if (head == null || head.next == null) return head; //先遞歸找到到鏈表的末端結點,從後依次反轉整個鏈表 ListNode reverseHead = ReverseList(head.next); //再將當前節點設置爲後面節點的後續節點 head.next.next = head; head.next = null; return reverseHead; }
用LinkedHashMap記錄字符出現的次數
public Character firstNotRepeating(String str){ if(str == null) return null; char[] strChar = str.toCharArray(); LinkedHashMap<Character,Integer> hash = new LinkedHashMap<Character,Integer>(); for(char item:strChar){ if(hash.containsKey(item)) hash.put(item, hash.get(item)+1); else hash.put(item, 1); } for(char key:hash.keySet()) { if(hash.get(key)== 1) return key; } return null; }
利用HashSet的元素不能重複,若是有重複的元素,則刪除重複元素,若是沒有則添加,最後剩下的就是隻出現一次的元素
public void FindNumsAppearOnce(int[] array, int num[]) { HashSet<Integer> set = new HashSet<>(); for (int i = 0; i < array.length; i++) { if (!set.add(array[i])) { set.remove(array[i]); } } Iterator<Integer> iterator = set.iterator(); num[0] = iterator.next(); }
用HashMap<K,V>保存數組的值,key爲數組值,value爲布爾型表示是否有重複
public void FindNumsAppearOnce_2(int[] array, int num[]) { HashMap<Integer, Boolean> map = new HashMap<>(); for (int i = 0; i < array.length; i++) { if (!map.containsKey(array[i])) { map.put(array[i], true); } else { map.put(array[i], false); } } for (int i = 0; i < array.length; i++) { if (map.get(array[i])) { num[0] = array[i]; } } }
利用HashSet的元素不能重複,若是有重複的元素,則刪除重複元素,若是沒有則添加,最後剩下的就是隻出現一次的元素
public void FindNumsAppearOnce(int[] array, int num1[], int num2[]) { HashSet<Integer> set = new HashSet<>(); for (int i = 0; i < array.length; i++) { if (!set.add(array[i])) { set.remove(array[i]); } } Iterator<Integer> iterator = set.iterator(); num1[0] = iterator.next(); num2[0] = iterator.next(); }
用HashMap<K,V>保存數組的值,key爲數組值,value爲布爾型表示是否有重複
public void FindNumsAppearOnce_2(int[] array, int num1[], int num2[]) { HashMap<Integer, Boolean> map = new HashMap<>(); for (int i = 0; i < array.length; i++) { if (!map.containsKey(array[i])) { map.put(array[i], true); } else { map.put(array[i], false); } } int index = 0;//區分是第幾個不重複的值 for (int i = 0; i < array.length; i++) { if (map.get(array[i])) { index++; if (index == 1) { num1[0] = array[i]; } else { num2[0] = array[i]; } } } }
位運算 異或,兩個不相等的元素在位級表示上一定會有一位存在不一樣。
public void FindNumsAppearOnce_3(int[] array, int num1[], int num2[]) { int diff = 0; for (int num : array) diff ^= num; // 獲得最右一位 diff &= -diff; for (int num : array) { if ((num & diff) == 0) num1[0] ^= num; else num2[0] ^= num; } }
進程:進程是操做系統資源分配的基本單位。每一個進程都有獨立的代碼和數據空間(進程上下文),進程間的切換會有較大的開銷,一個進程包含1–n個線程。
線程:線程是CPU獨立調度的基本單位。同一類線程共享代碼和數據空間,每一個線程有獨立的運行棧和程序計數器(PC),線程切換開銷小。
線程和進程的生命週期:新建、就緒、運行、阻塞、死亡
不一樣進程打開同一個文件,文件描述符可能相同可能不一樣。
OSI七層網絡模型 | 對應網絡協議 |
---|---|
應用層 | HTTP、TFTP、FTP、NFS、WAIS、SMTP |
表示層 | Telnet、Rlogin、SNMP、Gopher |
會話層 | SMTP、DNS |
傳輸層 | TCP、UDP |
網絡層 | IP、ICMP、ARP、RARP、AKP、UUCP |
數據鏈路層 | FDDI、Ethernet、Arpanet、PDN、SLIP、PPP |
物理層 | IEEE 802.1A、IEEE 802.2到IEEE 802.11 |
HTTP/0.9只支持客戶端發送Get請求,且不支持請求頭。HTTP具備典型的無狀態性。
HTTP/1.0在HTTP/0.9的基礎上支持客戶端發送POST、HEAD。HTTP 1.0須要使用keep-alive參數來告知服務器端要創建一個長鏈接,但默認是短鏈接。
HTTP(Hypertext Transfer Protocol)超文本傳輸協議是用來在Internet上傳送超文本的傳送協議,它可使瀏覽器更加高效,使網絡傳輸減小。但HTTP協議採用明文傳輸信息,存在信息竊聽、信息篡改和信息劫持的風險。
HTTPS(Secure Hypertext Transfer Protocol) 安全超文本傳輸協議是一個安全的通訊通道,它基於HTTP開發,用於在客戶計算機和服務器之間交換信息。HTTPS使用安全套接字層(SSL)進行信息交換,簡單來講HTTPS是HTTP的安全版,是使用TLS/SSL加密的HTTP協議。
HTTPS和HTTP的區別主要以下:
所謂三次握手(Three-Way Handshake)即創建TCP鏈接,就是指創建一個TCP鏈接時,須要客戶端和服務端總共發送3個包以確認鏈接的創建。整個流程以下圖所示:
Server在LISTEN狀態下,收到創建鏈接請求的SYN報文後,能夠直接把ACK和SYN放在一個報文裏發送給Client。而關閉鏈接時,當收到對方的FIN報文時,僅僅表示對方再也不發送數據了可是還能接收數據,己方也未必所有數據都發送給對方了,因此己方能夠當即close,也能夠發送一些數據給對方後,再發送FIN報文給對方來表示贊成如今關閉鏈接,所以,己方ACK和FIN通常都會分開發送。
http是要基於TCP鏈接基礎上的,簡單的說,TCP就是單純創建鏈接,不涉及任何咱們須要請求的實際數據,簡單的傳輸。http是用來收發數據,即實際應用上的。
Server在LISTEN狀態下,收到創建鏈接請求的SYN報文後,能夠直接把ACK和SYN放在一個報文裏發送給Client。而關閉鏈接時,當收到對方的FIN報文時,僅僅表示對方再也不發送數據了可是還能接收數據,己方也未必所有數據都發送給對方了,因此己方能夠當即close,也能夠發送一些數據給對方後,再發送FIN報文給對方來表示贊成如今關閉鏈接,所以,己方ACK和FIN通常都會分開發送。
經常使用的會話跟蹤技術是Cookie與Session。Cookie經過在客戶端記錄信息肯定用戶身份,Session經過在服務器端記錄信息肯定用戶身份。
聯繫:
區別:
域名解析 --> 發起TCP的3次握手 --> 創建TCP鏈接後發起http請求 --> 服務器響應http請求,瀏覽器獲得html代碼 --> 瀏覽器解析html代碼,並請求html代碼中的資源(如js、css、圖片等) --> 瀏覽器對頁面進行渲染呈現給用戶
瀏覽器緩存 --> 系統緩存 --> 路由器緩存 --> ISP(互聯網服務提供商)DNS緩存 --> 根域名服務器 --> 頂級域名服務器 --> 主域名服務器 --> 保存結果至緩存
Ping程序的實質是利用了ICMP請求回顯和回顯應答報文,但ARP請求和應答報文也在其中起了很是重要的做用。
GET 請求:
POST 請求 :
在MySQL數據庫中,支持上面四種隔離級別,默認的爲REPEATABLE READ(可重複讀)。
left join / inner join / right join
回答存儲機制以及持久化
確保一個類最多隻有一個實例,並提供一個全局訪問點。
public class Singleton { private volatile static Singleton instance = null; private Singleton() { } /** * 當第一次調用getInstance()方法時,instance爲空,同步操做,保證多線程實例惟一 * 當第一次後調用getInstance()方法時,instance不爲空,不進入同步代碼塊,減小了沒必要要的同步 */ public static Singleton getInstance() { if (instance == null) { synchronized (Singleton.class) { if (instance == null) { instance = new Singleton(); } } } return instance; } }
單例模式
SpringBoot就是對各類框架的整合,讓框架集成在一塊兒更加簡單,簡化了開發過程、配置過程、部署過程、監控過程。
IOC:控制反轉也叫依賴注入,IOC利用java反射機制。所謂控制反轉是指,原本被調用者的實例是有調用者來建立的,這樣的缺點是耦合性太強,IOC則是統一交給spring來管理建立,將對象交給容器管理,你只須要在spring配置文件總配置相應的bean,以及設置相關的屬性,讓spring容器來生成類的實例對象以及管理對象。在spring容器啓動的時候,spring會把你在配置文件中配置的bean都初始化好,而後在你須要調用的時候,就把它已經初始化好的那些bean分配給你須要調用這些bean的類。
AOP是對OOP的補充和完善。AOP利用的是代理,分爲CGLIB動態代理和JDK動態代理。OOP引入封裝、繼承和多態性等概念來創建一種對象層次結構。OOP編程中,會有大量的重複代碼。而AOP則是將這些與業務無關的重複代碼抽取出來,而後再嵌入到業務代碼當中。實現AOP的技術,主要分爲兩大類:一是採用動態代理技術,利用截取消息的方式,對該消息進行裝飾,以取代原有對象行爲的執行;二是採用靜態織入的方式,引入特定的語法建立「方面」,從而使得編譯器能夠在編譯期間織入有關「方面」的代碼,屬於靜態代理。
下降了組件之間的耦合性 ,實現了軟件各層之間的解耦
工廠模式
權限管理、日誌、事務管理等。
切面經過帶有@Aspect註解的類實現。
Spring中定義了四個advice:BeforeAdvice, AfterAdvice, ThrowAdvice和DynamicIntroductionAdvice。
Before Advice:在方法執行前執行。
AfterAdvice:在方法執行以後調用的通知,不管方法執行是否成功。
After ReturningAdvice:在方法執行後返回一個結果後執行。
After ThrowingAdvice:在方法執行過程當中拋出異常的時候執行。
代理分爲靜態代理和動態代理,靜態代理是在編譯時就將接口、實現類、代理類所有手動完成,但若是咱們須要不少的代理,每個都這麼手動的去建立實屬浪費時間,並且會有大量的重複代碼。動態代理能夠在程序運行期間根據須要動態的建立代理類及其實例,來完成具體的功能。
@Controller:用於標記在一個類上,使用它標記的類就是一個SpringMVC Controller 對象。
@RequestMapping:是一個用來處理請求地址映射的註解,可用於類或方法上。用於類上,表示類中的全部響應請求的方法都是以該地址做爲父路徑。
@Resource和@Autowired:@Resource和@Autowired都是作bean的注入時使用,其實@Resource並非Spring的註解,它的包是javax.annotation.Resource,須要導入,可是Spring支持該註解的注入。
@ResponseBody:返回的數據不是html標籤的頁面,而是其餘某種格式的數據時(如json、xml等)使用。
@Repository:DAO層
@Service:服務層
@Autowired註解是按類型裝配依賴對象,默認狀況下它要求依賴對象必須存在,若是容許null值,能夠設置它required屬性爲false。
@Resource註解和@Autowired同樣,也能夠標註在字段或屬性的setter方法上,但它默認按名稱裝配。名稱能夠經過@Resource的name屬性指定,若是沒有指定name屬性,當註解標註在字段上,即默認取字段的名稱做爲bean名稱尋找依賴對象,當註解標註在屬性的setter方法上,即默認取屬性名做爲bean名稱尋找依賴對象。
@Resources按名稱,是JDK的,@Autowired按類型,是Spring的。
@PathVariable是用來對指定請求的URL路徑裏面的變量。
Listener我是這樣理解他的,他是一種觀察者模式的實現。
Filter的使用戶能夠改變一 個request或修改一個response。 Filter 不是一個servlet,它不能產生一個response,可是他可以在一個request到達servlet以前預先處理request,也能夠在一個響應離開 servlet時處理response。
通俗的說,就是一個容器,把消息丟進去,不須要當即處理。而後有個程序去從容器裏面把消息一條條讀出來處理。
dubbo
ps -ef | grep java
多線程,JVM
書籍+博客+視頻
舉出三個以上的國內開源框架,越多越好,dubbo、fastjson、sharding-jdbc、Elastic-job...
電商,突出質量
淘寶是C2C,京東和天貓是B2C,淘寶門檻低,種類,國際市場佈局
深刻理解Java虛擬機&HEAD FIRST設計模式&高性能MYSQL&Java併發編程實戰,看博客比較多,感受博客更有針對性