對於javaSE的理解
是整個JAVA的基礎和核心,是剛接觸java要學習的基礎知識
1.1 控制數據的流向,將前臺傳過來的數據包起來,而後一個一個地插入數據庫永久保存。
1.2 從數據庫中用jdbc取出數據,而後包起來,最終傳遞到前臺頁面進行公開展覽
where、having之間的區別和用法
聚合函數是比較where、having 的關鍵。
若須引入聚合函數來對group by 結果進行過濾 則只能用having
select sum(score) from student where sex='man' group by name having sum(score)>210
where 後不能跟聚合函數,由於where執行順序大於聚合函數
dubbo
調用關係說明:
0. 服務容器負責啓動,加載,運行服務提供者。
1. 服務提供者在啓動時,向註冊中心註冊本身提供的服務。 --寫入本身的URL地址。
2. 服務消費者在啓動時,向註冊中心訂閱本身所需的服務。 --訂閱提供者的URL地址,並寫入本身的URL地址。
3. 註冊中心返回服務提供者地址列表給消費者,若是有變動,註冊中心將基於長鏈接推送變動數據給消費者。
4. 服務消費者,從提供者地址列表中,基於軟負載均衡算法,選一臺提供者進行調用,若是調用失敗,再選另外一臺調用。
5. 服務消費者和提供者,在內存中累計調用次數和調用時間,定時每分鐘發送一次統計數據到監控中心。
Dubbo建議使用Zookeeper做爲服務的註冊中心。
Dubbo的將註冊中心進行抽象,是得它能夠外接不一樣的存儲媒介給註冊中心提供服務,有ZooKeeper,Redis等
首先是負載均衡,單註冊中心的承載能力是有限的,在流量達到必定程度的時 候就須要分流,負載均衡就是爲了分流而存在的,一個ZooKeeper羣配合相應的Web應用就能夠很容易達到負載均衡;資源同步,單單有負載均衡還不夠,節點之間的數據和資源須要同步
負載均衡策略
RandomLoadBalance:隨機負載均衡算法,Dubbo默認的負載均衡策略
按權重設置隨機機率。在一個截面上碰撞的機率較高,但調用越大分佈越均勻
RoundRobinLoadBalance:輪詢負載均衡算法,按公約後的權重設置輪循比率
這種模式下,在權重設置不合理的狀況下,會致使某些節點沒法負載請求,另外,若是有些機器性能比較低,會存在請求阻塞的狀況
ConsistentHashLoadBalance: 一致性Hash,相同參數的請求老是發到同一提供者。
當某一臺提供者掛時,本來發往該提供者的請求,基於虛擬節點,平攤到其它提供者,不會引發劇烈變更。
Zookeeper的做用:
zookeeper用來註冊服務和進行負載均衡,哪個服務由哪個機器來提供必需讓調用者知道,簡單來講就是ip地址和服務名稱的對應關係。固然也能夠 經過硬編碼的方式把這種對應關係在調用方業務代碼中實現,可是若是提供服務的機器掛掉調用者沒法知曉,若是不更改代碼會繼續請求掛掉的機器提供服務。 zookeeper經過心跳機制能夠檢測掛掉的機器並將掛掉機器的ip和服務對應關係從列表中刪除。
java小例子: int a=2,b=2;
硬編碼:if(a==2) return false;
非硬編碼 if(a==b) return true; (就是把數值寫成常數而不是變量 )
一個簡單的版本:如求圓的面積 的問題 PI(3.14)
那麼3.14*r*r 就是硬編碼,而PI*r*r 就不是硬編碼。
ZooKeeper的特性引進來。
首先是負載均衡,單註冊中心的承載能力是有限的,在流量達到必定程度的時 候就須要分流,負載均衡就是爲了分流而存在的,一個ZooKeeper羣配合相應的Web應用就能夠很容易達到負載均衡
資源同步 節點之間的數據和資源須要同步,ZooKeeper集羣就自然具有有這樣的功能
Zookeeper作了什麼?
配置管理 若是程序分散部署在多臺機器上,要逐個改變配置就變得困難。如今把這些配置所有放到zookeeper上去,保存在 Zookeeper 的某個目錄節點中,而後全部相關應用程序對這個目錄節點進行監聽,一旦配置信息發生變化,每一個應用程序就會收到 Zookeeper 的通知
集羣管理 是否有機器退出和加入、選舉master。
分佈式鎖 一個是保持獨佔,另外一個是控制時序。
dubbo協議
適用範圍:傳入傳出參數數據包較小(建議小於100K),消費者比提供者個數多(併發量高),單一消費者沒法壓滿提供者,儘可能不要用dubbo協議傳輸大文件或超大字符串。
適用場景:常規遠程服務方法調用
一、dubbo默認採用dubbo協議,dubbo協議採用單一長鏈接和NIO異步通信,適合於小數據量大併發的服務調用,以及服務消費者機器數遠大於服務提供者機器數的狀況
二、他不適合傳送大數據量的服務,好比傳文件,傳視頻等,除非請求量很低。
三、Dubbo協議缺省每服務每提供者每消費者使用單一長鏈接,若是數據量較大,可使用多個鏈接。
四、爲防止被大量鏈接撐掛,可在服務提供方限制大接收鏈接數,以實現服務提供方自我保護
爲何採用異步單一長鏈接?
由於服務的現狀大都是服務提供者少,一般只有幾臺機器,而服務的消費者多,可能整個網站都在訪問該服務,好比Morgan的提供者只有6臺提供者,卻有上百臺消費者,天天有1.5億次調用,若是採用常規的hessian服務,服務提供者很容易就被壓跨,經過單一鏈接,保證單一消費者不會壓死提供者,長鏈接,減小鏈接握手驗證等
何時用長鏈接,短鏈接?
長鏈接多用於操做頻繁,點對點的通信,並且鏈接數不能太多狀況。每一個TCP鏈接都須要三步握手,這須要時間,若是每一個操做都是先鏈接,再操做的話那麼處理速度會下降不少,因此每一個操做完後都不斷開,次處理時直接發送數據包就OK了,不用創建TCP鏈接。例如:數據庫的鏈接用長鏈接,若是用短鏈接頻繁的通訊會形成socket錯誤,並且頻繁的socket 建立也是對資源的浪費。
而像WEB網站的http服務通常都用短連接,由於長鏈接對於服務端來講會耗費必定的資源,而像WEB網站這麼頻繁的成千上萬甚至上億客戶端的鏈接用短鏈接會更省一些資源,若是用長鏈接,並且同時有成千上萬的用戶,若是每一個用戶都佔用一個鏈接的話,那可想而知吧。因此併發量大,但每一個用戶無需頻繁操做狀況下需用短連好。
短鏈接:通訊雙方有數據交互時,就創建一個TCP鏈接,數據發送完成後,則斷開此TCP鏈接
單例模式:確保某一個類只有一個實例,並且自行實例化並向整個系統提供這個實例
枚舉(單例模式)
public enum Singleton {
INSTANCE;
public void whateverMethod() {
}
}
// 餓漢式單例
public class Singleton1 {
// 私有構造
private Singleton1() {}
private static Singleton1 single = new Singleton1();
// 靜態工廠方法
public static Singleton1 getInstance() {
return single;
}
}
應用剛啓動的時候,無論外部有沒有調用該類的實例方法,該類的實例就已經建立好了。以空間換時間
寫法簡單,在多線程下也能保證單例實例的惟一性,不用同步,運行效率高。
當類被加載時,靜態變量instance會被初始化,此時類的私有構造函數會被調用,單例類的惟一實例將被建立。
懶漢式:
應用剛啓動的時候,並不建立實例,當外部調用該類的實例或者該類實例方法的時候,才建立該類的實例。是以時間換空間。
實例在被使用的時候才被建立,能夠節省系統資源,體現了延遲加載的思想。html
/**
* 飽漢式(懶漢式)----就是有錢,豪,用的時候再new(線程不安全)
* <p>
* Created by lxk on 2017/3/23
*/
public class SingletonPattern2 {
private static SingletonPattern2 singletonInstance;
private SingletonPattern2() {
}
public static SingletonPattern2 getSingletonInstance() {
if (singletonInstance == null) {
singletonInstance = new SingletonPattern2();
}
return singletonInstance;
}
///**
// * 爲了應對上述的不安全,能夠簡單的以下操做給方法添加[synchronized],使之成爲同步函數。
// * 可是:
// * 在不少線程的狀況下,就每一個線程訪問都得判斷鎖,效率就是問題。因此,纔有後面的[雙重鎖形式]
// */
//public static synchronized SingletonPattern2 getSingletonInstance() {
// if (singletonInstance == null) {
// singletonInstance = new SingletonPattern2();
// }
// return singletonInstance;
//}
在任何須要生成複雜對象的地方,均可以使用工廠方法模式(好比 計算器的加減乘除)
步驟 1
建立一個接口:
Shape.java
public interface Shape { void draw(); }
步驟 2
建立實現接口的實體類。
Rectangle.java
public class Rectangle implements Shape { @Override public void draw() { System.out.println("Inside Rectangle::draw() method."); } }
Square.java
public class Square implements Shape { @Override public void draw() { System.out.println("Inside Square::draw() method."); } }
Circle.java
public class Circle implements Shape { @Override public void draw() { System.out.println("Inside Circle::draw() method."); } }
步驟 3
建立一個工廠,生成基於給定信息的實體類的對象。
ShapeFactory.java
public class ShapeFactory { //使用 getShape 方法獲取形狀類型的對象
public Shape getShape(String shapeType){
if(shapeType == null){ return null; }
if(shapeType.equalsIgnoreCase("CIRCLE")){ return new Circle(); } else if(shapeType.equalsIgnoreCase("RECTANGLE")){ return new Rectangle(); } else if(shapeType.equalsIgnoreCase("SQUARE")){ return new Square(); } return null; } }
步驟 4
使用該工廠,經過傳遞類型信息來獲取實體類的對象。
FactoryPatternDemo.java
public class FactoryPatternDemo {
public static void main(String[] args) {
ShapeFactory shapeFactory = new ShapeFactory(); //獲取 Circle 的對象,並調用它的 draw 方法
Shape shape1 = shapeFactory.getShape("CIRCLE"); //調用 Circle 的 draw 方法 shape1.draw(); //獲取 Rectangle 的對象,並調用它的 draw 方法
Shape shape2 = shapeFactory.getShape("RECTANGLE"); //調用 Rectangle 的 draw 方法 shape2.draw(); //獲取 Square 的對象,並調用它的 draw 方法
Shape shape3 = shapeFactory.getShape("SQUARE"); //調用 Square 的 draw 方法 shape3.draw();
}
}
步驟 5
執行程序,輸出結果:
Inside Circle::draw() method.
Inside Rectangle::draw() method.
Inside Square::draw() method.
sql優化
SELECT子句中避免使用‘*’;
表設計--合理的增長冗餘的字段(減小表的聯接查詢);
在業務密集的SQL當中儘可能不採用IN操做符,用EXISTS替代IN、用NOT EXISTS替代NOT IN;
用UNION-ALL 替換UNION /or( 若是有可能的話);
最左匹配原則
兩個字段(name,age)創建聯合索引,若是where age=12這樣的話,是沒有利用到索引的,這裏咱們能夠簡單的理解爲先是對name字段的值排序,而後對age的數據排序,若是直接查age的話,這時就沒有利用到索引了,查詢條件where name=’xxx’ and age=xx 這時的話,就利用到索引了
失效條件
條件是or,若是還想讓or條件生效,給or每一個字段加個索引
避免在索引列上使用計算。WHERE子句中,若是索引列是函數的一部分。優化器將不使用索引而使用全表掃描;
低效: SELECT … FROM DEPT WHERE SAL * 12 > 25000; 高效: SELECT … FROM DEPT WHERE SAL > 25000/12;
模糊查詢like 關鍵詞%yue%,因爲yue前面用到了「%」,所以該查詢必然走全表掃描,除非必要,不然不要在關鍵詞前加%;
注意:like ‘…%’,是會使用索引的;左模糊like
考慮索引重建場合
索引最大的好處是提升查詢速度,
缺點是更新數據時效率低,由於要同時更新索引
對數據進行頻繁查詢進創建索引,若是要頻繁更改數據不建議使用索引。
表上頻繁發生update,delete操做。
表上發生了alter table ..move操做(move操做致使了rowid變化)
爲何要分庫分表,主從複製,讀寫分離
針對大數據量而且訪問頻繁的表,將其分爲若干個表
當一張表的數據達到幾千萬時,你查詢一次所花的時間會變多,若是有聯合查詢的話,我想有可能會死在那兒了。分表的目的就在於此,減少數據庫的負擔,縮短查詢時間;
主從結構,一主多備,讀寫分離,讀從庫,寫主庫
在實際的應用中,絕大部分狀況都是讀遠大於寫。Mysql提供了讀寫分離的機制,全部的寫操做都必須對應到Master,讀操做能夠在 Master和Slave機器上進行,Slave與Master的結構徹底同樣,
全部的寫操做都是先在Master上操做,而後同步更新到Slave上,因此從Master同步到Slave機器有必定的延遲
提升數據庫的吞吐量
非關係型數據庫中,咱們查詢一條數據,結果出來一個數組,關係型數據庫中,查詢一條數據結果是一個對象。
關係型數據庫
SQLite、Oracle、mysql
特性:關係型數據庫的最大特色就是事務的一致性;
優勢:通用的SQL語言使得操做關係型數據庫很是方便,大大減低了數據冗餘和數據不一致的機率;
缺點:爲了維護一致性所付出的巨大代價就是其讀寫性能比較差,海量數據的高效率讀寫;
非關係型數據庫
MongoDb、redis、HBase
特性:使用鍵值對存儲數據;嚴格上不是一種數據庫,應該是一種數據結構化存儲方法的集合
優勢:無需通過sql層的解析,讀寫性能很高,nosql的存儲格式是key,value形式、文檔形式、圖片形式等等,文檔形式、圖片形式等等,而關係型數據庫則只支持基礎類型。
缺點:不提供sql支持,學習和使用成本較高,無事務處理,附加功能bi和報表等支持也很差
數據庫事務必須具有ACID特性,ACID是Atomic原子性,Consistency一致性,Isolation隔離性,Durability持久性
事務的四大特性
原子性--事務包含的全部操做要麼所有成功,要麼所有失敗回滾
一致性--事務必須使數據庫從一個一致性狀態變換到另外一個一致性狀態,也就是說一個事務執行以前和執行以後都必須處於一致性狀態。
拿轉帳來講,假設用戶A和用戶B二者的錢加起來一共是5000,那麼無論A和B之間如何轉帳,轉幾回帳,事務結束後兩個用戶的錢相加起來應該還得是5000,這就是事務的一致性。
隔離性--多個用戶併發訪問數據庫時,好比操做同一張表時,數據庫爲每個用戶開啓的事務,不能被其餘事務的操做所幹擾,多個併發事務之間要相互隔離.
持久性--一個事務一旦被提交了,那麼對數據庫中的數據的改變就是永久性的,即使是在數據庫系統遇到故障的狀況下也不會丟失提交事務的操做。
髒讀:事務B讀取事務A尚未提交的數據
不可重複讀:兩次事務讀的數據不一致
幻讀:事務A修改了數據,事務B也修改了數據,這時在事務A看來,明明修改了數據,昨不同,
隔離級別
① Serializable (串行化):可避免髒讀、不可重複讀、幻讀的發生。
② Repeatable read (可重複讀):可避免髒讀、不可重複讀的發生。
③ Read committed (讀已提交):可避免髒讀的發生。
④ Read uncommitted (讀未提交):最低級別,任何狀況都沒法保證。
Spring 框架前端
spring管理的bean在默認狀況下是會在服務器啓動的時候初始化的。
bean設置了scope爲prototype(原型)以後,會每次使用時生產一個
bean設置了lazy-init=」true」後,啓動服務器不會立刻實例化,而是在用到的時候被實例化
具體來講Spring是一個輕量級的容器,用於管理業務相關對象的。核心功能主要爲:IOC,AOP,MVC。
Spring 的基礎是ioc和 aop,ioc 提供了依賴注入的容器, aop解決了面向橫切面的編程
控制反轉IoC(Inversion of Control)
是說建立對象的控制權進行轉移,之前建立對象的主動權和建立時機是由本身把控的,而如今這種權力轉移到第三方,好比轉移交給了IoC容器,它就是一個專門用來建立對象的工廠,你要什麼對象,它就給你什麼對象,有了 IoC容器,依賴關係就變了,原先的依賴關係就沒了,它們都依賴IoC容器了,經過IoC容器來創建它們之間的關係,讓容器管理對象的生命週期如建立,初始化,銷燬等。
DI(依賴注入)其實就是IOC的另一種說法
Spring MVC提供了一種輕度耦合的方式來開發web應用。它是Spring的一個模塊,是一個web框架。經過Dispatcher Servlet, ModelAndView 和 View Resolver,開發web應用變得很容易
SpringBoot實現了自動配置,下降了項目搭建的複雜度。它主要是爲了解決使用Spring框架須要進行大量的配置太麻煩的問題,因此它並非用來替代Spring的解決方案,而是和Spring框架緊密結合用於提高Spring開發者體驗的工具
spring-colud是一種雲端分佈式架構解決方案,基於spring boot,在spring boot作較少的配置,即可成爲 spring cloud 中的一個微服務。
什麼是AOP?
面向切面編程(AOP)完善spring的依賴注入(DI),面向切面編程在spring中主要表現爲兩個方面
1.面向切面編程提供聲明式事務管理
2.spring支持用戶自定義的切面
Spring AOP的核心實現原理就是採用的動態代理,根據被代理對象是否實現了所要被代理的接口這個條件,動態代理會選擇不一樣的實現方案。
java中最多見的動態代理模式:jdk原生動態代理和cgLlb動態代理
JDK原生:不須要任何外部依賴,但只能基於接口進行代理,實現一個InvocationHandler,方法調用會被轉發到該類的invoke()方法,在須要使用對象實例的時候,經過JDK動態代理獲取實例的代理對象
cgLlb:經過繼承的方式實現,不管目標對象有沒有實現接口均可以代理,可是沒法處理final的狀況
其實最核心的仍是java的反射機制,經過獲取對象實例,調用對應的方法,前者經過接口來作橋樑,後者經過中間類轉發,都只是形式而已
面向切面編程(aop)是對面向對象編程(oop)的補充,
面向對象編程將程序分解成各個層次的對象,面向切面編程將程序運行過程分解成各個切面。
AOP從程序運行角度考慮程序的結構,提取業務處理過程的切面,oop是靜態的抽象,aop是動態的抽象,
是對應用執行過程當中的步驟進行抽象,,從而得到步驟之間的邏輯劃分。
aop框架具備的兩個特徵:
1.各個步驟之間的良好隔離性
2.源代碼無關性
SpringMVC工做流程
一、用戶發送請求至前端控制器DispatcherServlet
二、DispatcherServlet收到請求調用HandlerMapping處理器映射器。
三、處理器映射器找到具體的處理器,生成處理器對象及處理器攔截器(若是有則生成)一併返回給DispatcherServlet。
四、DispatcherServlet調用HandlerAdapter處理器適配器
五、HandlerAdapter通過適配調用具體的處理器(Controller,也叫後端控制器)。
六、Controller執行完成返回ModelAndView
七、HandlerAdapter將controller執行結果ModelAndView返回給DispatcherServlet
八、DispatcherServlet將ModelAndView傳給ViewReslover視圖解析器
九、ViewReslover解析後返回具體View
十、DispatcherServlet根據View進行渲染視圖(即將模型數據填充至視圖中)。
十一、DispatcherServlet響應用戶
簡單:系統啓動的時候根據配置文件建立spring的容器, 首先是發送http請求到核心控制器DispatcherServlet,spring容器經過映射器去尋找業務控制器,
使用適配器找到相應的業務類,在進業務類時進行數據封裝,在封裝前可能會涉及到類型轉換,執行完業務類後使用ModelAndView進行視圖轉發,
數據放在model中,用map傳遞數據進行頁面顯示。
值傳遞和引用傳遞的區別
值傳遞僅僅傳遞的是值。
引用傳遞,傳遞的是內存地址,修改後會改變內存地址對應儲存的值。
用數組來舉例就最清楚了,例如咱們定義一個數組a[]={1,2};那麼a[0]=1, a[1=2].
若是咱們把數組a裏的元素值做爲參數傳遞,實際上只是進行了值傳遞,對數組自己沒有影響
若是咱們把 數組a的指針做爲參數傳遞,那麼假如處理的函數就能夠直接修改數組a裏的值。
== 和equals區別?
當「==」運算符的兩個操做數都是包裝器類型的引用,則是比較執行的是不是同於個對象,而若是二者比較中有一個操做數是表達式(含運算符)則比較的是數值(會自動觸發拆箱的過程)
equals 用於判斷兩個變量是不是對同一個對象的引用
Session和Cookie的區別?
session是存放在服務器端的,cookie是存放在客戶端的,cookie的安全性不高,雖然它已經加了密,可是仍是能夠僞造的。
死鎖產生髮生:
線程死鎖是指因爲兩個或者多個線程互相持有對方所須要的資源,致使這些線程處於等待狀態,沒法前往執行。當線程進入對象的synchronized代碼塊時,便佔有了資源,直到它退出該代碼塊或者調用wait方法,才釋放資源,在此期間,其餘線程將不能進入該代碼塊。當線程互相持有對方所須要的資源時,會互相等待對方釋放資源,若是線程都不主動釋放所佔有的資源,將產生死鎖。
如何避免:
一、加鎖順序:
二、加鎖時限:
解決方案:簡單粗暴 找到進程號,kill 進程
String,StringBuffer和StringBuilder的區別
一、運行速度,或者說是執行速度,在這方面運行速度快慢爲:StringBuilder > StringBuffer > String。
二、線程安全上,StringBuilder是線程不安全的,而StringBuffer是線程安全的。
適用場景分析:
String:適用於少許的字符串操做的狀況
StringBuilder:適用於單線程下在字符緩衝區進行大量操做的狀況
StringBuffer:適用多線程下在字符緩衝區進行大量操做的狀況
mybatis如何處理結果集
MyBatis的結果集是經過反射來實現的
MyBatis裏面的核心處理類叫作SqlSession
MyBatis(IBatis)的好處是什麼
把sql語句從Java源程序中獨立出來,放在單獨的XML文件中編寫,給程序的維護帶來了很大便利。
封裝了底層JDBC API的調用細節,並能自動將結果集轉換成JavaBean對象,大大簡化了Java數據庫編程的重複工做
須要程序員本身去編寫sql語句,程序員能夠結合數據庫自身的特色靈活控制sql語句,更高的查詢效率
#{}與${}的區別
1. #將傳入的數據都當成一個字符串,會對自動傳入的數據加一個雙引號。如:order by #{user_id},若是傳入的值是111,那麼解析成sql時的值爲order by 「111」, 若是傳入的值是id,則解析成的sql爲order by 「id」.
2. $將傳入的數據直接顯示生成在sql中。如:order by ${user_id},若是傳入的值是111,那麼解析成sql時的值爲order by 111, 若是傳入的值是id,則解析成的sql爲order by id.
${}方式會引起SQL注入的問題、同時也會影響SQL語句的預編譯,因此從安全性和性能的角度出發,能使用#{}的狀況下就不要使用${}。
在mapper中如何傳遞多個參數
第一種:使用 @param 註解 第二種:多個參數封裝成map
分佈式鎖通常有三種實現方式:(樂觀鎖,本身實現,經過版本號 )
1. 數據庫樂觀鎖;2. 基於Redis的分佈式鎖;3. 基於ZooKeeper的分佈式鎖
首先,爲了確保分佈式鎖可用,咱們至少要確保鎖的實現同時知足如下四個條件:
互斥性。在任意時刻,只有一個客戶端能持有鎖。
不會發生死鎖。即便有一個客戶端在持有鎖的期間崩潰而沒有主動解鎖,也能保證後續其餘客戶端能加鎖。
具備容錯性。只要大部分的Redis節點正常運行,客戶端就能夠加鎖和解鎖。
解鈴還須繫鈴人。加鎖和解鎖必須是同一個客戶端,客戶端本身不能把別人加的鎖給解了。java
加鎖
1. 當前沒有鎖(key不存在),那麼就進行加鎖操做,並對鎖設置個有效期,同時value表示加鎖的客戶端。mysql
2. 已有鎖存在,不作任何操做。
解鎖
首先獲取鎖對應的value值,檢查是否與requestId相等,若是相等則刪除鎖(解鎖)
深刻探索SpringApplication執行流程
若是咱們使用的是SpringApplication的靜態run方法,那麼,這個方法裏面首先要建立一個SpringApplication對象實例,而後調用這個建立好的SpringApplication的實例方法。在SpringApplication實例初始化的時候,它會提早作幾件事情:
根據classpath裏面是否存在某個特徵類(org.springframework.web.context.ConfigurableWebApplicationContext)來決定是否應該建立一個爲Web應用使用的ApplicationContext類型。
使用SpringFactoriesLoader在應用的classpath中查找並加載全部可用的ApplicationContextInitializer。實現了這個接口的這些實例將在上下文初始化的時候prepareContext被使用。
使用SpringFactoriesLoader在應用的classpath中查找並加載全部可用的ApplicationListener。這個接口表示這個接口將監聽對應的ApplicationEvent事件
推斷並設置main方法的定義類。
Spring 框架中的單例 Beans 是線程安全的麼?
Spring 框架並無對單例 bean 進行任何多線程的封裝處理。關於單例 bean 的線程安全和並
發問題須要開發者自行去搞定。但實際上,大部分的 Spring bean 並無可變的狀態(好比
Serview類和DAO類),因此在某種程度上說Spring的單例bean是線程安全的。若是你的bean
有多種狀態的話(好比 View Model 對象),就須要自行保證線程安全。
最淺顯的解決辦法就是將多態 bean 的做用域由「singleton」變動爲「prototype」。
spring開發web 時要注意,默認Controller、Dao、Service都是單例的
@SpringBootApplication是一個複合註解,包括@ComponentScan,和@SpringBootConfiguration,@EnableAutoConfiguration。
@Autowired和@Resource(java原生)開啓基於註解的自動裝配
@Autowired是Spring的註解,@Resource是J2EE的註解
@Component是全部受Spring 管理組件的通用形式,@Component註解能夠放在類的頭上,@Component不推薦使用。
@Service對應的是業務層Bean
@Controller對應表現層的Bean
@RequestMapping 代表全部的請求路徑都要基於該路徑
Java集合類
(1)List 支持null元素和重複元素的動態擴容列表,jdk提供的實現類有:ArrayList, LinkedList, Stack,CopyOnWriteArrayList、Vector
(2)Set 不支持重複元素的動態擴容列表,jdk提供的實現類有:EnumSet, TreeSet, HashSet, LinkedHashSet、 NavigableSet、ConcurrentSkipListSet、CopyOnWriteArraySet
(3)map 是存儲鍵/值對的映射集,jdk提供的實現類有:HashMap, TreeMap,LinkedHashMap、ConcurrentHashMap、HashTable、ConcurrentSkipListMap
(4)queue/deque queue是在集合尾部添加元素,在頭部刪除元素的隊列,deque是可在頭部和尾部添加或者刪除元素的雙端隊列
List 線程不安全的子類:ArrayList, LinkedList,
ArrayList:是一個容量動態擴張的集合,實現了RandomAccess接口,支持隨機訪問,能夠經過List list = Collections.synchronizedList(new ArrayList(...))把它轉成線程安全的集合,固然只是封裝了對ArrayList的操做,保存同步而已,性能不是很高,全部的修改操做都要一個個同步。
LinkedList:內部是鏈表結果,非線程安全,添加元素的方法只是新增一個節點而後改變尾部節點和新增節點的引用連接,因此新增和刪除操做比較快,可是不支持隨機訪問,同時實現List和Deque接口,因此便可以當一個雙端隊列使用,也能夠當List使用
set 線程不安全的子類:EnumSet, TreeSet, HashSet, LinkedHashSet、 NavigableSet
treeSet是有序集合,內部經過TreeMap來存儲元素,把元素存儲在map的key裏,經過TreeMap存儲Key的有序性和無重複性來實現本身的有序性和Set的的元素無重複性
HashSet不是線程安全的
map 線程不安全的子類:HashMap, TreeMap,LinkedHashMap,鍵值對、鍵惟1、值不惟一
HashMap是線程不安全的提供全部Map操做的集合容器,支持Null爲key或者value,而且是無序的。nginx
HashMap是線程不安全的,不要在併發的環境中同時操做HashMap,建議使用ConcurrentHashMap。
jdk1.8後HashMap的存儲結構,由於和1.7以前都不太同樣,性能也不同。
jdk1.8以前,hashMap的存儲結構是數組+鏈表,也就是發生hash衝突後的元素後插入到鏈表裏,而不是存儲在數組,這樣的的話若是對於hash衝突比較嚴重的數據時,hashMap的查詢速度就不是o(1)了,而是o('n');
jdk1.8後,HashMap的存儲結構是數組+鏈表or平衡樹,由於平衡樹的時間複雜度是o(log('n')),是1.8後HashMap的查詢複雜度是O(1)~O(log('n' ))。
loadFactor是觸發HashMap擴容的負載因子,默認是0.75,擴容是很是耗時的事情,因此這個負載因子很重要,0.75是性能比較好的一個數
若是你常常會使用索引來對容器中的元素進行訪問,那麼 List 是你的正確的選擇。若是你已經知道索引了的話,那麼 List 的實現類好比 ArrayList 能夠提供更快速的訪問,若是常常添加刪除元素的,那麼確定要選擇LinkedList。
若是你想容器中的元素可以按照它們插入的次序進行有序存儲,那麼仍是 List,由於 List 是一個有序容器,它按照插入順序進行存儲。
若是你想保證插入元素的惟一性,也就是你不想有重複值的出現,那麼能夠選擇一個 Set 的實現類,好比 HashSet、LinkedHashSet 或者 TreeSet。全部 Set 的實現類都遵循了統一約束好比惟一性,並且還提供了額外的特性好比 TreeSet 仍是一個 SortedSet,全部存儲於 TreeSet 中的元素可使用 Java 裏的 Comparator 或者 Comparable 進行排序。LinkedHashSet 也按照元素的插入順序對它們進行存儲。
若是你以鍵和值的形式進行數據存儲那麼 Map 是你正確的選擇。你能夠根據你的後續須要從 Hashtable、HashMap、TreeMap 中進行選擇。
Comparable和Comparator區別比較
Comparable是排序接口,若一個類實現了Comparable接口,就意味着「該類支持排序」。而Comparator是比較器,咱們若須要控制某個類的次序,能夠創建一個「該類的比較器」來進行排序。
Comparable至關於「內部比較器」,而Comparator至關於「外部比較器」。
兩種方法各有優劣, 用Comparable 簡單, 只要實現Comparable 接口的對象直接就成爲一個能夠比較的對象,可是須要修改源代碼。 用Comparator 的好處是不須要修改源代碼, 而是另外實現一個比較器, 當某個自定義的對象須要做比較的時候,把比較器和對象一塊兒傳遞過去就能夠比大小了, 而且在Comparator 裏面用戶能夠本身實現複雜的能夠通用的邏輯,使其能夠匹配一些比較簡單的對象,那樣就能夠節省不少重複勞動了。
jdk1.8 lambam表達式
// 之前的循環方式
for (String player : players) {
System.out.print(player + "; ");
}
// 使用 lambda 表達式以及函數操做(functional operation)
players.forEach((player) -> System.out.print(player + "; "));
使用Lambdas排序集合
// 1.3 也能夠採用以下形式:
Arrays.sort(players, (String s1, String s2) -> (s1.compareTo(s2)));
readExcelList.stream().forEach(p->{ xxx });
java經過Stream對list集合分組
CompleteDtos.stream().collect(Collectors.groupingBy(CompleteRateDto::getIdKey)).values().forEach(p->{ xxx });
kafaka
Apache開發的一種發佈訂閱消息系統,它是一個分佈式的、分區的和重複的日誌服務。
nginx程序員
在正向代理中,Proxy和Client同屬於一個LAN(圖中方框內),隱藏了客戶端信息;web
在反向代理中,Proxy和Server同屬於一個LAN(圖中方框內),隱藏了服務端信息;redis
負載均衡調度算法:算法
weight輪詢(默認):接收到的請求按照順序逐一分配到不一樣的後端服務器,即便在使用過程當中,某一臺後端服務器宕機,Nginx會自動將該服務器剔除出隊列,請求受理狀況不會受到任何影響。spring
ip_hash:每一個請求按照發起客戶端的ip的hash結果進行匹配,這樣的算法下一個固定ip地址的客戶端總會訪問到同一個後端服務器
(1)保證內網的安全,一般將反向代理做爲公網訪問地址,Web服務器是內網
(2)負載均衡,經過反向代理服務器來優化網站的負載
Tomcat在高併發環境下處理動態請求時性能很低,而在處理靜態頁面更加脆弱,可是經過Nginx來處理靜態頁面要比經過Tomcat處理在性能方面好不少
Nginx能夠經過兩種方式來實現與Tomcat的耦合。
將靜態頁面請求交給Nginx,動態請求交給後端Tomcat處理。
將全部請求都交給後端的Tomcat服務器處理,同時利用Nginx自身的負載均衡功能,進行多臺Tomcat服務器的負載均衡。
Servlet程序是由WEB服務器調用,web服務器收到客戶端的Servlet訪問請求後:
①Web服務器首先檢查是否已經裝載並建立了該Servlet的實例對象。若是是,則直接執行第④步,不然,執行第②步。
②裝載並建立該Servlet的一個實例對象。
③調用Servlet實例對象的init()方法。
④建立一個用於封裝HTTP請求消息的HttpServletRequest對象和一個表明HTTP響應消息的HttpServletResponse對象,而後調用Servlet的service()方法並將請求和響應對象做爲參數傳遞進去。
⑤WEB應用程序被中止或從新啓動以前,Servlet引擎將卸載Servlet,並在卸載以前調用Servlet的destroy()方法。
Servlet是一個供其餘Java程序(Servlet引擎)調用的Java類,它不能獨立運行,它的運行徹底由Servlet引擎來控制和調度。
針對客戶端的屢次Servlet請求,一般狀況下,服務器只會建立一個Servlet實例對象,也就是說Servlet實例對象一旦建立,它就會駐留在內存中,爲後續的其它請求服務,直至web容器退出,servlet實例對象纔會銷燬。
ConcurentHashMap原理?
線程不安全的HashMap-- 由於多線程環境下,使用Hashmap進行put操做會引發死循環,致使CPU利用率接近100%,因此在併發狀況下不能使用HashMap。 底層數組+鏈表實現,線程不安全
效率低下的HashTable容器 -- HashTable容器使用synchronized來保證線程安全,但在線程競爭激烈的狀況下HashTable的效率很是低下。由於當一個線程訪問HashTable的同步方法時,其餘線程訪問HashTable的同步方法時,可能會進入阻塞或輪詢狀態
底層數組+鏈表實現 線程安全
ConcurrentHashMap --底層採用分段的數組+鏈表實現,線程安全,jdk 1.8後 變動爲table數組+單向鏈表+紅黑樹的結構,負載因子恆定爲0.75
經過把整個Map分爲N個Segment,能夠提供相同的線程安全,可是效率提高N倍,默認提高16倍。
鎖分段技術:首先將數據分紅一段一段的存儲,而後給每一段數據配一把鎖,當一個線程佔用鎖訪問其中一個段數據的時候,其餘段的數據也能被其餘線程訪問。
ConcurrentHashMap提供了與Hashtable和SynchronizedMap不一樣的鎖機制。Hashtable中採用的鎖機制是一次鎖住整個hash表,從而在同一時刻只能由一個線程對其進行操做;而ConcurrentHashMap中則是一次鎖住一個桶。
諸如get、put、remove等經常使用操做只鎖住當前須要用到的桶。這樣,原來只能一個線程進入,如今卻能同時有16個寫線程執行,併發性能的提高是顯而易見的
spring事務和jdbc事務的優缺點
Spring提供了對事務的聲明式事務管理,只須要在配置文件中作一些配置,便可把操做歸入到事務管理當中,解除了和代碼的耦合。
Spring聲明式事務管理,核心實現就是基於Aop。
Spring聲明式事務管理是粗粒度的事務控制,只能給整個方法應用事務,不能夠對方法的某幾行應用事務。
1.xml方式聲明事務 2.註解方式聲明事務
JDBC事務
JDBC的一切行爲包括事務是基於一個Connection
的,在JDBC中是經過Connection
對象進行事務管理。在JDBC中,經常使用的和事務相關的方法是: setAutoCommit
、commit
、rollback
等。
JDBC爲使用Java進行數據庫的事務操做提供了最基本的支持。經過JDBC事務,咱們能夠將多個SQL語句放到同一個事務中,保證其ACID特性。JDBC事務的主要優勢就是API比較簡單,能夠實現最基本的事務操做,性能也相對較好。
可是,JDBC事務有一個侷限:一個 JDBC 事務不能跨越多個數據庫
http原理
HTTP的工做過程
一次HTTP操做稱爲一個事務,其工做過程可分爲四步:
1)首先客戶機與服務器須要創建鏈接。只要單擊某個超級連接,HTTP的工做開始。
2)創建鏈接後,客戶機發送一個請求給服務器,請求方式的格式爲:統一資源標識符(URL)、協議版本號,後邊是MIME信息包括請求修飾符、客戶機信息和可能的內容。
3)服務器接到請求後,給予相應的響應信息,其格式爲一個狀態行,包括信息的協議版本號、一個成功或錯誤的代碼,後邊是MIME信息包括服務器信息、實體信息和可能的內容。
4)客戶端接收服務器所返回的信息經過瀏覽器顯示在用戶的顯示屏上,而後客戶機與服務器斷開鏈接。
若是在以上過程當中的某一步出現錯誤,那麼產生錯誤的信息將返回到客戶端,有顯示屏輸出。對於用戶來講,這些過程是由HTTP本身完成的,用戶只要用鼠標點擊,等待信息顯示就能夠了。
設計模式分哪幾種
整體來講設計模式分爲三大類:
建立型模式,共五種:工廠方法模式、抽象工廠模式、單例模式、建造者模式、原型模式。
結構型模式,共七種:適配器模式、裝飾器模式、代理模式、外觀模式、橋接模式、組合模式、享元模式。
行爲型模式,共十一種:策略模式、模板方法模式、觀察者模式、迭代子模式、責任鏈模式、命令模式、備忘錄模式、狀態模式、訪問者模式、中介者模式、解釋器模式。
Socket併發解決方案?
多線程同步實現?
synchronized和volatile的使用區別?
一旦一個共享變量(類的成員變量、類的靜態成員變量)被volatile修飾以後,那麼就具有了兩層語義:
1)保證了不一樣線程對這個變量進行操做時的可見性,即一個線程修改了某個變量的值,這新值對其餘線程來講是
當即可見的。
2)禁止進行指令重排序。
volatile本質是在告訴jvm當前變量在寄存器(工做內存)中的值是不肯定的,須要從主存中讀取;
synchronized則是鎖定當前變量,只有當前線程能夠訪問該變量,其餘線程被阻塞住。
1.volatile僅能使用在變量級別;
synchronized則可使用在變量、方法、和類級別的
2.volatile僅能實現變量的修改可見性,並不能保證原子性;
synchronized則能夠保證變量的修改可見性和原子性
3.volatile不會形成線程的阻塞;
synchronized可能會形成線程的阻塞。
mybatis和hibernate的優缺點
Hibernate的優勢:
一、hibernate是全自動,hibernate徹底能夠經過對象關係模型實現對數據庫的操做,擁有完整的JavaBean對象與數據庫的映射結構來自動生成sql。
二、數據庫移植性良好。
Hibernate的缺點:
一、學習門檻高,精通門檻更高,程序員如何設計O/R映射,在性能和對象模型之間如何取得平衡,以及怎樣用好Hibernate方面須要的經驗和能力都很強才行
二、hibernate的sql不少都是自動生成的,沒法直接維護sql;雖然有hql查詢,但功能仍是不及sql強大,見到報表等變態需求時,hql查詢要虛,也就是說hql查詢是有侷限的;hibernate雖然也支持原生sql查詢,但開發模式上卻與orm不一樣,須要轉換思惟,所以使用上有些不方便。總之寫sql的靈活度上hibernate不及mybatis。
Mybatis的優勢:
一、易於上手和掌握,提供了數據庫查詢的自動對象綁定功能,並且延續了很好的SQL使用經驗,對於沒有那麼高的對象模型要求的項目來講,至關完美。
二、sql寫在xml裏,便於統一管理和優化, 解除sql與程序代碼的耦合。
三、提供xml標籤,支持編寫動態sql。
四、速度相對於Hibernate的速度較快
Mybatis的缺點:
一、關聯表多時,字段多的時候,sql工做量很大。
二、sql依賴於數據庫,致使數據庫移植性差。
三、對象關係映射標籤和字段映射標籤僅僅是對映射關係的描述,具體實現仍然依賴於sql。
四、編寫動態sql時,不方便調試,尤爲邏輯複雜時。
java線程池有哪些?線程池的原理,什麼場景下不適用線程池
ThreadLocal的理解
向ThreadLocal裏面存東西就是向它裏面的Map存東西的,而後ThreadLocal把這個Map掛到當前的線程底下,這樣Map就僅僅屬於這個線程了。
mysql和oracle的區別
最重要的區別
MySQL是輕量型數據庫,而且免費,沒有服務恢復數據。
Oracle是重量型數據庫,收費,Oracle公司對Oracle數據庫有任何服務。
對事務的提交
MySQL默認是自動提交,而Oracle默認不自動提交,須要用戶手動提交,須要在寫commit;指令或者點擊commit按鈕
分頁查詢
MySQL是直接在SQL語句中寫"select... from ...where...limit x, y",有limit就能夠實現分頁;而Oracle則是須要用到僞列ROWNUM和嵌套查詢
JVM
類加載的幾個過程
加載、驗證、準備、解析、初始化。而後是使用和卸載了
堆裏面的分區:Eden,survival (from+ to),老年代,各自的特色?
堆裏面分爲新生代和老生代(java8取消了永久代,採用了Metaspace),新生代包含Eden+Survivor區,survivor區裏面分爲from和to區,內存回收時,若是用的是複製算法,從from複製到to,當通過一次或者屢次GC以後,存活下來的對象會被移動到老年區,當JVM內存不夠用的時候,會觸發Full GC,清理JVM老年區
當新生區滿了以後會觸發YGC,先把存活的對象放到其中一個Survice
區,而後進行垃圾清理。由於若是僅僅清理須要刪除的對象,這樣會致使內存碎
片,所以通常會把Eden 進行徹底的清理,而後整理內存。那麼下次GC 的時候,
就會使用下一個Survive,這樣循環使用。若是有特別大的對象,新生代放不下,
就會使用老年代的擔保,直接放到老年代裏面。由於JVM 認爲,通常大對象的存
活時間通常比較久遠。
容器
HashMap 底層實現。
HashMap的底層經過位桶實現,位桶裏面存的是鏈表(1.7之前)或者紅黑樹(有序,1.8開始) ,其實就是數組加鏈表(或者紅黑樹)的格式,經過判斷hashCode定位位桶中的下標,經過equals定位目標值在鏈表中的位置,,當添加一個元素(key-value)時,就首先計算元素key的hash值,以此肯定插入數組中的位置,可是可能存在同一hash值的元素已經被放在數組同一位置了,這時就添加到同一hash值的元素的後面,他們在數組的同一位置,可是造成了鏈表,同一各鏈表上的Hash值是相同的,因此說數組存放的是鏈表。而當鏈表長度太長時,鏈表就轉換爲紅黑樹,這樣大大提升了查找的效率。
當鏈表數組的容量超過初始容量的0.75時,再散列將鏈表數組擴大2倍,把原鏈表數組的搬移到新的數組中。
HasMap的擴容機制resize()?
構造hash表時,若是不指明初始大小,默認大小爲16(即Node數組大小16),若是Node[]數組中的元素達到(填充比*Node.length)從新調整HashMap大小 變爲原來2倍大小,擴容很耗時
何時擴容:當向容器添加元素的時候,會判斷當前容器的元素個數,若是大於等於閾值---即當前數組的長度乘以加載因子的值的時候,就要自動擴容啦。
擴容(resize)就是從新計算容量,向HashMap對象裏不停的添加元素,而HashMap對象內部的數組沒法裝載更多的元素時,對象就須要擴大數組的長度,以便能裝入更多的元素。方法是使用一個新的數組代替已有的容量小的數組,就像咱們用一個小桶裝水,若是想裝更多的水,就得換大水桶。
Linux系統查看當前運行java的進程?
在Linux下查看全部java進程命令:ps -ef | grep java
中止特定java進程命令:kill -9 java進程序號
中止全部java進程命令:pkill - 9 java
HashSet類是如何實現添加元素保證不重複的?---哈希碼的原理
當你利用HashSet建立一個對象時,在HashSet的構造方法中,先用hashCode方法計算出該對象的哈希碼。
比較順序以及原理
(1).若是該對象哈希碼與集合已存在對象的哈希碼不一致,則該對象沒有與其餘對象重複,添加到集合中!
(2).若是存在於該對象相同的哈希碼,那麼經過equals方法判斷兩個哈希碼相同的對象是否爲同一對象(判斷的標準是:屬性是否相同)
1>.相同對象,不添加!
2>.不一樣對象,添加!
final finally finalize區別
一、final修飾符(關鍵字)。被final修飾的類,就意味着不能再派生出新的子類,不能做爲父類而被子類繼承
二、finally是在異常處理時提供finally塊來執行任何清除操做。無論有沒有異常被拋出、捕獲,finally塊都會被執行
三、finalize是方法名。在垃圾收集器刪除對象以前對這個對象調用的,將對象從內存中清除出去以前作必要的清理工做。
一 反射機制的概念:
指在運行狀態中,對於任意一個類,都可以知道這個類的全部屬性和方法,對於任意一個對象,都能調用它的任意一個方法.這種動態獲取信息,以及動態調用對象方法的功能叫java語言的反射機制.
二 反射機制的應用:
生成動態代理,面向切片編程(在調用方法的先後各加棧幀).
三 反射機制的原理:
1 首先明確的概念: 一切皆對象----類也是對象.
2 而後知道類中的內容 :modifier constructor field method.
3 其次明白加載: 當Animal.class在硬盤中時,是一個文件,當載入到內存中,能夠認爲是一個對象,是java.lang.class的對象.
Hash衝突?
因爲哈希算法被計算的數據是無限的,而計算後的結果範圍有限,所以總會存在不一樣的數據通過計算後獲得的值相同,這就是哈希衝突
Spring框架分爲哪七大模塊以及各模塊的主要功能做用?
1. Spring Core: Core封裝包是框架的最基礎部分,提供IOC和依賴注入特性。這裏的基礎概念是BeanFactory,它提供對Factory模式的經典實現來消除對程序性單例模式的須要,並真正地容許你從程序邏輯中分離出依賴關係和配置。2.Spring Context: 構建於Core封裝包基礎上的 Context封裝包,提供了一種框架式的對象訪問方法,有些象JNDI註冊器。Context封裝包的特性得自於Beans封裝包,並添加了對國際化(I18N)的支持(例如資源綁定),事件傳播,資源裝載的方式和Context的透明建立,好比說經過Servlet容器。3.Spring DAO: DAO (Data Access Object)提供了JDBC的抽象層,它可消除冗長的JDBC編碼和解析數據庫廠商特有的錯誤代碼。 而且,JDBC封裝包還提供了一種比編程性更好的聲明性事務管理方法,不只僅是實現了特定接口,並且對全部的POJOs(plain old Java objects)都適用。4.Spring ORM: ORM 封裝包提供了經常使用的「對象/關係」映射APIs的集成層。 其中包括JPA、JDO、Hibernate 和 iBatis 。利用ORM封裝包,能夠混合使用全部Spring提供的特性進行「對象/關係」映射,如前邊提到的簡單聲明性事務管理。5.Spring AOP: Spring的 AOP 封裝包提供了符合AOP Alliance規範的面向方面的編程實現,讓你能夠定義,例如方法攔截器(method-interceptors)和切點(pointcuts),從邏輯上講,從而減弱代碼的功能耦合,清晰的被分離開。並且,利用source-level的元數據功能,還能夠將各類行爲信息合併到你的代碼中。6.Spring Web: Spring中的 Web 包提供了基礎的針對Web開發的集成特性,例如多方文件上傳,利用Servlet listeners進行IOC容器初始化和針對Web的ApplicationContext。當與WebWork或Struts一塊兒使用Spring時,這個包使Spring可與其餘框架結合。7.Spring Web MVC: Spring中的MVC封裝包提供了Web應用的Model-View-Controller(MVC)實現。Spring的MVC框架並非僅僅提供一種傳統的實現,它提供了一種清晰的分離模型,在領域模型代碼和Web Form之間。而且,還能夠藉助Spring框架的其餘特性。