一裙犹、Java基礎
1、Java中兩種數(shù)據(jù)類型(為后面進一步提問做鋪墊)
(1)基本數(shù)據(jù)類型衔憨,分為boolean叶圃、byte、int践图、char掺冠、long、short码党、double德崭、float斥黑;
(2)引用數(shù)據(jù)類型 ,分為數(shù)組眉厨、類锌奴、接口。
擴展:Java中引入了基本數(shù)據(jù)類型缺猛,但是為了能夠將這些基本數(shù)據(jù)類型當成對象操作缨叫,Java為每一個基本數(shù)據(jù)類型都引入了對應的包裝類型(wrapper class)椭符,int的包裝類就是Integer荔燎,從Java 5開始引入了自動裝箱/拆箱機制,使得二者可以相互轉換销钝。
基本數(shù)據(jù)類型: boolean有咨,char,byte蒸健,short座享,int,long似忧,float渣叛,double
封裝類類型: Boolean,Character盯捌,Byte淳衙,Short,Integer饺著,Long箫攀,F(xiàn)loat,Double
2幼衰、java中==和eqauls()的區(qū)別
==分兩類分析靴跛,既可以比較基本類型也可以比較引用類型,對于基本類型來說是比較的數(shù)值渡嚣。對于引用類型來說比較的內存地址值梢睛;equals是屬于java.lang.Object類里面的方法,Object里的equals里默認的是雙等于==识椰。分兩種情況討論:一種是自定義類绝葡,看自定義類有沒有重寫equals方法,通常情況下裤唠,如果重寫了equals則比較的是類中相應屬性是否相等挤牛。如果沒有重寫equals方法,則仍然使用==比較的是地址种蘸。
總結墓赴、:
== :
基本類型:比較值是否相等
引用類型:比較的就是內存地址是否相同
equals :
引用類型:默認情況下竞膳,比較的是地址值〗胨叮可以進行重寫,使其比較對象的值是否相等章办。
3、說說int和Integer有何區(qū)別
(1)Integer是int的包裝類藕届;int是基本數(shù)據(jù)類型;
(2)Integer變量必須實例化后才能使用休偶;int變量不需要梁厉;
(3)Integer實際是對象的引用踏兜,指向此new的Integer對象;int是直接存儲數(shù)據(jù)值 碱妆;
(4)Integer的默認值是null肉盹;int的默認值是0疹尾。
4、switch中能否使用string類型的參數(shù)作為變量(涉及到jdk版本的理解)
在JDK1.7之前航棱,switch只能支持byte、short饮醇、char、int观蓄、float祠墅、double或者其對應的封裝類以及Enum類型。JDK1.7開始支持String毁嗦。當字符串不會頻繁改變時可以用枚舉來代替String。
5克锣、說明ArrayList和LinkedList的區(qū)別和優(yōu)缺點,在哪些場景會使用袭祟?
區(qū)別:
(1)ArrayList是實現(xiàn)了基于動態(tài)數(shù)組的數(shù)據(jù)結構,LinkedList是基于鏈表結構您没;
(2)對于隨機訪問的get和set方法胆绊,ArrayList要優(yōu)于LinkedList,因為LinkedList要移動指針辑舷;
(3)對于新增和刪除操作add和remove槽片,LinkedList比較占優(yōu)勢,因為ArrayList要移動數(shù)據(jù)还栓;
各自優(yōu)缺點:
(1)對ArrayList和LinkedList而言,在列表末尾增加一個元素所花的開銷都是固定的谷婆。對ArrayList而言辽聊,主要是在內部數(shù)組中增加一項,指向所添加的元素跟匆,偶爾可能會導致對數(shù)組重新進行分配;而對LinkedList而言烤蜕,這個開銷是 統(tǒng)一的迹冤,分配一個內部Entry對象。
(2)在ArrayList集合中添加或者刪除一個元素時泡徙,當前的列表移動元素后面所有的元素都會被移動。而LinkedList集合中添加或者刪除一個元素的開銷是固定的莉兰。
(3)LinkedList集合不支持 高效的隨機隨機訪問(RandomAccess),因為可能產(chǎn)生二次項的行為贮勃。
(4)ArrayList的空間浪費主要體現(xiàn)在在list列表的結尾預留一定的容量空間,而LinkedList的空間花費則體現(xiàn)在它的每一個元素都需要消耗相當?shù)目臻g奏瞬。
應用場景:
ArrayList使用在查詢比較多泉孩,但是插入和刪除比較少的情況,而LinkedList用在查詢比較少而插入刪除比較多的情況
6寓搬、實現(xiàn)多線程的幾種方式,多線程的應用場景有哪些镣典?
(1)唾琼、繼承Thread類,重寫run方法
(2)锡溯、實現(xiàn)Runnable接口,重寫run方法芜茵〕【可以避免由于Java的單繼承特性而帶來的局限。適合多個線程去處理同一資源的情況】
(3)悠咱、實現(xiàn)Callable接口,重寫call方法躬贡⊙刍担【有返回值酸些,允許拋出異抽苎粒】
(4)、使用線程池【減少創(chuàng)建新線程的時間闯第,重復利用線程池中線程,降低資源消耗填帽,可有返回值】
7咙好、${}和#{}的區(qū)別
使用#{}:
(1)、傳入?yún)?shù)勾效,sql在解析的時候會加上" ",當成字符串來解析,如 id = "id";
(2)杨伙、#{}能夠很大程度上防止sql注入;
使用${}:
(1)卒密、傳入數(shù)據(jù)直接顯示在生成的sql中,sql在解析的時候值為id = id哮奇。
(2)睛约、${}方式無法防止sql注入
最后:能用#{}時盡量用#{},但有些場合需要使用$贸伐。
注意MyBatis排序時使用order by 動態(tài)參數(shù)時需要注意怔揩,用$而不是#(#會自動拼接符號)
8、描述一下JVM加載class文件的原理機制和特點商膊。
Java中的所有類,都需要由類加載器裝載到JVM中才能運行藐翎。JVM中類的加載是由類加載器(ClassLoader)和它的子類來實現(xiàn)的。在我們使用一個類之前吝镣,JVM需要先將該類的字節(jié)碼文件(.class文件)從磁盤、網(wǎng)絡或其他來源加載到內存中(加載Class文件到JVM)闸溃,并對字節(jié)碼進行解析生成對應的Class對象拱撵,這就是類加載器的功能。我們可以利用類加載器裕膀,實現(xiàn)類的動態(tài)加載。在寫程序的時候寸齐,我們幾乎不需要關心類的加載抄谐,因為這些都是隱式裝載的,除非我們有特殊的用法蛹含,像是反射,就需要顯式的加載所需要的類吸耿。
Java類的加載是動態(tài)的酷窥,它并不會一次性將所有類全部加載后再運行,而是保證程序運行的基礎類(像是基類)完全加載到jvm中蓬推,至于其他類,則在需要的時候才加載糕珊。這當然就是為了節(jié)省內存開銷毅糟。
進一步提問:類加載的方式有幾種?區(qū)別是什么留特?
類裝載方式有兩類:隱式裝載和顯示裝載玛瘸,其中顯示裝載又分2種方式苟蹈。
(1)、隱式裝載渺绒,程序在運行過程中當碰到通過new 等方式生成對象時菱鸥,隱式調用類裝載器加載對應的類到jvm中,比如
Dog dog = new Dog()氮采;【第一種方式】
(2)、顯式裝載主到,
【第二種方式】使用Class.forName()通過反射加載類型躯概,并創(chuàng)建對象實例,比如
Class clazz = Class.forName(“Dog”)牧牢;
? Object dog =clazz.newInstance()姿锭;
如果無法找到Dog,則拋出ClassNotFoundException艾凯。
【第三種方式】使用某個ClassLoader實例的loadClass()方法
Class clazz = classLoader.loadClass("Dog");
Object dog=clazz.newInstance();
如果無法找到Dog,則拋出ClassNotFoundException。
區(qū)別:
方式1和2使用的類加載器是相同的蹬蚁,都是當前類加載器(即:this.getClass.getClassLoader)。
方式3由用戶指定類加載器贝乎。如果需要在當前類路徑以外尋找類叽粹,則只能采用方式3却舀。即第3種方式加載的類與當前類分屬不同的命名空間锤灿。
方式1是靜態(tài)加載,方式2和3是動態(tài)加載螃诅。
進一步提問:java內置的類加載器(ClassLoader)有哪些状囱,簡述一下類加載器工作原理
Java的類加載器有三個:
第一種是Bootstrap Loader(引導類加載器)。它的實現(xiàn)依賴于底層操作系統(tǒng)惨驶,由C編寫而成,沒有繼承于ClassLoader類猾编。根類加載器從系統(tǒng)屬性sun.boot.class.path所指定的目錄中加載類庫宣鄙。默認為jre目錄下的lib目錄下的class文件,該加載器沒有父加載器冻晤。負責加載虛擬機的核心類庫,如java.lang.*设江。Object類就是由根類加載器加載的攘轩。
第二種是Extended Loader(標準擴展類加載器)。它的父加載器為根類加載器度帮。由java編寫而成,是ClassLoader的子類瞳秽。它從java.ext.dirs中加載類庫率翅,或者從JDK安裝目錄jre\lib\ext子目錄下加載類庫。如果把用戶創(chuàng)建的jar文件放在該目錄下腺晾,也會自動由擴展類加載器加載。
第三種是AppClass Loader(應用程序類路徑類加載器)悯蝉。它的父加載器為擴展類加載器。由java編寫而成连霉,是ClassLoader的子類嗡靡,它從環(huán)境變量classpath或者系統(tǒng)屬性java.class.path所指定的目錄中加載類,是用戶自定義的類加載器的默認父加載器讨彼。
加載類時,會以Bootstrap Loader→Extended Loader→AppClass Loader的順序來尋找類哩至,如果找不到蜜自,就會丟出NoClassDefFoundError。
9箭阶、在一個類中戈鲁,聲明了若干個static方法和非static方法,聲明的static方法能否直接訪問聲明的非static方法婆殿?
static方法不能直接訪問非static方法,因為static方法是屬于這個類本身的一個方法怕磨,在編譯期間就已經(jīng)確定了消约;而非static方法是屬于這個類的對象的方法,需要在實例化之后才能訪問到荆陆。即:static方法調用時不需要創(chuàng)建對象被啼,可以直接調用,非static方法是要與對象關聯(lián)在一起的浓体,必須創(chuàng)建一個對象后,才可以在該對象上進行方法調用娄猫,若在static方法中訪問非static方法生闲,非static方法不知道關聯(lián)到哪個對象上,將不能通過編譯悬蔽。
進一步提問:說一下靜態(tài)方法和非靜態(tài)方法都是在什么時候被裝載到內存中的捉兴?
靜態(tài)方法(Static Method)與靜態(tài)成員變量一樣,屬于類本身倍啥,在類裝載的時候被裝載到內存(Memory),不自動進行銷毀始藕,會一直存在于內存中彼宠,直到JVM關閉。
非靜態(tài)方法(Non-Static Method)又叫實例化方法凭峡,屬于實例對象,實例化后才會分配內存倍踪,必須通過類的實例來引用索昂。不會常駐內存,當實例對象被JVM 回收之后缤至,也跟著消失康谆。
進一步提問:靜態(tài)方法怎樣訪問非靜態(tài)方法嫉到?
靜態(tài)方法不能直接使用本類的非靜態(tài)方法
解決方式有三種
(1)月洛、兩個方法都改成非靜態(tài)
(2)、兩個方法都改成靜態(tài)
(3)细层、先創(chuàng)建類的實例唬涧,然后靜態(tài)方法再調用這個實例的非靜態(tài)方法
10、在Java中,對象什么時候可以被垃圾回收?
Java垃圾回收不是實時的爵卒,垃圾回收器的作用是查找和回收(清理)無用的對象。以便讓JVM更有效的使用內存实牡。垃圾回收器的運行時間是不確定的轴合,由JVM決定,在運行時是間歇執(zhí)行的受葛。也可以通過System.gc()來強制回收垃圾总滩,但是這個命令下達后JVM不一定會立即響應執(zhí)行,但間隔一小段時間基本都會執(zhí)行闰渔。
11、一個漢字占幾個字節(jié)
中文在不同編碼下占不定長的 2~4個字節(jié)茂附。注意在utf-16中占用兩個字節(jié)督弓,在java 運行時用UTF-16編碼在轉碼的時候會在前面加上表示字節(jié)順序的字符,這個字符稱為”零寬度非換行空格”(ZERO WIDTH NO-BREAK SPACE)愚隧,用FEFF表示。FEFF占用兩個字節(jié)蒜危。
12虱痕、項目中使用Maven進行構建辐赞,有哪些優(yōu)勢响委?你使用過哪些maven命令窖梁?說一下maven中本地倉庫和遠程倉庫的區(qū)別和聯(lián)系。
優(yōu)點:
(1)創(chuàng)建項目纵刘,自動關聯(lián)和下載依賴的jar包,統(tǒng)一維護jar包
(2)升級框架版本方便
常用 Maven 命令:
(1)瞬捕、安裝項目到本地倉庫:mvn install
(2)舵抹、創(chuàng)建maven項目:mvn archetype:generate
(3)、驗證項目是否正確:mvn validate
(4)扇救、maven 打包:mvn package
(5)香嗓、只打jar包:mvn jar:jar
(6)、生成源碼jar包:mvn source:jar
(7)沧烈、產(chǎn)生應用需要的任何額外的源代碼:mvn generate-sources
(8)饱岸、編譯源代碼: mvn compile
(9)、編譯測試代碼:mvn test-compile
(10)苫费、運行測試:mvn test
(11)、運行檢查:mvn verify
(12)闲礼、清理maven項目:mvn clean
Maven倉庫關系:
maven的倉庫只有兩大類:1.本地倉庫 2.遠程倉庫,在遠程倉庫中又分成了3種:2.1 中央倉庫 2.2 私服 2.3 其它公共庫
運行Maven的時候慎菲,Maven所需要的任何構件都是直接從本地倉庫獲取的锨并。如果本地倉庫沒有,它會首先嘗試從遠程倉庫下載構件至本地倉庫第煮,然后再使用本地倉庫的構件。
13撵摆、Thread.sleep(0)有沒有實際作用
觸發(fā)操作系統(tǒng)立刻重新進行一次CPU競爭害晦,操作系統(tǒng)重新計算線程的優(yōu)先級(包括當前線程)。競爭的結果也許是當前線程仍然獲得CPU控制權鲫剿,也許會換成別的線程獲得CPU控制權俐筋。
二、前端框架
1笆呆、在項目中使用過哪些前端框架粱挡?
Vue(用于構建用戶界面的 漸進式框架,特點:輕量級榕堰、雙向數(shù)據(jù)綁定嫌套、組件化)、
React(構建用戶界面的 JAVASCRIPT 庫踱讨,特點:只負責顯示、聲明式框架莺治、數(shù)據(jù)驅動DOM)、
Angular(前端JS框架床佳,核心:MVVM榄审、模塊化、自動化雙向數(shù)據(jù)綁定怨绣、語義化標簽拷获、依賴注入等)减细、
QucikUI(企業(yè)級web前端開發(fā)解決方案)、
Layui(前端 UI 框架)驮吱、
Avalon(前端MVVM框架)萧吠、
還有Dojo、Ember纸型、Aurelia等
2狰腌、js中如何查看某變量的數(shù)據(jù)類型?可以查看的數(shù)據(jù)類型有哪些琼腔?
使用typeof查看變量的數(shù)據(jù)類型。
javascript共有6種數(shù)據(jù)類型:
基本類型5種:number光坝、string甥材、boolean、null土铺、undefined。引用類型1種:object
typeof檢測返回6種:undefined究恤、boolean后德、string、number瓢湃、object绵患、function
3、前端進行文件下載時落蝙,能不能用ajax向后端發(fā)起請求筏勒?
Ajax不能實現(xiàn)文件下載功能
原因:ajax的返回值是json,text,html,xml類型,或者可以說ajax的接收類型只能是String字符串管行,不是流類型,所以無法實現(xiàn)文件下載荡陷。但用aja仍然可以獲得文件的內容(可以讀取到返回的response套菜,但只是讀取而已),該文件將被保留在內存中蛹头,無法將文件保存到磁盤戏溺,這是因為javascript無法和磁盤進行交互,否則這會是一個嚴重的安全問題耕拷,js無法調用瀏覽器的下載處理機制和程序托享,會被瀏覽器阻塞浸赫。
4赃绊、如何解決前后端交互過程中特殊字符的傳參(比如中文碧查、特殊符號等)?
(這個問題屬于送分題忠售,有一定項目經(jīng)驗的人稻扬,都會注意到在前后端進行交互時,需要進行decoder編碼-Encoder解碼的過程泰佳,防止亂碼)
進一步提問:前后端數(shù)組傳參如何處理?
前端:數(shù)據(jù)使用JSON.stringify(str)處理
后端:數(shù)據(jù)轉換:List<Object> objectList = JSONObject.parseArray(str, Object.class)
5、FreeMarker汽绢、jsp侧戴、html 三者的區(qū)別
先說說freemarker和jsp的不同,運行機制就不大一樣,jsp是編譯成繼承自servlet的class文件积仗,運行jsp就是運行一個servlet(Java文件編譯后會產(chǎn)生一個class文件蜕猫,最終執(zhí)行的就是這個class文件,JSP也一樣回右,它也要編譯成class文件翔烁。JSP不止要編譯,它還得要轉譯蹬屹,首先把JSP轉譯成一個Servlet文件,然后再編譯成class文件贩耐。當用戶訪問JSP時就執(zhí)行了class文件)。
而freemarker就是套模板鸟赫,通過模板+內容直接生成HTML然后輸出消别。
HTML(Hypertext Markup Language)文本標記語言,它是靜態(tài)頁面岁经,和JavaScript一樣是解釋性語言蛇券。
JSP(Java Server Page)Java服務端的頁面,它是動態(tài)頁面塘慕,它是需要經(jīng)過JDK編譯后把內容發(fā)給客戶端去顯示蒂胞。
6、vue實例內部和外部分別怎么調用vue中的方法?
內部調用: this.operate();
外部調用:vm.operate(); (vm是vue實例名)
三蛤织、后端技術
1鸿染、Spring:
(1)Spring中IOC和AOP的應用場景。
AOP:面向切面編程摊鸡《妫可以運用在日志,事務和異常處理等掸刊。如果不使用aop赢乓,那么就必須在每個類和方法中去實現(xiàn)它們石窑。代碼糾纏在一起松逊。每個類和方法中都包含日志肯夏、事務或者異常處理甚至是業(yè)務邏輯。在一個這樣的方法中驯击,很難分清代碼中實際做的是什么處理徊都。AOP 所做的就是將所有散落各處的事務代碼集中到一個事務切面中。
AOP日志處理:使用Aop在接口方法上插入一行自定義的切面注解類主之,在切面處理類中可以記錄接口名稱李根、請求參數(shù)、請求ip史翘、請求url冀续、請求時間必峰、響應參數(shù)、響應狀態(tài)凭需、調用時長等肝匆;
AOP事務處理:Spring在方法訪問數(shù)據(jù)庫之前,自動開啟事務枯怖,當訪問數(shù)據(jù)庫結束之后能曾,自動提交/回滾事務肿轨;
AOP異常處理:自定義開啟環(huán)繞通知椒袍,一旦運行接口報錯藻茂,環(huán)繞通知捕獲異常跳轉異常處理頁面。
IOC就是Inversion of Control优俘,即控制反轉肖油,又稱依賴注入。它不是什么技術视搏,而是一種設計思想县袱。在Java開發(fā)中,傳統(tǒng)的創(chuàng)建對象的方法是直接通過 new 關鍵字(之前我們通過 "類名 對象名 = new 類名( )"的方式進行對象的創(chuàng)建筋遭,也就是說我們的程序負責對象的創(chuàng)建暴拄,控制了它是否被創(chuàng)建這件事情,這就叫做控制)响驴,而 spring 則是通過 IOC 容器來創(chuàng)建對象撕蔼,也就是說我們將創(chuàng)建對象的控制權交給了 IOC 容器。這稱為控制反轉琳骡。概括的說就是:
IOC 讓程序員不再關注怎么去創(chuàng)建對象讼溺,而是關注于對象創(chuàng)建之后的操作,把對象的創(chuàng)建竖席、初始化、銷毀等工作交給spring容器來做束析。
舉個例子:梳理這個問題在各種社會形態(tài)里如何解決:一個人(Java實例憎亚,調用者)需要一把斧子(Java實例,被調用者)
(1) 原始社會里蝶锋,幾乎沒有社會分工什往。需要斧子的人(調用者)只能自己去磨一把斧子(被調用者)。對應的情形為:Java程序里的調用者自己創(chuàng)建被調用者躯舔。
(2)進入工業(yè)社會省古,工廠出現(xiàn)。斧子不再由普通人完成惜互,而在工廠里被生產(chǎn)出來琳拭,此時需要斧子的人(調用者)找到工廠,購買斧子蔫慧,無須關心斧子的制造過程权薯。對應Java程序的簡單工廠的設計模式睡扬。
(3)進入“按需分配”社會卖怜,需要斧子的人不需要找到工廠,坐在家里發(fā)出一個簡單指令:需要斧子马靠。斧子就自然出現(xiàn)在他面前。對應Spring的依賴注入逞度。
第一種情況下档泽,Java實例的調用者創(chuàng)建被調用的Java實例,必然要求被調用的Java類出現(xiàn)在調用者的代碼里抑胎。無法實現(xiàn)二者之間的松耦合渐北。
第二種情況下,調用者無須關心被調用者具體實現(xiàn)過程赃蛛,只需要找到符合某種標準(接口)的實例,即可使用淡喜。此時調用的代碼面向接口編程诵闭,可以讓調用者和被調用者解耦,這也是工廠模式大量使用的原因瘟芝。但調用者需要自己定位工廠褥琐,調用者與特定工廠耦合在一起敌呈。
第三種情況下,調用者無須自己定位工廠磕洪,程序運行到需要被調用者時析显,系統(tǒng)自動提供被調用者實例。事實上分尸,調用者和被調用者都處于Spring的管理下,二者之間的依賴關系由Spring提供孔庭。
生活中這種例子比比皆是伶选,支付寶在整個淘寶體系里就是龐大的ioc容器,交易雙方之外的第三方資金管理中心构资。
(2)Spring依賴注入的方式有哪些陨簇?
【set設值注入、構造函數(shù)注入己单、spring注解注入】
Spring IOC既可以通過XML的形式進行bean與依賴注入配置耙饰,也可以通過注解的方式。(在springmvc中廷痘,我們一般使用xml進行裝配件已,而springboot使用全注解的形式)
①通過XML的形式進行bean與依賴注入
通常有兩種: 設值注入&構造注入篷扩。
設值注入就是指要被注入的類中定義有一個setter()方法,并在參數(shù)中定義需要注入的對象鉴未。
構造注入就是指要被注入的類中聲明一個構造方法铜秆,并在此方法的參數(shù)中定義要注入的對象。
②注解的方式:
注解包含三部分:
| 組件類型注解--聲明當前類的功能與職責
|| 自動裝配注解--根據(jù)屬性特征自動注入對象
||| 元數(shù)據(jù)注解--更細化的輔助IoC容器管理對象的注解
A、四種組件類型注解
@Component:組件注解梅屉,通用注解,該注解描述的類將被IoC容器管理并實例化
@Controller:語義注解虐唠,說明當前類是MVC應用中的控制類
@Service:語義注解惰聂,說明當前類是Service業(yè)務服務類
@Repository:語義注解,說明當前類作用于業(yè)務持久層杆故,通常描述對應Dao類
此外溉愁,在使用四種組件類型的注解時拐揭,必須開啟組件掃描,詳細配置如下:
B堂污、兩類自動裝配注解
按類型裝配
@Autowired
@Inject
按名稱裝配
@Named
@Resource
優(yōu)先設置name屬性盟猖,若未包含name屬性,會按照@Autowired注入
C值依、元數(shù)據(jù)注解
@Primary--按類型裝配時出現(xiàn)多個相同類型的對象碟案,擁有此注解對象優(yōu)先被注入
@PostContruct:相當于init-method
@PreDestory:相當于destory--method
@Scope:設置對象Scope屬性
@Value:為屬性注入靜態(tài)數(shù)據(jù)
(3)為什么非使用依賴注入,我要用到一個其他對象時辆亏,new一個怎么就不好了鳖目。
本質上都是創(chuàng)建對象,最大的區(qū)別還是生命周期的管理以及復雜依賴的處理彻磁。
①、生命周期
比如一個類或者接口全程只要一個實例累提,用依賴注入的話只需要注冊成單例即可磁浇,如果自己實例化的話你需要擼一個單機模式(餓漢、懶漢无虚、線程安全等模式)的類衍锚,并發(fā)下還要考慮線程安全。
②构拳、復雜依賴
如果這個類或者接口不依賴其他的類或者接口差異不明顯,如果依賴的類比較多的情況下(A依賴B置森,B又依賴C凫海,C又依賴D,D又依賴其他)自己實例化會很麻煩漾稀。要創(chuàng)建A, 要先B建瘫、C、D先new一遍再new A殷蛇。用ioc就快多了橄浓,A(B b),其他自動創(chuàng)建,是不是快多了匀们。
總結:在程序中如果不是必須同一個對象多個實例時准给,也就是一個對象只是在某個地方使用一下時new一下,依賴注入就比new一個對象更好祖灰,因為new一個對象必選面臨頻繁創(chuàng)建和銷毀內存實例對象的問題夫植。而ioc管控下實例對象都是單例模式的油讯,就是在程序運行時始終只有一個對象實例生成不需要頻繁創(chuàng)建和銷毀,也因為在內存中只有一個實例對象沈跨,減少內存開銷兔综。
(4)描述一下DispatcherServlet的工作流程?
(5)SpringMVC如何區(qū)分控制器返回的是頁面還是數(shù)據(jù)(比如JSON格式的數(shù)據(jù))
使用@ResponseBody注解软驰,該注解用于將Controller方法返回的對象,通過適當?shù)腍ttpMessageConverter轉化為指定格式后纠吴,寫入到Response對象的body數(shù)據(jù)區(qū)慧瘤。
使用時機:返回的數(shù)據(jù)不是html標簽的頁面,而是其他某種格式的數(shù)據(jù)時(如json糖儡,xml等)怔匣。(如果是在程序中返回的html頁面代碼劫狠,也可以使用@ResponseBody,在HttpServletResponse寫入呐矾,設置ContentType為text/html)
(6)Spring全家桶有哪些懦砂?
Spring、Spring MVC罚随、Spring Boot、Spring Cloud 遵班、 Spring Security 潮改、Spring Data
(7)Spring普通類與工具類如何調用service層方法,為什么不能直接使用注解調用翰萨?
Spring中的Service不是你想new就能new的糕殉,因為通過new實例化的對象脫離了Spring容器的管理阿蝶,獲取不到注解的屬性值,所以會是null,就算調用service的類中有@Component注解加入了Spring容器管理魄缚,也還是null焚廊。
新建SpringContextUtil類,在application.xml配置SpringContextUtil,最后使用DictService dictService = (DictService) SpringContextUtil.getBean("dictService");
2嚼隘、Springboot:
(1) SpringBoot中如何進行單元測試袒餐?
導入spring-boot-starter-test依賴飞蛹。測試類使用注解@SpringBootTest,測試的方法上加@Test注解灸眼。
(2) SpringBootApplication注解的作用卧檐。
@SpringBootApplication注解是一個組合注解,@SpringBootApplication注解的源碼我們發(fā)現(xiàn)焰宣,它是由ComponentScan霉囚、SpringBootConfiguration匕积、EnableAutoConfiguration等注解組合而成:
(3) 在一個Springboot+mybatis+mysql+oracle+redis+aop功能的項目中盈罐,在pom.xml中需要引入哪些jar包依賴榜跌?
進一步提問:以redis為例,springboot 1.x與springboot 2.x引入的jar包有何不同盅粪?
在 springboot 1.5.x版本的默認的Redis客戶端是Jedis實現(xiàn)的钓葫,springboot 2.x版本中默認客戶端是用lettuce實現(xiàn)的。
3票顾、SpringCloud:
(1)springCloud的核心組件有哪些础浮,解決什么問題?
Eureka(注冊中心)
每個微服務都有一個EurekaClient組件奠骄,專門負責將這個服務的信息注冊到EurekaServer中霸旗,也就是告訴EurekaServer,自己在哪臺機器上戚揭,監(jiān)聽著哪個端口。而EurekaServer是一個注冊中心撵枢,里面有一個注冊表民晒,保存了各服務所在的機器和端口號。
Feign(REST客戶端)
Feign是一個聲明式REST客戶端锄禽,主要是為了簡便服務調用潜必,更快捷、優(yōu)雅地調用HTTPAPI沃但。主要是實現(xiàn)原理是用動態(tài)代理磁滚,你要是調用哪個接口,本質就是調用Feign創(chuàng)建的動態(tài)代理宵晚。
Ribbon(負載均衡)
Ribbon的作用是負載均衡垂攘,會幫你在每次請求時選擇一臺機器,均勻地把請求分發(fā)到各個機器上淤刃,默認使用的最經(jīng)典的RoundRobin輪詢算法(如果發(fā)起10次請求晒他,那就先讓你請求第1臺機器、然后是第2臺機器逸贾、第3臺機器陨仅,接著再來—個循環(huán),第1臺機器铝侵、第2臺機器。。皿伺。以此類推)
Hystrix(熔斷器)
微服務框架是許多服務互相調用的滋捶,要是不做任何保護的話,某一個服務掛了疟丙,就會引起連鎖反應猾警,導致別的服務也掛孔祸。Hystrix是隔離、熔斷以及降級的一個框架发皿。如果調用某服務報錯或者掛了崔慧,就對該服務熔斷,在5分鐘內請求此服務直接就返回一個默認值穴墅,不需要每次都卡幾秒惶室,這個過程,就是所謂的熔斷玄货。但是熔斷了之后就會少調用一個服務皇钞,此時需要做下標記,標記本來需要做什么業(yè)務松捉,但是因為服務掛了夹界,暫時沒有做,等熔斷的服務恢復了隘世,就可以手工處理這些業(yè)務可柿。這個過程,就是所謂的降級丙者。
Zuul(服務網(wǎng)關)
Zuul微服務網(wǎng)關复斥,負責網(wǎng)絡路由。假設你后臺部署了幾百個服務械媒,現(xiàn)在有個前端兄弟要來調用這些服務目锭,難不成你讓他把所有服務的名稱和地址全部記住,這是不現(xiàn)實的纷捞,所以一般微服務架構中都必然會設計一個網(wǎng)關痢虹,所有請求都往網(wǎng)關走,網(wǎng)關會根據(jù)請求中的一些特征主儡,將請求轉發(fā)給后端的各個服務世分。而且有一個網(wǎng)關之后,還有很多好處缀辩,比如可以做統(tǒng)一的降級臭埋、限流、認證授權臀玄、安全瓢阴,等等。
總結步驟:①服務注冊—》②服務發(fā)現(xiàn)—》③負載均衡—》④服務調用—》⑤隔離健无、熔斷與降級—》⑥網(wǎng)關路由
流程說明:各個服務啟動時荣恐,Eureka Client都會將服務注冊到Eureka Server,并且Eureka Client還可以反過來從Eureka Server拉取注冊表,從而知道其他服務在哪里叠穆。服務間發(fā)起請求的時候少漆,基于Ribbon做負載均衡,從一個服務的多臺機器中選擇一臺硼被∈舅穑基于Feign的動態(tài)代理機制,根據(jù)注解和選擇的機器嚷硫,拼接請求URL地址检访,發(fā)起請求。發(fā)起請求是通過Hystrix的線程池來走的仔掸,不同的服務走不同的線程池脆贵,實現(xiàn)了不同服務調用的隔離,避免了服務雪崩的問題起暮。如果前端卖氨、移動端要調用后端系統(tǒng),統(tǒng)一從Zuul網(wǎng)關進入负懦,由Zuul網(wǎng)關轉發(fā)請求給對應的服務筒捺。
(2)SpringCloud和Dubbo兩種微服務架構有何區(qū)別?
Dubbo的定位始終是一款RPC框架密似,而SpringCloud的目標是微服務架構下的一站式解決方案。如果非要比較的話葫盼,Dubbo可以類比到NetflixOSS技術棧残腌,而SpringCloud集成了NetflixOSS作為分布式服務治理解決方案,但除此之外SpringCloud還提供了配置贫导、消息抛猫、安全、調用鏈跟蹤等分布式問題解決方案孩灯。
(3)SpringBoot和SpringCloud 側重點分別在哪些方面闺金?
SpringBoot是Spring的一套快速配置腳手架,可以基于SpringBoot快速開發(fā)單個微服務峰档,SpringCloud是一個基于SpringBoot實現(xiàn)的云應用開發(fā)工具败匹;
SpringBoot專注于快速、方便集成的單個微服務個體讥巡,SpringCloud關注全局的服務治理框架掀亩;
SpringBoot使用了默認大于配置的理念,很多集成方案已經(jīng)幫你選擇好了欢顷,能不配置就不配置槽棍,SpringCloud很大的一部分是基于SpringBoot來實現(xiàn)。SpringBoot可以離開SpringCloud獨立使用開發(fā)項目,但是SpringCloud離不開SpringBoot炼七,屬于依賴的關系缆巧。
(4)springcloud如何實現(xiàn)服務的注冊和調用?
1)服務發(fā)布時,指定對應的服務名(服務名包括了IP地址和端口),將服務注冊到注冊中心(eureka 或者zookeeper)
2)注冊中心加@EnableEurekaServer,服務用@EnableDiscoveryClient豌拙,然后用ribbon或feign進行服務直接的調用發(fā)現(xiàn)陕悬。(這一過程是springcloud自動實現(xiàn) 只需要在main方法添加@EnableDisscoveryClient。同一個服務修改端口就可以啟動多個實例)
4姆蘸、mybatis:
(1)Mybatis中mapper.xml映射文件墩莫,通常都會寫一個Mapper接口與之對應,這個Mapper層接口是怎么能夠找到指定xml下的方法的?
Mapper接口是沒有實現(xiàn)類的逞敷,當調用接口方法時狂秦,接口全限名(就是映射文件中的namespace的值)+方法名拼接字符串作為key值,可唯一定位一個MapperStatement推捐。在Mybatis中裂问,每一個、牛柒、堪簿、標簽,都會被解析為一個MapperStatement對象皮壁。
(2)Mybatis的Xml映射文件中椭更,不同的Xml映射文件,id是否可以重復蛾魄?
不同的Xml映射文件虑瀑,如果配置了namespace,那么id可以重復滴须;如果沒有配置namespace舌狗,那么id不能重復;原因就是namespace+id是作為Map的key使用的扔水,如果沒有namespace痛侍,就剩下id,那么魔市,id重復會導致數(shù)據(jù)互相覆蓋主届。有了namespace,自然id就可以重復待德,namespace不同岂膳,namespace+id自然也就不同。
(3)Mybatis中使用MySQL和Oracle分頁的區(qū)別
MySQL分頁:(利用LIMIT關鍵字)計算參數(shù)為開始序號(startNum)磅网,要查的總條數(shù)(totalNum)
Oracle分頁:(利用自帶的rownum)計算參數(shù)為開始序號(startNum)谈截,結束序號(endNum)【注意:Oracle分頁利用其自帶的rownum,但是rownum在表中不能使用>號(比如select rownum,a.* from A a where rownum > n,查出的都是空),但是可以使用n(n>1的自然數(shù))這種條件依舊不成立簸喂,所以查不到記錄】
(4)Mybatis是如何將sql執(zhí)行結果封裝為目標對象并返回的毙死?
第一種是使用resultMap標簽,逐一定義列名和對象屬性名之間的映射關系喻鳄。
第二種是使用sql列的別名功能扼倘,將列別名書寫為對象屬性名,比如T_NAME AS NAME除呵,對象屬性名一般是name再菊,小寫,但是列名不區(qū)分大小寫颜曾,Mybatis會忽略列名大小寫纠拔,智能找到與之對應對象屬性名,你甚至可以寫成T_NAME AS NaMe泛豪,Mybatis一樣可以正常工作稠诲。
進一步提問:resultMap和resultType有啥區(qū)別?
resultType:當使用resultType做SQL語句返回結果類型處理時,對于SQL語句查詢出的字段在相應的pojo中必須有和它相同的字段對應诡曙,而resultType中的內容就是pojo在本項目中的位置臀叙。
resultMap:當使用resultMap做SQL語句返回結果類型處理時,通常需要先在mapper.xml中定義resultMap進行pojo和相應表字段的對應關系价卤。然后再使用resultMap劝萤。
(5)Mybatis xml映射文件中,除了常見的select慎璧、insert床嫌、updae、delete標簽之外炸卑,還有哪些標簽及其作用既鞠?
除了這四個標簽煤傍,還有<resultMap>盖文、<parameterMap>、<sql>蚯姆、<include>五续、<selectKey>,一個9個標簽龄恋,其中<sql>為sql片段標簽疙驾,通過<include>標簽引入sql片段,<selectKey>為不支持自增的主鍵生成策略標簽郭毕。
(6)為什么說Mybatis是半自動ORM映射工具它碎?它與全自動的區(qū)別在哪里?
hibernate對很多數(shù)據(jù)庫的操作已經(jīng)進行了封裝,hibernate操作對象時扳肛,比如往數(shù)據(jù)庫添加一條記錄傻挂,直接save就可以了。(Hibernate屬于全自動ORM映射工具挖息,使用Hibernate查詢關聯(lián)對象或者關聯(lián)集合對象時金拒,可以根據(jù)對象關系模型直接獲取)套腹,而Mybatis在查詢關聯(lián)對象或關聯(lián)集合對象時绪抛,需要手動編寫sql來完成,雖然現(xiàn)在已經(jīng)有不少程序可以自動生成xml文件电禀,但還是需要自己調整sql,所以稱之為半自動ORM映射工具幢码。這也從側面可以看出hibernate的拓展性不如Mybatis(hibernate做了很多封裝)。
(7)mybatis 為什么大于不用轉義,小于必須轉義鞭呕?
mybatis不支持“<”蛤育,本質是xml不支持這個符號,<會引起xml格式的錯誤葫松,xml文件中的標簽是?<…>?這種形式的, 所以當出現(xiàn) “<” 號時, 會認為是一個標簽的開始瓦糕。