Java經典面試題最全匯總208道(五)
前言
短時間提升自己最快的手段就是背面試題,最近總結瞭Java常用的面試題,分享給大傢,希望大傢都能圓夢大廠,加油,我命由我不由天。
152、什麼是 YAML?
YAML是JSON的一個超集,可以非常方便地將外部配置以層次結構形式存儲起來。
YAML可以作為properties配置文件的替代。
YAML使用的註意事項:
- 在properties文件中是以"."進行分割的,在yml中是用"."進行分割的;
- yml的數據格式和json的格式很像,都是K-V格式,並且通過":"進行賦值;
- 每個冒號後面一定要加一個空格;
153、如何使用 Spring Boot 實現分頁和排序?
使用Spring Data Jpa可以實現將可分頁的傳遞給存儲庫方法。
154、如何使用 Spring Boot 實現異常處理?
1、使用 @ExceptionHandler 註解處理局部異常(隻能處理當前controller中的ArithmeticException和NullPointerException異常,缺點就是隻能處理單個controller的異常)
@Controller public class ExceptionHandlerController { @RequestMapping("/excep") public String exceptionMethod(Model model) throws Exception { String a=null; System.out.println(a.charAt(1)); int num = 1/0; model.addAttribute("message", "沒有拋出異常"); return "index"; } @ExceptionHandler(value = {ArithmeticException.class,NullPointerException.class}) public String arithmeticExceptionHandle(Model model, Exception e) { model.addAttribute("message", "@ExceptionHandler" + e.getMessage()); return "index"; } }
2、使用 @ControllerAdvice + @ExceptionHandler 註解處理全局異常(value後面可以填寫數組)
@ControllerAdvice public class ControllerAdviceException { @ExceptionHandler(value = {NullPointerException.class}) public String NullPointerExceptionHandler(Model model, Exception e) { model.addAttribute("message", "@ControllerAdvice + @ExceptionHandler :" + e.getMessage()); return "index"; } }
3、配置 SimpleMappingExceptionResolver 類處理異常(配置類)
@Configuration public class SimpleMappingException { @Bean public SimpleMappingExceptionResolver getSimpleMappingExceptionResolver(){ SimpleMappingExceptionResolver resolver = new SimpleMappingExceptionResolver(); Properties mappings = new Properties(); //第一個參數為異常全限定名,第二個為跳轉視圖名稱 mappings.put("java.lang.NullPointerException", "index"); mappings.put("java.lang.ArithmeticException", "index"); //設置異常與視圖映射信息的 resolver.setExceptionMappings(mappings); return resolver; } }
4、實現 HandlerExceptionResolver 接口處理異常
@Configuration public class HandlerException implements HandlerExceptionResolver { @Override public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { ModelAndView modelAndView = new ModelAndView(); modelAndView.addObject("message", "實現HandlerExceptionResolver接口"); //判斷不同異常類型,做不同視圖跳轉 if(ex instanceof NullPointerException){ modelAndView.setViewName("index"); } if(ex instanceof ArithmeticException){ modelAndView.setViewName("index"); } return modelAndView; } }
155、單點登錄
1、概念
單點登錄SSO,說的是在一個多系統共存的環境下,用戶在一處登錄後,就不用在其他系統中登錄,也就是用戶的一次登錄能得到其他所有系統的信任。
2、單點登錄的要點
- 存儲信任;
- 驗證信任;
3、實現單點登錄的三種方式
(1)以cookie作為憑證
最簡單的單點登錄實現方式,是使用cookie作為媒介,存放用戶憑證。
用戶登錄父應用之後,應用返回一個加密的cookie,當用戶訪問子應用的時候,攜帶上這個cookie,授權應用解密cookie進行校驗,校驗通過則登錄當前用戶。
缺點:
cookie不安全
通過加密可以保證安全性,但如果對方掌握瞭解密算法就完蛋瞭。
不能跨域實現免登
(2)通過JSONP實現
對於跨域問題,可以使用JSONP實現。用戶在父應用中登錄後,跟session匹配的cookie會存到客戶端中,當用戶需要登錄子應用的時候,授權應用訪問父應用提供的JSONP接口,並在請求中帶上父應用域名下的cookie,父應用接收到請求,驗證用戶的登錄狀態,返回加密的信息,子應用通過解析返回來的加密信息來驗證用戶,如果通過驗證則登錄用戶。
缺點:
這種方法雖然能解決跨域問題,但是治標不治本,沒有解決cookie安全性的問題。
(3)通過頁面重定向的方式
最後一種介紹的方式,是通過父應用和子應用來回重定向進行通信,實現信息的安全傳遞。
父應用提供一個GET方式的登錄接口A(此時的父應用接口固定,攻擊者無法去偽造),用戶通過子應用重定向連接的方式訪問這個接口
如果用戶還沒有登錄,則返回一個登錄頁面,用戶輸入賬號密碼進行登錄
如果用戶已經登錄瞭,則生成加密的token,並且重定向到子應用提供的驗證token的接口B(此時的子應用接口固定,攻擊者無法去偽造)
通過解密和校驗之後,子應用登錄當前用戶。
缺點:
這種方式較前面的兩種方式,是解決瞭安全性和跨域的問題,但是並沒有前面兩種方式簡單,安全與方便,本來就是矛盾的。
4、使用獨立登錄系統
一般來說,大型應用會把授權的邏輯和用戶信息的相關邏輯獨立成一個應用,稱為用戶中心。
用戶中心不處理業務邏輯,隻是處理用戶信息的管理以及授權給第三方應用。
第三方應用需要登錄的時候,則把用戶的登錄請求轉發給用戶中心進行處理,用戶處理完畢後返回憑證,第三方應用驗證憑證,通過後就登錄用戶。
5、sso(單點登錄)與OAuth2.0(授權)的區別?
(1)sso(單點登錄)
- 通常處理的是一個公司的不同應用間的訪問登錄問題,如企業應用有很多子系統,隻需登錄一個系統,就可以實現不同子系統間的跳轉,而避免瞭登錄操作;
- 通過cookie、jsonp、重定向來實現;
(2)OAuth2.0(授權)
解決的是服務提供方(如微信)給第三方應用授權的問題,簡稱微信登錄;
是一種具體的協議,隻是為用戶資源的授權提供瞭一個安全的、開放的而又簡易的標準,OAuth2.0(授權)為客戶開發者開發web應用,桌面應用程序,移動應用及客廳設備提供特定的授權流程。
156、Spring Boot比Spring多哪些註解
Spring Boot常用註解(絕對經典)
157、打包和部署
Spring和Spring Boot都支持maven和Gradle通用打包管理技術。
Spring Boot相對Spring的一些優點:
- 提供嵌入式容器支持;
- 使用命令java -jar獨立運行jar;
- 部署時可以靈活指定配置文件;
最近項目是分佈式的項目,都是通過分項目打包部署,然後部署在docker中運行。
158、Spring Boot如何訪問不同的數據庫
可以使用druidDataSource創建DataSource,然後通過jdbcTemplate執行sql。
159、查詢網站在線人數
通過監聽session對象的方式來實現在線人數的統計和在線人信息展示,並且讓超時的自動銷毀。
對session對象實現監聽,首先必須繼承HttpSessionListener類,該程序的基本原理就是當瀏覽器訪問頁面的時候必定會產生一個session對象,當關閉該頁面的時候必然會刪除session對象。
所以每當產生一個新的session對象就讓在線人數+1,當刪除一個session對象就讓在線人數-1。
還要繼承一個HttpSessionAttributeListener,來實現對其屬性的監聽。
分別實現attributeAdded方法,attributeReplace方法以及attributeRemove方法。
sessionCreated//新建一個會話的時候觸發,也可以說是客戶端第一次喝服務器交互時觸發。
sessionDestroyed//銷毀會話的時候,一般來說隻有某個按鈕觸發進行銷毀,或者配置定時銷毀。
HttpSessionAttributeListener有三個方法需要實現
attributeAdded//在session中添加對象時觸發此操作 籠統的說就是調用setAttribute這個方法時候會觸發的
attributeRemoved//修改、刪除session中添加對象時觸發此操作 籠統的說就是調用 removeAttribute這個方法時候會觸發的
attributeReplaced//在Session屬性被重新設置時。
160、easyExcel如何實現
異步讀取
新建一個 ExcelModelListener 監聽類出來,並且 繼承 AnalysisEventListener 類
package com.zh.oukele.listener; import com.alibaba.excel.context.AnalysisContext; import com.alibaba.excel.event.AnalysisEventListener; import com.zh.oukele.model.ExcelMode; import java.util.ArrayList; import java.util.List; /*** * 監聽器 */ public class ExcelModelListener extends AnalysisEventListener<ExcelMode> { /** * 每隔5條存儲數據庫,實際使用中可以3000條,然後清理list ,方便內存回收 */ private static final int BATCH_COUNT = 5; List<ExcelMode> list = new ArrayList<ExcelMode>(); private static int count = 1; @Override public void invoke(ExcelMode data, AnalysisContext context) { System.out.println("解析到一條數據:{ "+ data.toString() +" }"); list.add(data); count ++; if (list.size() >= BATCH_COUNT) { saveData( count ); list.clear(); } } @Override public void doAfterAllAnalysed(AnalysisContext context) { saveData( count ); System.out.println("所有數據解析完成!"); System.out.println(" count :" + count); } /** * 加上存儲數據庫 */ private void saveData(int count) { System.out.println("{ "+ count +" }條數據,開始存儲數據庫!" + list.size()); System.out.println("存儲數據庫成功!"); } }
161、什麼是 Swagger?你用 Spring Boot 實現瞭它嗎?
Swagger是用於生成RestFul Web服務的可視化表示工具,它使文檔和服務器可視化更新;
當定義好Swagger後,可以調用服務端接口,來查看接口的返回值,驗證返回數據的正確性;
162、數據庫的三范式是什麼?
1、列不可再分;
2、每一行數據隻做一件事,隻與一列相關,主鍵;
3、每個屬性都與主鍵有直接關系,而不是間接關系;
三大范式隻是設計數據庫的基本理念,可以建立冗餘較小、結構合理的數據庫。
如果有特殊情結,當然要特殊對待,數據庫設計最重要的是看需求和性能,需求>性能>表結構。
所以不能一味的追求三范式建立數據庫。
163、一張自增表裡面總共有 7 條數據,刪除瞭最後 2 條數據,重啟 mysql 數據庫,又插入瞭一條數據,此時 id 是幾?
一般情況下,我們創建的表類型是InnoDB。
- 不重啟MySQL,如果新增一條記錄,id是8;
- 重啟,ID是6;因為InnoDB表隻把自增主鍵的最大ID記錄在內存中,如果重啟,已刪除的最大ID會丟失。
- 如果表類型是MyISAM,重啟之後,最大ID也不會丟失,ID是8;
InnoDB必須有主鍵(建議使用自增主鍵,不用UUID,自增主鍵索引查詢效率高)、支持外鍵、支持事務、支持行級鎖。
系統崩潰後,MyISAM很難恢復;
綜合考慮,優先選擇InnoDB,MySQL默認也是InnoDB。
164、如何獲取當前數據庫版本?
//MySQL,,mysql -v select version(); //Oracle select * from v$version;
165、說一下 ACID 是什麼?
ACID是數據庫事務執行的四大基本要素,包括原子性(Atomicity)、一致性(Consistency)、隔離性(Isolation)、持久性(Durability)。
1、原子性
整個事務中的所有操作,要麼全部完成,要不全部不完成,不可能停滯在中間某個環節。
事務在執行過程中發生錯誤,會被roolback回滾到事務開始前的狀態,就像這個事務從未執行過一樣。
2、一致性
事務必須始終保持系統處於一致的狀態,不管在任何給定的時間並發事務有多少。
3、隔離性
隔離狀態執行事務,使他們好像是系統在給定時間內執行的唯一操作。
如果有兩個事務,運行在相同的時間內,執行相同的功能,事務的隔離性確保每一個事務在系統中認為隻有自己在使用系統。
這種屬性稱為串行化,為瞭防止事務操作間的混淆,必須串行化或序列化請求,使得在同一時間僅有一個請求用於同一數據。
4、持久性
一個成功的事務將永久的改變系統的狀態。
166、char 和 varchar 的區別是什麼?
- char的長度是固定的,varchar的長度的可變的;
- char的效率比varchar的效率高;
- char占用空間比varchar大,char在查詢時需要使用trim;
167、float 和 double 的區別是什麼?
1、float 和 double 的區別是什麼?
(1)內存中占有的字節數不同
- 單精度浮點數在內存中占有4個字節;
- 雙精度浮點數在內存中占有8個字節;
(2)有效數字位數不同
- 單精度浮點數有效數字8位;
- 雙精度浮點數有效數字16位;
(3)數值取值范圍不同
- 單精度浮點數的表示范圍:-3.40E+38~3.40E+38
- 雙精度浮點數的表示范圍:-1.79E+308~-1.79E+308
(4)在程序中處理速度不同
一般來說,CPU處理單精度浮點數的速度比雙精度浮點數的速度快
如果不聲明,默認小數是double類型,如果想用float,要進行強轉;
2、例如
float f = 1.3;會編譯報錯,正確的寫法是float f = (float)1.3;或者float a = 1.3f;(f或F都可以不區分大小寫)
3、註意
float是八位有效數字,第七位會四舍五入;
4、面試題
(1)java中3*0.1==0.3將會返回什麼?true還是false?
答:返回false,因為浮點數不能完全精確的表示出來,一般會損失精度;
(2)java中float f = 3.4;是否正確?
答:不正確。因為3.4是雙精度浮點數,將雙精度賦給單精度屬於向下轉型,會造成精度損失,因此需要強制類型轉換float=(float)3.4;或者寫成float f = 3.4f;
168、Oracle分頁sql
#不帶排序的 SELECT * FROM ( SELECT ROWNUM AS rowno, t.* FROM worker t where ROWNUM <=20) table_alias WHERE table_alias.rowno > 10;
#帶排序的 SELECT * FROM ( SELECT tt.*, ROWNUM AS rowno FROM ( SELECT t.* FROM worker t ORDER BY wkid aSC) tt WHERE ROWNUM <= 20) table_alias WHERE table_alias.rowno >= 10;
169、數據庫如何保證主鍵唯一性
1、主鍵約束
主鍵列上沒有任何兩行具有相同值(即重復值),不允許空(NULL);
2、唯一性約束
保證一個字段或者一組字段裡的數據都與表中其它行的對應數據不同。
和主鍵約束不同,唯一性約束允許為null,但是隻能有一行;
3、唯一性索引
不允許具有索引值相同的行,從而禁止重復的索引和鍵值;
4、三者的區別
- 約束是用來檢查數據的正確性;索引是用來優化查詢的;
- 創建唯一性約束會創建一個約束和一個唯一性索引;
- 創建唯一性索引隻會創建一個唯一性索引;
- 主鍵約束和唯一性約束都會創建一個唯一性索引
170、如何設計數據庫
1、數據庫設計最起碼要占用這個項目開發的40%以上的時間
2、數據庫設計不僅僅停留在頁面demo的表面
頁面內容所需字段,在數據庫設計中隻是一部分,還有系統運轉、模塊交互、中轉數據、表之間的聯系等等所需要的字段
因此數據庫設計絕對不是簡單的基本數據存儲,還有邏輯數據存儲。
3、數據庫設計完成後,項目80%的設計開發都要存在你的腦海中
每個字段的設計都要有他存在的意義,要清楚的知道程序中如何去運用這些字段,多張表的聯系在程序中是如何體現的。
4、數據庫設計時就要考慮效率和優化問題
數據量大的表示粗粒度的,會冗餘一些必要字段,達到用最少的表,最弱的表關系去存儲海量的數據。
大數據的表要建立索引,方便查詢。對於含有計算、數據交互、統計這類需求時,還有考慮是否有必要采用存儲過程。
5、添加必要的冗餘字段
像創建時間、修改時間、操作用戶IP、備註這些字段,在每張表中最好都有,一些冗餘的字段便於日後維護、分析、拓展而添加。
6、設計合理的表關聯
若兩張表之間的關系復雜,建議采用第三張映射表來關聯維護兩張表之間的關系,以降低表之間的直接耦合度。
7、設計表時不加主外鍵等約束關聯,系統編碼階段完成後再添加約束性關聯
8、選擇合適的主鍵生成策略
數據庫的設計難度其實比單純的技術實現難很多,他充分體現瞭一個人的全局設計能力和掌控能力,最後說一句,數據庫設計,很重要,很復雜。
171、性別是否適合做索引
區分度不高的字段不適合做索引,因為索引頁是需要有開銷的,需要存儲的,不過這類字段可以做聯合索引的一部分。
172、如何查詢重復的數據
1、查詢重復的單個字段(group by)
select 重復字段A, count(*) from 表 group by 重復字段A having count(*) > 1
2、查詢重復的多個字段(group by)
select 重復字段A, 重復字段B, count(*) from 表 group by 重復字段A, 重復字段B having count(*) > 1
173、數據庫一般會采取什麼樣的優化方法?
1、選取適合的字段屬性
- 為瞭獲取更好的性能,可以將表中的字段寬度設得盡可能小。
- 盡量把字段設置成not null執行查詢的時候,數據庫不用去比較null值。
- 對某些省份或者性別字段,將他們定義為enum類型,enum類型被當做數值型數據來處理,而數值型數據被處理起來的速度要比文本類型塊很多。
2、使用join連接代替子查詢
3、使用聯合union來代替手動創建的臨時表
註意:union用法中,兩個select語句的字段類型要匹配,而且字段個數要相同。
4、事務
要麼都成功,要麼都失敗。
可以保證數據庫中數據的一致性和完整性。
事務以begin開始,commit關鍵字結束。
如果出錯,rollback命令可以將數據庫恢復到begin開始之前的狀態。
事務的另一個重要作用是當多個用戶同時使用相同的數據源時,它可以利用鎖定數據庫的方式為用戶提供一種安全的訪問方式,這樣就可以保證用戶的操作不被其他的用戶幹擾。
5、鎖定表
盡管事務是維護數據庫完整性的一個非常好的方法,但卻因為它的獨占性,有時會影響數據庫的性能,尤其是在大應用中。
由於在事務執行的過程中,數據庫會被鎖定,因此其它用戶隻能暫時等待直到事務結束。
有的時候可以用鎖定表的方法來獲得更好的性能,
共享鎖:其它用戶隻能看,不能修改
lock table person in share mode;
對於通過lock table 命令主動添加的鎖來說,如果要釋放它們,隻需發出rollback命令即可。
6、使用外鍵
鎖定表的方法可以維護數據的完整性,但是它卻不能保證數據的關聯性,這個時候可以使用外鍵。
7、使用索引
索引是提高數據庫查詢速度的常用方法,尤其是查詢語句中包含max()、min()、order by這些命令的時候,性能提高更為顯著。
一般來說索引應該建在常用於join、where、order by的字段上。盡量不要對數據庫中含有大量重復的值得字段建立索引。
8、優化的查詢語句
在索引的字段上盡量不要使用函數進行操作。
盡量不要使用like關鍵字和通配符,這樣做法很簡單,但卻是以犧牲性能為代價的。
避免在查詢中進行自動類型轉換,因為類型轉換也會使索引失效。
174、索引怎麼定義,分哪幾種
- b-tree索引,如果不建立索引的情況下,oracle就自動給每一列都加一個B 樹索引;
- normal:普通索引
- unique:唯一索引
- bitmap:位圖索引,位圖索引特定於隻有幾個枚舉值的情況,比如性別字段;
- 基於函數的索引
175、mysql 的內連接、左連接、右連接有什麼區別?
- 內連接,顯示兩個表中有聯系的所有數據;
- 左鏈接,以左表為參照,顯示所有數據,右表中沒有則以null顯示
- 右鏈接,以右表為參照顯示數據,,左表中沒有則以null顯示
176、RabbitMQ的使用場景有哪些?
1、解決異步問題
例如用戶註冊,發送郵件和短信反饋註冊成功,可以使用RabbitMQ消息隊列,用戶無需等待反饋。
2、服務間解耦
訂單系統和庫存系統,中間加入RabbitMQ消息隊列,當庫存系統出現問題時,訂單系統依舊能正常使用,降低服務間耦合度。
3、秒殺系統
利用RabbitMQ的最大值,實現秒殺系統。
177、RabbitMQ有哪些重要的角色?有哪些重要的組件?
1、RabbitMQ有哪些重要的角色?
客戶端、RabbitMQ、服務端。
2、有哪些重要的組件?
(1)connectionFactory(連接管理器)
應用程序與RabbitMQ之間建立連接的管理器。
(2)Channel(信道)
消息推送使用的信道。
(3)RoutingKey(路由鍵)
用於把生產者的數據分配到交換機上。
(4)Exchange(交換機)
用於接受和分配消息。
(5)BindKey(綁定鍵)
用於把交換機的消息綁定到隊列上
(6)Queue(隊列)
用於存儲生產者消息。
178、RabbitMQ中 vhost 的作用是什麼?
vhost可以理解為mini版的RabbitMQ,其內部均含有獨立的交換機、綁定、隊列,最重要的是擁有獨立的權限系統,可以做到vhost范圍內的用戶控制。
從RabbitMQ全局考慮,不同的應用可以跑在不同的vhost上,作為不同權限隔離的手段。
179、說一下 jvm 的主要組成部分?及其作用?
JVM包括類加載子系統、堆、方法區、棧、本地方法棧、程序計數器、直接內存、垃圾回收器、執行引擎。
1、類加載子系統
類加載子系統負責加載class信息,加載的類信息存放於方法區中。
2、直接內存
直接內存是在Java堆外的、直接向系統申請的內存空間。訪問直接內存的速度會由於Java堆。
出於性能的考慮,讀寫頻繁的場合可能會考慮使用直接內存。
3、垃圾回收器
垃圾回收器可以對堆、方法區、直接內存進行回收。
4、執行引擎
執行引擎負責執行虛擬機的字節碼,虛擬機會使用即時編譯技術將方法編譯成機器碼後再執行。
180、說一下 jvm 運行時數據區?
運行時數據區包括堆、方法區、棧、本地方法棧、程序計數器。
1、堆
堆解決的是對象實例存儲的問題,垃圾回收器管理的主要區域。
2、方法區
方法區可以認為是堆的一部分,用於存儲已被虛擬機加載的信息,常量、靜態變量、即時編譯器編譯後的代碼。
3、棧
棧解決的是程序運行的問題,棧裡面存的是棧幀,棧幀裡面存的是局部變量表、操作數棧、動態鏈接、方法出口等信息。
(1)棧幀
每個方法從調用到執行的過程就是一個棧幀在虛擬機棧中入棧到出棧的過程。
(2)局部變量表
用於保存函數的參數和局部變量。
(3)操作數棧
操作數棧又稱操作棧,大多數指令都是從這裡彈出數據,執行運算,然後把結果壓回操作數棧。
4、本地方法棧
與棧功能相同,本地方法棧執行的是本地方法,一個Java調用非Java代碼的接口。
5、程序計數器(PC寄存器)
程序計數器中存放的是當前線程所執行的字節碼的行數。JVM工作時就是通過改變這個計數器的值來選取下一個需要執行的字節碼指令。
到此這篇關於Java經典面試題最全匯總208道(五)的文章就介紹到這瞭,更多相關Java面試題內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- MySQL為Null會導致5個問題(個個致命)
- Laravel操作session和cookie的教程詳解
- Java Session會話追蹤原理深入分析
- Java Springboot之Spring傢族的技術體系
- SpringMVC處理數據輸出的實例代碼