-- **************************************************************************************************css
-- ************************************* 兩年程序員知識 begin****************************************html
-- **************************************************************************************************前端
spring特性:java
1,方便解耦,簡化開發 經過Spring提供的IoC容器,咱們能夠將對象之間的依賴關係交由Spring進行控制,避免硬編碼所形成的過分程序耦合。有了Spring,用戶沒必要再爲單實例模式類、mysql
屬性文件解析等這些很底層的需求編寫代碼,能夠更專一於上層的應用。jquery
2,AOP編程的支持 經過Spring提供的AOP功能,方便進行面向切面的編程,許多不容易用傳統OOP實現的功能能夠經過AOP輕鬆應付。程序員
事務經過配置文件配置1.事務管理器web
2.配置通知 引入事務管理器 tx:attibutes配置事務屬性 method 是否只讀事務傳播行爲面試
3.配置切面 切入點表達式 通知引入切點ajax
註解事務 1.配置事務管理器
2.事務的註解掃描 引入 事務管理器
3,聲明式事務的支持 在Spring中,經過聲明式方式靈活地進行事務的管理,提升開發效率和質量。
4,方便程序的測試整合Junit 只要在方法加@Test註解 能夠用非容器依賴的編程方式進行幾乎全部的測試工做,在Spring裏,測試再也不是昂貴的操做,而是隨手可作的事情。
5,方便集成各類優秀框架 Spring不排斥各類優秀的開源框架,相反,Spring能夠下降各類框架的使用難度,Spring提供了對各類優秀框架(如Struts,Hibernate、Hession、Quartz)等的直接支持。
6,下降Java EE API的使用難度 Spring對不少難用的Java EE API(如JDBC,JavaMail,遠程調用等)提供了一個薄薄的封裝層,經過Spring的簡易封裝,這些Java EE API的使用難度大爲下降。
7,Java 源碼是經典學習範例 Spring的源碼設計精妙、結構清晰、匠心獨用,到處體現着大師對Java設計模式靈活運用以及對Java技術的高深造詣。Spring框架源碼無疑是Java技術的最佳實踐範例。
若是想在短期內迅速提升本身的Java技術水平和應用開發水平,學習和研究Spring源碼將會使你收到意想不到的效果。
對Spring aop的理解
AOP,也就是面向切面編程,我是這麼理解的:學java的應該都知道面向對象編程(oop),而OOP是從靜態解讀考慮程序結構,但AOP是從動態角度考慮程序運行過程。
也能夠說AOP是OOP的補充和完善。OOP引入了封裝、繼承和多態性等概念來創建一種對象層次結構, 用以模擬公共的一個集合。當咱們須要爲分散的對象引入公共行爲的時候,
則OOP顯得無能爲力了。也就是說,OOP容許你定義從上到下的關係,但並不適合從左到右的關係,例如日誌功能。日誌代碼每每水平的散步在全部對象層次中,
而與它所散步到的對象的核心功能毫無關係。對於其餘類型的代碼,如安全性、異常處理和透明的持續性也是如此。這種散佈在各處的無關的代碼被稱爲橫切代碼,
在oop設計中,他致使了大量代碼的重複,而不利於各個模塊的重用。
而AOP技術則偏偏相反,它利用一種稱爲「橫切」的技術,剖解開封裝的對象內部,並將哪些影響了多個類的公共行爲封裝到一個可重用模塊,簡單的來講就是將那些與業務無關,
卻爲業務模塊所共同調用的邏輯或責任封裝起來。便於減小系統的重複代碼,下降模塊間的耦合度等。
aop 底層有兩種代理(jdk代理,CGLIB代理):
java動態代理是利用反射機制生成一個實現代理接口的匿名類,在調用具體方法前調用InvokeHandler來處理。
cglib代理,是針對類來實現代理的,他的原理是對指定的目標類生成一個子類,並覆蓋其中方法實現加強,但由於採用的是繼承,因此不能對final修飾的類進行代理。(例如service的事務處理)
對Spring IOC的理解
IoC(控制反轉),將類的建立和依賴關係寫在配置文件裏,由配置文件注入,實現了鬆耦合
IOC 底層實現原理:JAVA反射
經過Bean標籤的 class屬性 經過類的全路徑名經過反射建立對象
springmvc的運行流程,實現原理?
執行流程:
1). 若一個請求匹配 DispatcherServlet 的請求映射路徑(在 web.xml 中指定), WEB 容器將該請求轉交給 DispatcherServlet 處理
2). DispatcherServlet 接收到請求後, 將根據請求信息(包括 URL、HTTP 方法、請求 頭、請求參數、Cookie 等)及 HandlerMapping 的配置找處處理請求的處理器(Handler). 可將 HandlerMapping 當作路由控制器,將 Handler 當作目標主機。
3). 當 DispatcherServlet 根據 HandlerMapping 獲得對應當前請求的 Handler 後, 經過 HandlerAdapter 對 Handler 進行封裝,再以統一的適配器接口調用 Handler。
4). 處理器完成業務邏輯的處理後將返回一個 ModelAndView 給 DispatcherServlet, ModelAndView 包含了視圖邏輯名和模型數據信息
5). DispatcherServlet 藉助 ViewResoler 完成邏輯視圖名到真實視圖對象的解析
6). 得 到 真 實 視 圖 對 象 View 後 , DispatcherServlet 使用這個 View 對 ModelAndView 中的模型數據進行視圖渲染
實現原理:
基於servlet實現,一樣流行的mvc框架還有struts2,二者區別是:
1,SpringMVC的入口是servlet,而Struts2是filter(filter執行順序 > serlvet)
2,spring會稍微比struts快。 spring mvc是基於方法的設計 ,而sturts是基於類 ,每次發一次請求都會實例一個action,每一個action都會被注入屬性,而spring基於方法,
粒度更細,但要當心把握像在servlet控制數據同樣。spring3mvc是方法級別的攔截,攔截到方法後根據參數上的註解,把request數據注入進去,在spring3mvc中,一個方法對應一個request上下文,
因此說從架構自己上SpringMVC就容易實現restful,且SpringMVC執行和開發效率都應該是高於Struts2的。
來講說你認爲寫過的最複雜的業務邏輯吧;
這個嘛,我認爲目前認爲,我沒有寫過任何複雜的業務邏輯,任何複雜的業務邏輯,細化拆分都是有簡單的業務組成,若是你很想聽的話,
那我就以登陸爲例給你說說吧
1,首先,判斷用戶是否存在,若不存在,返回前端帳戶不存在信息(json形式),不然執行下一步;
2,判斷輸入密碼是否錯誤,若是錯誤,返回前端密碼錯誤,用戶密碼錯誤次數加一,若大於指定次數,鎖定該用戶,不然執行下一步;
3,判斷用戶是否首次登陸,如果,跳轉指定頁面,強制修改密碼,修改完畢以後,從新登陸便可,不然進入下一步;
4,判斷用戶上次登陸時間,若是超過指定時間,跳轉強制修改頁面,不然進入下一步;
5,判斷用戶上次修改密碼時間,若是超過指定時間,跳轉強制修改頁面,不然進入下一步;
6,初始化一些信息(受權,基礎信息保存【字典信息】等),放入session,修改上次用戶登陸時間,
7,返回成功登陸頁面
-- *************************************兩年以上程序員 end****************************************
-- **************************************************************************************************
-- *************************************三年以上程序員 begin****************************************
-- **************************************************************************************************
深刻分析ClassLoader
先說說爲何要知道java的類加載機制。我的認爲主要有如下幾個緣由:
按需加載。JVM啓動時不能肯定我要加載哪些東西,或者有些類很是大,我只但願用到它時再加載,並不是一次性加載全部的class,因此這時候瞭解了加載機制就能夠按需加載了。
類隔離。好比web容器中部署多個應用,應用之間互相可能會有衝突,因此但願儘可能隔離,這裏可能就要分析各個應用加載的資源和加載順序之間的衝突,針對這些衝突再本身定些規則,
讓它們可以愉快地玩耍。
資源回收。若是你不瞭解java是如何加載資源的,又怎麼理解java是如何回收資源的?
通常說到java的類加載機制,都要說到「雙親委派模型」(其實我的很不理解爲何叫「雙親」,其實英文叫「parent」)。使用這種機制,能夠避免重複加載,當父親已經加載了該類的時候,
就沒有必要子ClassLoader再加載一次。若是讓子類先加載 子類加載的時候默認調用父類加載器也加載JVM根據 類名+包名+ClassLoader實例ID 來斷定兩個類是否相同,是否已經加載過(因此這裏能夠略微擴展下,能夠經過建立不一樣的classloader實例
來實現類的熱部署)。
a) BootStrapClassLoader。它是最頂層的類加載器,是由C++編寫而成, 已經內嵌到JVM中了。在JVM啓動時會初始化該ClassLoader,它主要用來讀取Java的核心類庫JRE/lib/rt.jar中全部的class文件,這個jar文件中包含了java規範定義的全部接口及實現。
b) ExtensionClassLoader。它是用來讀取Java的一些擴展類庫,如讀取JRE/lib/ext/*.jar中的包等(這裏要注意,有些版本的是沒有ext這個目錄的)。
c) AppClassLoader。它是用來讀取CLASSPATH下指定的全部jar包或目錄的類文件,通常狀況下這個就是程序中默認的類加載器。
d) CustomClassLoader。它是用戶自定義編寫的,它用來讀取指定類文件 。基於自定義的ClassLoader可用於加載非Classpath中(如從網絡上下載的jar或二進制)的jar及目錄、還能夠在加載前
對class文件優一些動做,如解密、編碼等。
不少資料和文章裏說,ExtClassLoader的父類加載器是BootStrapClassLoader,其實這裏省掉了一句話,容易形成不少新手(好比我)的迷惑。嚴格來講,ExtClassLoader的父類加載器是null,
只不過在默認的ClassLoader 的 loadClass 方法中,當parent爲null時,是交給BootStrapClassLoader來處理的,並且ExtClassLoader 沒有重寫默認的loadClass方法,因此,
ExtClassLoader也會調用BootStrapLoader類加載器來加載,這就致使「BootStrapClassLoader具有了ExtClassLoader父類加載器的功能」
查看classloader的源碼能夠發現三個重要的方法:
a) loadClass。classloader加載類的入口,此方法負責加載指定名字的類,ClassLoader的實現方法爲先從已經加載的類中尋找,如沒有則繼續從父ClassLoader中尋找,
如仍然沒找到,則從BootstrapClassLoader中尋找,最後再調用findClass方法來尋找,如要改變類的加載順序,則可覆蓋此方法,如加載順序相同,則可經過覆蓋findClass來作特殊的處理,
例如解密、固定路徑尋找等,當經過整個尋找類的過程仍然未獲取到Class對象時,則拋出ClassNotFoundException。如類須要 ,則調用resolveClass進行連接。
b) findClass。此方法直接拋出ClassNotFoundException,所以須要經過覆蓋loadClass或此方法來以自定義的方式加載相應的類。
C) defineClass。此方法負責將二進制的字節碼轉換爲Class對象,這個方法對於自定義加載類而言很是重要,如二進制的字節碼的格式不符合JVM Class文件的格式,拋出ClassFormatError;如須要生成的類名和二進制字節碼中的不一樣,則拋出NoClassDefFoundError;如須要加載的class是受保護的、採用不一樣簽名的或類名是以java.開頭的,則拋出SecurityException;如需加載的class在此ClassLoader中已加載,則拋出LinkageError。
類的加載的過程
一個java文件從被加載到被卸載這個生命過程
加載->連接(驗證+準備+解析)->初始化(使用前的準備)->使用->卸載
類的加載全過程
加載->驗證->準備->解析->初始化
1,首先是加載:
這一塊虛擬機要完成3件事:
1.經過一個類的全限定名來獲取定義此類的二進制字節流。
2.將這個字節流所表明的靜態存儲結構轉化爲方法區的運行時數據結構。
3.在java堆中生成一個表明這個類的java.lang.Class對象,做爲方法區這些數據的訪問入口。
關於第一點,很靈活,不少技術都是在這裏切入,由於它並無限定二進制流從哪裏來:
從class文件來->通常的文件加載
從zip包中來->加載jar中的類
從網絡中來->Applet
2,加載完成後就要開始對那些字節流進行檢驗
檢驗的目的:確保class文件的字節流信息符合jvm的口味,不會讓jvm感到不舒服。
檢驗主要經歷幾個步驟:文件格式驗證->元數據驗證->字節碼驗證->符號引用驗證
文件格式驗證:驗證字節流是否符合Class文件格式的規範並驗證其版本是否能被當前的jvm版本所處理。
ok沒問題後,字節流就能夠進入內存的方法區進行保存了。後面的3個校驗都是在方法區進行的。
元數據驗證:對字節碼描述的信息進行語義化分析,保證其描述的內容符合java語言的語法規範。
字節碼檢驗:校驗java編譯成的字節碼文件是否破損或格式錯誤
符號引用驗證:來驗證一些引用的真實性與可行性,好比代碼裏面引了其餘類,這裏就要去檢測一下那些來到底是否存在;
或者說代碼中訪問了其餘類的一些屬性,這裏就對那些屬性的可訪問性進行檢驗。(這一步將爲後面的解析工做打下基礎)
3,接着就上面步驟完成後,就會進入準備階段了:
這階段會爲類變量(指那些靜態變量)分配內存並設置初始值的階段,這些內存在方法區中進行分配。這裏不包含用final修飾的static,由於final在編譯的時候就會分配了
4,完成上步後,就要進行解析了。解析好像是對類的字段,方法等東西進行轉換,具體涉及到Class文件的格式內容,並沒深刻去了解。
5,在前面的類加載過程當中,除了在加載階段用戶能夠經過自定義類加載器參與以外,其餘的動做徹底有jvm主導,到了初始化這塊,纔開始真正執行java裏面的代碼。
這一步將會執行一些預操做,注意區分在準備階段,已經爲類變量執行過一次系統賦值了。
其實說白了,這一步就是執行程序的構造器
GC:
垃圾檢測方式:
引用計數法:給一個對象添加引用計數器,每當有個地方引用它,計數器就加1;引用失效就減1。
好了,問題來了,若是我有兩個對象A和B,互相引用,除此以外,沒有其餘任何對象引用它們,實際上這兩個對象已經沒法訪問,便是咱們說的垃圾對象。可是互相引用,
計數不爲0,致使沒法回收,因此還有另外一種方法:
可達性分析算法:以根集對象爲起始點進行搜索,若是有對象不可達的話,便是垃圾對象。這裏的根集通常包括java棧中引用的對象、方法區常良池中引用的對象本地方法中引用的對象等。
總之,JVM在作垃圾回收的時候,會檢查堆中的全部對象是否會被這些根集對象引用,不可以被引用的對象就會被垃圾收集器回收。
回收算法:
1.標記-清除(Mark-sweep)
說明:算法和名字同樣,分爲兩個階段:標記和清除。標記全部須要回收的對象,而後統一回收。這是最基礎的算法,後續的收集算法都是基於這個算法擴展的。
不足:效率低;標記清除以後會產生大量碎片
2.複製(Copying)
說明:此算法把內存空間劃爲兩個相等的區域,每次只使用其中一個區域。垃圾回收時,遍歷當前使用區域,把正在使用中的對象複製到另一個區域中。此算法每次只處理正在使用中的對象,所以複製成本比較小,同時複製過去之後還能進行相應的內存整理,不會出現「碎片」問題。
缺點:就是須要兩倍內存空間
3.標記-整理(Mark-Compact)
說明:此算法結合了「標記-清除」和「複製」兩個算法的優勢。也是分兩階段,第一階段從根節點開始標記全部被引用對象,第二階段遍歷整個堆,把清除未標記對象而且把存活對象「壓縮」到堆的其中一塊,按順序排放。此算法避免了「標記-清除」的碎片問題,同時也避免了「複製」算法的空間問題
缺點:
4.分代收集算法
說明:
這是當前商業虛擬機經常使用的垃圾收集算法。分代的垃圾回收策略,是基於這樣一個事實:不一樣的對象的生命週期是不同的。所以,不一樣生命週期的對象能夠採起不一樣的收集方式,以便提升回收效率。
爲何要運用分代垃圾回收策略?
在java程序運行的過程當中,會產生大量的對象,因每一個對象所能承擔的職責不一樣所具備的功能不一樣因此也有着不同的生命週期,有的對象生命週期較長,好比Http請求中的Session對象,
線程,Socket鏈接等;有的對象生命週期較短,好比String對象,因爲其不變類的特性,有的在使用一次後便可回收。試想,在不進行對象存活時間區分的狀況下,每次垃圾回收都是對整
個堆空間進行回收,那麼消耗的時間相對會很長,並且對於存活時間較長的對象進行的掃描工做等都是徒勞。所以就須要引入分治的思想,所謂分治的思想就是因地制宜,將對象進行代的
劃分,把不一樣生命週期的對象放在不一樣的代上使用不一樣的垃圾回收方式。
如何劃分?
將對象按其生命週期的不一樣劃分紅:年輕代(Young Generation)、年老代(Old Generation)、持久代(Permanent Generation)。其中持久代主要存放的是類信息,因此與java對象的回收關
系不大,與回收息息相關的是年輕代和年老代。這裏有個比喻很形象
「假設你是一個普通的 Java 對象,你出生在 Eden 區,在 Eden 區有許多和你差很少的小兄弟、小姐妹,能夠把 Eden 區當成幼兒園,在這個幼兒園裏你們玩了很長時間。
Eden 區不能無休止地放大家在裏面,因此當年紀稍大,你就要被送到學校去上學,這裏假設從小學到高中都稱爲 Survivor 區。開始的時候你在 Survivor 區裏面劃分出來
的的「From」區,讀到高年級了,就進了 Survivor 區的「To」區,中間因爲學習成績不穩定,還常常來回折騰。直到你 18 歲的時候,高中畢業了,該去社會上闖闖了。因而你
就去了年老代,年老代裏面人也不少。在年老代裏,你生活了 20 年 (每次 GC 加一歲),最後壽終正寢,被 GC 回收。有一點沒有提,你在年老代遇到了一個同窗,他的名
字叫愛德華 (慕光之城裏的帥哥吸血鬼),他以及他的家族永遠不會死,那麼他們就生活在永生代。」
年輕代:是全部新對象產生的地方。年輕代被分爲3個部分——Enden區和兩個Survivor區(From和to)當Eden區被對象填滿時,就會執行Minor GC。並把全部存活下來的對象轉移到其中
一個survivor區(假設爲from區)。Minor GC一樣會檢查存活下來的對象,並把它們轉移到另外一個survivor區(假設爲to區)。這樣在一段時間內,總會有一個空的survivor區。
通過屢次GC週期後,仍然存活下來的對象會被轉移到年老代內存空間。一般這是在年輕代有資格提高到年老代前經過設定年齡閾值來完成的。須要注意,Survivor的兩個區是
對稱的,沒前後關係,from和to是相對的。涉及了複製算法
年老代:在年輕代中經歷了N次回收後仍然沒有被清除的對象,就會被放到年老代中,能夠說他們都是久經沙場而不亡的一代,都是生命週期較長的對象。對於年老代和永久代,就不能再採用
像年輕代中那樣搬移騰挪的回收算法,由於那些對於這些回收戰場上的老兵來講是小兒科。一般會在老年代內存被佔滿時將會觸發Full GC,回收整個堆內存。涉及了「標記-整理(Mark-Sweep)」的算法。
持久代:用於存放靜態文件,好比java類、方法等。持久代對垃圾回收沒有顯著的影響。
-- *************************************三年以上程序員 end****************************************
-- **************************************************************************************************
-- *************************************五年以上程序員 begin****************************************
-- **************************************************************************************************
簡要說明oracle數據庫是如何執行SQL語句的。
1、 基本階段
當用戶執行SQL語句(這裏主要值數據操縱語言DML)時,經過鏈接,先將該語句發送到oracle服務器,再由服務器進程處理該語句。
服務器進程處理SQL語句的基本階段是:解析、執行、返回結果。
1、解析(perse)
解析指檢查SQL語句的語法和語義,生成SQL語句的執行計劃,並將SQL語句和執行計劃存放到SGA區的共享SQL區中。
在解析期間服務器進程會執行以下操做:
1)搜索SGA區的共享SQL區,檢查其中是否存在相同的SQL語句及其執行計劃。若是有,則直接執行該SQL語句。這樣可以提升oracle的性能
若是沒有該SQL語句,就檢查該SQL的語法。若是語法不正確,就將語法錯誤消息返回給客戶機
2)若是語法正確,就經過查詢數據字典,檢查該SQL語句的語義,以肯定表名、列名是否正確。若是表名和列名不正確,就將語義錯誤消息返回給客戶機
3)若是語義正確,就給相應的對象加解析鎖,以防止在解析期間其餘用戶改變這些對象的結構(或刪除這些對象)
4)檢查用戶是否具備訪問相應對象的相應權限。若是沒有相應權限,就將權限不夠錯誤消息返回給客戶機,若是具備相應的權限,
就由SQL語句的優化器來肯定該SQL語句的最佳執行計劃,爲該SQL語句在SGA區的共享SQL區中分配空間,將該SQL語句及其執行計劃裝入其中,以便執行
2、 執行(execute)
執行指服務器進程按照SQL語句的執行計劃執行SQL語句。在此期間,服務器進程執行以下操做:
1,肯定被操縱對象的數據所在的數據塊是否已經被讀取到SGA區的數據高速緩存區中了。若是數據塊在數據高速緩存中,則直接在其中操做
2,若是數據塊不在數據高速緩存中,則從數據文件所對應的物理存儲設備中讀取該數據塊,並在數據高速緩存中尋找空閒數據塊,將讀入的數據放入
3,對於update和delete語句,將須要修改或刪除的行鎖住,以便在事務結束以前相同的行不會被其餘進程修改。對於select和insert語句,由於不會修改數據,因此不須要鎖住行。
3、 返回結果
對於select語句,在執行階段,要將查詢到的結果(或被標示的行)返回給用戶進程。加入查詢結果須要排序,還要利用共享池的排序區,甚至臨時表空間的臨時段來排序。查詢結果老是以列表格式顯示。根據查詢結果的大小不一樣,能夠一次所有返回,也能夠分屢次逐步返回。對於其餘DML語句,將執行是否成功等狀態細心返回給用戶進程。
-- *************************************五年以上程序員 end****************************************
-- **************************************************************************************************
-- *************************************必問問題 begin****************************************
-- **************************************************************************************************
說說你最近有什麼計劃吧;
這個嘛,是一個不錯的問題啊,我呢,是搞技術的,也只想在技術方向走向輝煌;爲此呢,我專門作了一些準備:
1,一直呢,據說spring是java程序員學習的典範,最想研究一下spring,Spring是於2003 年興起的一個輕量級的Java 開發框架,它可以活到如今而沒有被時間所打死,這足以證實它有足夠的魅力誘惑那一羣飢渴難耐的程序員,終於呢,我這個一貫清高的小哥也淪陷了;其源碼設計的精妙,結構清晰,及java設計模式的靈活運用,
以及對java技術的高深造詣,都是我學習的典範,其IOC主從關係的轉變,讓我想到好萊塢的一句話,「別找咱們,咱們會找你的,你等着哈」,若是不是spring,也許我還在陷入永無止境的new Objec()的苦海深淵中
2,我還買了一些其餘的書籍,mysql的從入門到精通,不要問我做者是誰,我看書歷來不問出處,也懶的看,日常看到很無聊的電視節目的時候,我遙控器都懶得拿,sql基本程序員必備技能,可是如何快速寫出高效的sql是一個值得學習的問題
3,學完這些,大概也過了小半年了吧,接下來幹什麼呢,唉喲,這就是個問題了,sql學習了,spring研究的差很少了,本身該寫點東西,練練手了吧,光看不練,來裝逼的嗎?
4,練習以後,該幹嗎了啊,嗯,分佈式,緩存,事多着呢,沒幾年,估計也別想再技術上面有什麼發展,提什麼走向輝煌,恩哼
說說你遇到的問題:
1, 問題描述:
短信驗證碼被別人惡意刷,當時咱們這個東西,加的是有驗證碼的,且後端對手機號格式,發送頻率都有校驗(每分鐘最多六次),
可是仍是出現了被惡意刷的問題,幾個小時,兩千塊的短信費就沒了,查看後臺才知道,手機號沒有重複的
解決方案:
原來也考慮過 判斷 手機 mac ip,在實施過程當中,才知道手機上網是隨機分配網絡地址的,是沒有固定的IP的,
因而採用了另外一種方案,數據加密,數據組包組完之後 對數據加密 而後再組包,至關於 多了一層,而後就沒有問題了
你還有想問的嗎?
1,公司如今作什麼業務?進展到哪裏了?
2,福利待遇?
3,公司人員怎麼分配的,幾個前端,幾個後臺?
-- *************************************必問問題 end****************************************
-- **************************************************************************************************
-- *************************************常問問題 begin****************************************
-- **************************************************************************************************
索引建設原則:
1、索引應該常常建在Where 子句常常用到的列上。若是某個大表常用某個字段進行查詢,而且檢索行數小於總錶行數的5%。則應該考慮。
2、對於兩錶鏈接的字段,應該創建索引。若是常常在某表的一個字段進行Order By 則也通過進行索引。
3、不該該在小表上建設索引。
Sql 優化:
當Oracle數據庫拿到SQL語句時,其會根據查詢優化器分析該語句,並根據分析結果生成查詢執行計劃。
也就是說,數據庫是執行的查詢計劃,而不是Sql語句。
查詢優化器有rule-based-optimizer(基於規則的查詢優化器) 和Cost-Based-optimizer(基於成本的查詢優化器)。
其中基於規則的查詢優化器在10g版本中消失。
對於規則查詢,其最後查詢的是全表掃描。而CBO則會根據統計信息進行最後的選擇。
1、先執行From ->Where ->Group By->Order By
2、執行From 字句是從右往左進行執行。所以必須選擇記錄條數最少的表放在右邊。這是爲何呢?
3、對於Where字句其執行順序是從後向前執行、所以能夠過濾最大數量記錄的條件必須寫在Where子句的末尾,而對於多表之間的鏈接,則寫在以前。
由於這樣進行鏈接時,能夠去掉大多不重複的項。
4. SELECT子句中避免使用(*)ORACLE在解析的過程當中, 會將’*’ 依次轉換成全部的列名, 這個工做是經過查詢數據字典完成的, 這意味着將耗費更多的時間
5、索引失效的狀況:
① Not Null/Null 若是某列創建索引,當進行Select * from emp where depto is not null/is null。 則會是索引失效。
② 索引列上不要使用函數,SELECT Col FROM tbl WHERE substr(name ,1 ,3 ) = 'ABC'
或者SELECT Col FROM tbl WHERE name LIKE '%ABC%' 而SELECT Col FROM tbl WHERE name LIKE 'ABC%' 會使用索引。
③ 索引列上不能進行計算SELECT Col FROM tbl WHERE col / 10 > 10 則會使索引失效,應該改爲
SELECT Col FROM tbl WHERE col > 10 * 10
④ 索引列上不要使用NOT ( != 、 <> )如:SELECT Col FROM tbl WHERE col ! = 10
應該 改爲:SELECT Col FROM tbl WHERE col > 10 OR col < 10 。
6、用UNION替換OR(適用於索引列)
union:是將兩個查詢的結果集進行追加在一塊兒,它不會引發列的變化。 因爲是追加操做,須要兩個結果集的列數應該是相關的,
而且相應列的數據類型也應該至關的。union 返回兩個結果集,同時將兩個結果集重複的項進行消除。 若是不進行消除,用UNOIN ALL.
一般狀況下, 用UNION替換WHERE子句中的OR將會起到較好的效果. 對索引列使用OR將形成全表掃描. 注意, 以上規則只針對多個索引列有效.
若是有column沒有被索引, 查詢效率可能會由於你沒有選擇OR而下降. 在下面的例子中, LOC_ID 和REGION上都建有索引.
高效:
SELECT LOC_ID , LOC_DESC , REGION FROM LOCATION WHERE LOC_ID = 10
UNION
SELECT LOC_ID , LOC_DESC , REGION FROM LOCATION WHERE REGION = 「MELBOURNE」
低效:
SELECT LOC_ID , LOC_DESC , REGION FROM LOCATION WHERE LOC_ID = 10 OR REGION = 「MELBOURNE」
若是你堅持要用OR, 那就須要返回記錄最少的索引列寫在最前面.
7. 用EXISTS替代IN、用NOT EXISTS替代NOT IN
在許多基於基礎表的查詢中, 爲了知足一個條件, 每每須要對另外一個表進行聯接. 在這種狀況下, 使用EXISTS(或NOT EXISTS)一般將提升查詢的效率.
在子查詢中, NOT IN子句將執行一個內部的排序和合並. 不管在哪一種狀況下, NOT IN都是最低效的(由於它對子查詢中的表執行了一個全表遍歷).
爲了不使用NOT IN, 咱們能夠把它改寫成外鏈接(Outer Joins)或NOT EXISTS.
例子:
高效: SELECT * FROM EMP (基礎表) WHERE EMPNO > 0 AND EXISTS (SELECT ‘X’ FROM DEPT WHERE DEPT.DEPTNO = EMP.DEPTNO AND LOC = ‘MELB’)
低效: SELECT * FROM EMP (基礎表) WHERE EMPNO > 0 AND DEPTNO IN(SELECT DEPTNO FROM DEPT WHERE LOC = ‘MELB’)
購物車業務分析:
1) 添加商品到購物車
a) 從cookie中獲取購物車列表
b) 判斷:此商品是否在購物車(cookie)存在。
i. 若是存在,此商品數據庫相加
ii. 若是不存在,直接添加
c) 把購物車寫回cookie
2) 查詢購物車
a) 展現購物車列表
3) 修改購物車
a) 修改購物車商品數量
b) 修改商品價格
4) 刪除購物車
任一項目登陸
a) 接受頁面用戶名,密碼
b) 根據用戶名查詢數據庫
c) 校驗此用戶在系統中是否存在,密碼須要進行md5加密校驗
d) 校驗成功,登陸成功。須要把用戶身份信息放入redis系統。生成token(咱們這個token是用的UUID),token至關於SESSION裏面jsessionid,token就是redis的key。
e) 返回token
f) 把token寫入cookie(頂級域名中),實現多系統之間共享。實現了單點登陸。
緊接着其餘項目登陸
根據token查詢redis服務器用戶身份信息
a) 若是cookie沒有token,從新登陸
b) 若是cookie中有token,redis服務器過時,從新登陸
c) 登陸,重置redis中用戶身份認證過時時間。
跨域問題:
i. 跨服務(不須要發請求)
ii. 跨域名(須要發送請求)[表現層與表現層交互]
1. 不能接受數據(普通Json數據)
2. 接受js代碼(callback(json))
iii.Jsonp(ajax的dataType爲jsonp)
網頁靜態化
爲何網頁靜態化:使用Freemarker技術,生成靜態化頁面,用戶不須要訪問後臺服務器,只須要訪問html頁面便可。訪問只是單純html頁面,只是和存放靜態化頁面的服務器有交互,和後臺淘淘商城沒有交互。大大減輕服務器壓力
秒殺活動技術挑戰:
1,對現有網站業務形成衝擊
秒殺只是一個附加活動,具備時間短,併發大的特色,若是和正常網站放到一塊,可能致使整站癱瘓。
2,高併發下應用和數據庫負載
由於用戶會不斷刷新頁面,相似12306搶票,這些請求若是安裝通常網站設計,對應用服務器和數據庫形成極大的負載壓力。
3,網絡帶寬壓力
假如返回一個頁面是200K,包括HTML和圖片JS等,那麼一萬我的訪問就是200K*10000,2G的帶寬流量。這種壓力,作過運維的應該清楚。
4,直接下單
秒殺規則就是開始後才能下單,以前只能瀏覽。下單頁面也是一個URL,若是有人破解,不用秒殺就能夠下單了。固然,直接下單後後端也必須判斷(這話是我加的)。
秒殺系統應對策略
1,秒殺系統獨立部署
蜂擁而至的用戶訪問,若是秒殺系統沒有獨立部署,會拖垮整個網站。通常咱們的Java系統都是分佈式部署,這裏的獨立部署不是簡單的把特定請求指向特定服務器,咱們甚至能夠用二級域名來處理。
2,頁面靜態化
通常咱們作java的,頁面就是JSP,可是每一個JSP都是動態生成HTML的,若是按照這個思惟作秒殺網站,光JSP就能幹掉本身的網站。不過如今互聯網網站前端都是PHP的,JSP也只有內部系統用了。可是瀏覽器須要的就是一個HTML,咱們在服務器放一個靜態頁面,不用任何程序處理。
3,租借秒殺活動網絡帶寬
服務器帶寬對外網的話,實際上是很貴的。全部以前有不少虛擬空間來作網站,你們公用帶寬,節省資本。在好比個人論壇,雖然是獨立服務器,但帶寬其實很坑的。這裏就要和運營商合做,甚至咱們能夠把靜態頁面放到CDN。
4,動態的下單URL
爲了防止用戶直接下單,下單URL應該是動態生成的,並且只有在活動開始的時候外層才能知道。
秒殺系統架構涉及
1,如何控制商品頁面購買按鈕點亮
購買按鈕在活動開始的時候才能點擊,在此以前是灰色。若是頁面是動態的,那麼能夠在活動開始的時候改變這個頁面,可是上面也說了,頁面都存到CDN了,請求不會到應用服務器。
方法是用JS控制,在靜態頁面引入一個JS,JS文件中有是否開始的標記,和下單的URL。這個JS文件不被瀏覽和CDN和反向代理緩存。該文件還要很是小,避免對集羣服務器形成帶寬壓力。
2,若是容許第一個提交的訂單能下單
若是能秒殺成功的只有一我的,那麼提交訂單的時候,就得檢查是否有訂單提交。因此要控制下單頁面入口,只有少數用戶能進入下單頁面,其餘直接進入活動結束頁面,和秒殺頁面同樣就是一個簡單HTML。
以上,是別人書上說的,大致意思是這樣的,我稍加修改讓意思更明瞭。
那麼其實他說的是總體思想,若是涉及到實現的時候,主要仍是要看活動開始後,下單時這個搶的動做。
資源數量是特定的,你們都來搶了,怎麼保證只有前幾個能搶到呢?這裏就涉及到了線程的問題,我面試的時候居然說了用消息隊列,往隊列裏面放特定數量消息,客戶端消費完了就是搶光了。其實這是有問題的,這和消息隊列的特性有關,另外這個時候效率也會有問題。
後來我又想了一下,簡述一下個人思路。
有兩個標量,1:是否開始。2:當前資源數量。3:是否結束。
剛纔說的是JS級別控制了開始,那麼其實在網站的後臺,請求來了之後也要判斷是否開始,防破解。另外要判斷是否結束,從這裏把運氣很差的用戶擋住。
若是活動是開始有效的,請求一個特定的接口,接口是線程安全的。
接口首先判斷是否有資源,沒有返回空,並設置活動結束。若是有則獲取並把資源數量減一,返回該資源。
那麼此時一個問題,該接口是線程安全的,大量用戶訪問的時候會不會堵塞?
由於這個接口的處理是足夠快的,另外部分用戶在是否結束判斷時擋住了,我認爲不會堵塞住。
框架就是別人說的那麼回事,搶的這個操做,我想的是這樣的。固然不必定是最好的方案,都說了是探討。
FastDFS是一個開源的分佈式文件系統,她對文件進行管理,功能包括:文件存儲、文件同步、文件訪問(文件上傳、文件下載)等,解決了大容量存儲和負載均衡的問題。特別適合以文件
爲載體的在線服務,如相冊網站、視頻網站等等。
FastDFS服務端有兩個角色:跟蹤器(tracker)和存儲節點(storage)。跟蹤器主要作調度工做,在訪問上起負載均衡的做用。
FastDFS架構包括 Tracker server和Storage server。客戶端請求Tracker server進行文件上傳、下載,經過Tracker server調度最終由Storage server完成文件上傳和下載。
Tracker server做用是負載均衡和調度,經過Tracker server在文件上傳時能夠根據一些策略找到Storage server提供文件上傳服務。能夠將tracker稱爲追蹤服務器或調度服務器。
Storage server做用是文件存儲,客戶端上傳的文件最終存儲在Storage服務器上,Storage server沒有實現本身的文件系統而是利用操做系統 的文件系統來管理文件。能夠將storage稱爲存儲服務器。
以下圖:
Tracker 集羣
FastDFS集羣中的Tracker server能夠有多臺,Tracker server之間是相互平等關係同時提供服務,Tracker server不存在單點故障。客戶端請求Tracker server採用輪詢方式,若是請求的tracker沒法
提供服務則換另外一個tracker。
Storage集羣
Storage集羣採用了分組存儲方式。storage集羣由一個或多個組構成,集羣存儲總容量爲集羣中全部組的存儲容量之和。一個組由一臺或多臺存儲服務器組成,組內的Storage server之間是平等關係,
不一樣組的Storage server之間不會相互通訊,同組內的Storage server之間會相互鏈接進行文件同步,從而保證同組內每一個storage上的文件徹底一致的。一個組的存儲容量爲該組內存儲服務器容量最
小的那個,因而可知組內存儲服務器的軟硬件配置最好是一致的。
採用分組存儲方式的好處是靈活、可控性較強。好比上傳文件時,能夠由客戶端直接指定上傳到的組也能夠由tracker進行調度選擇。一個分組的存儲服務器訪問壓力較大時,能夠在該組增長存儲服
務器來擴充服務能力(縱向擴容)。當系統容量不足時,能夠增長組來擴充存儲容量(橫向擴容)。
**********************************************************************************************************************************
*****前端*****前端*******前端*****前端*****前端*****前端*****前端*****前端*****前端*****前端****前端****前端****前端****前端******
**********************************************************************************************************************************
前端都用過什麼框架?
jquery,easyUI,boostrap(面試官問:"就這些嗎?","是的,由於我主要作一些傳統項目,都是一些老的項目,技術什麼的都比較老,像easyui當時就是很新穎的框架了")
jquery都有哪些方法?
val(),html(),css(),addClass(),hide(),show(),append()[追加方法],live()[追加方法],toggle()【切換方法】,find(),each(),parent()[父親輩分的],parents()[父親的父親,爺爺輩分的]
next(),prev()[上一個同級元素],siblings()【方法返回被選元素的全部同胞元素】,first()[獲取元素列表的第一個元素],last()[獲取元素列表的最後一個元素],eq()【返回被選元素中帶有指定索引號的元素】
attr()【獲取屬性】,text()
css有哪些選擇器?
類選擇器,ID選擇器,標籤選擇器
-------------------last updated time is 2017-03-12 by yangwenxue,soon,and continue to update-------------------
1。你必須選擇記錄條數最少的表做爲基礎表.
(from 是從前日後檢索的,因此要最少記錄的表放在最前面)
2。採用自下而上的順序解析WHERE子句,根據這個原理,表之間的鏈接必須寫在其餘WHERE條件以前, 那些 能夠過濾掉最大數量記錄的條件必須寫在WHERE子句的末尾。同時在連接的表中能過濾的就應該先進行過濾。
(where是從後往前檢索,因此能過濾最多數據的條件應放到最後。)
3。SELECT子句中避免使用 ‘ * ‘
4。儘可能多使用COMMIT
5。計算記錄條數時候,第一快:count(索引列),第二快:cout(*)
6。用Where子句替換HAVING子句
7。經過內部函數提升SQL效率
8。使用表的別名(Alias)
9。用EXISTS替代IN
10。用NOT EXISTS替代NOT IN
11。用錶鏈接替換EXISTS
12。用索引提升效率
13。避免在索引列上使用計算(此條包括在select後面 where後面等任何地方,由於在索引列上計算會致使索引失效)
14。避免在索引列上使用NOT(在索引列使用not會致使索引失效)
15。用>=替代>
16。用UNION替換OR (適用於索引列)
17。用IN來替換OR
18。避免在索引列上使用IS NULL和IS NOT NULL
19。老是使用索引的第一個列
20。用UNION-ALL 替換UNION ( 若是有可能的話)
21。ORDER BY 子句只在兩種嚴格的條件下使用索引.
22。避免改變索引列的類型
23。須要小心的WHERE子句
24。避免使用耗費資源的操做(帶有DISTINCT,UNION,MINUS,INTERSECT,ORDER BY)