SpringBoot系列十三:SpringBoot面試常見問題
你覺得 SpringBoot 最大的優勢是什么呢?
答:SpringBoot 的最大的優勢是“約定優于配置“。“約定優于配置“是一種軟件設計范式,開發人員按照約定的方式來進行編程,可以減少軟件開發人員需做決定的數量,獲得簡單的好處,而又不失靈活性。
SpringBoot 中 “約定優于配置“的具體產品體現在哪里?
答:SpringBoot Starter、SpringBoot Jpa 都是“約定優于配置“的一種體現。都是通過“約定優于配置“的設計思路來設計的,SpringBoot Starter 在啟動的過程中會根據約定的信息對資源進行初始化;SpringBoot Jpa 通過約定的方式來自動生成 Sql ,避免大量無效代碼編寫。
SpringBoot Starter 的工作原理是什么?
答: SpringBoot 在啟動的時候,按照約定去讀取 SpringBoot Starter 的配置信息,再根據配置信息對資源進行初始化并注入到 Spring 容器中。這樣 SpringBoot 啟動完畢后,就已經準備好了一切資源,使用過程中直接注入對應 Bean 資源即可。
具體干了這幾件事情:
-
① SpringBoot 在啟動時會去依賴的 Starter 包中尋找 resources/META-INF/spring.factories 文件,然后根據文件中配置的 Jar 包去掃描項目所依賴的 Jar 包。
-
② 根據 spring.factories 配置加載 AutoConfigure 類
-
③ 根據 @Conditional 注解的條件進行自動配置并將帶有@Conditional注解的 Bean 注入 Spring Context
SpringBoot 的自動配置是如何實現的?
SpringBoot 項目的啟動注解是:@SpringBootApplication,是一個復合注解,由下面三個注解組成的:
-
@EnableAutoConfiguration
- @ComponentScan
- @Configuration
其中 @EnableAutoConfiguration注解是實現自動配置的入口,該注解又通過 @Import 注解導入了AutoConfigurationImportSelector類,在AutoConfigurationImportSelector類中加載 META-INF/spring.factories 的配置信息,然后篩選出以 EnableAutoConfiguration 為 key 的數據,加載到 IOC 容器中,實現自動配置功能!
方便理解記憶鏈條:
@EnableAutoConfiguration注解自動配置入口 -> @Import 注解 導入了AutoConfigurationImportSelector類 -> AutoConfigurationImportSelector類中加載 META-INF/spring.factories 配置 -> 篩選出以 EnableAutoConfiguration 為 key 的數據,加載到 IOC 容器中實現自動配置
什么是嵌入式服務器?我們為什么要使用嵌入式服務器呢?
思考一下在你的虛擬機上部署應用程序需要些什么。
第一步:安裝 Java
第二部:安裝 Web 或者是應用程序的服務器(Tomat/Wbesphere/Weblogic 等等)
第三部:部署應用程序 war 包
如果我們想簡化這些步驟,應該如何做呢?
讓我們來思考如何使服務器成為應用程序的一部分?
你只需要一個安裝了 Java 的虛擬機,就可以直接在上面部署應用程序了,
是不是很爽?
這個想法是嵌入式服務器的起源。
什么是嵌入式服務器:
當我們創建一個可以部署的應用程序的時候,我們將會把服務器(例如,tomcat)嵌入到可部署的應用程序中,這就是嵌入式服務器。
例如,對于一個 SpringBoot 應用程序來說,你可以生成一個包含 Embedded Tomcat 的應用程序 jar。你就可以像運行正常 Java 應用程序一樣來運行 web 應用程序了。
嵌入式服務器就是我們的可執行單元包含服務器的二進制文件(例如,tomcat.jar)。
使用嵌入式服務器的好處:
可以簡化傳統部署應用程序的步驟,只需要安裝Java虛擬機,然后直接部署應用程序即可。
SpringBoot 如何設置支持跨域請求?
現代瀏覽器出于安全的考慮, HTTP 請求時必須遵守同源策略,否則就是跨域的 HTTP 請求,默認情況下是被禁止的,IP(域名)不同、或者端口不同、協議不同(比如 HTTP、HTTPS)都會造成跨域問題。
一般前端的解決方案有:
-
① 使用 JSONP 來支持跨域的請求,JSONP 實現跨域請求的原理簡單的說,就是動態創建
<script>標簽,然后利用<script>的 SRC 不受同源策略約束來跨域獲取數據。缺點是需要后端配合輸出特定的返回信息。 -
② 利用反應代理的機制來解決跨域的問題,前端請求的時候先將請求發送到同源地址的后端,通過后端請求轉發來避免跨域的訪問。
后來 HTML5 支持了 CORS 協議。CORS 是一個 W3C 標準,全稱是”跨域資源共享”(Cross-origin resource sharing),允許瀏覽器向跨源服務器,發出 XMLHttpRequest 請求,從而克服了 AJAX 只能同源使用的限制。它通過服務器增加一個特殊的 Header[Access-Control-Allow-Origin]來告訴客戶端跨域的限制,如果瀏覽器支持 CORS、并且判斷 Origin 通過的話,就會允許 XMLHttpRequest 發起跨域請求。
前端使用了 CORS 協議,就需要后端設置支持非同源的請求,SpringBoot 設置支持非同源的請求有兩種方式。
第一,配置 CorsFilter。
1 @Configuration 2 public class GlobalCorsConfig { 3 @Bean 4 public CorsFilter corsFilter() { 5 CorsConfiguration config = new CorsConfiguration(); 6 config.addAllowedOrigin("*"); 7 config.setAllowCredentials(true); 8 config.addAllowedMethod("*"); 9 config.addAllowedHeader("*"); 10 config.addExposedHeader("*"); 11 12 UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource(); 13 configSource.registerCorsConfiguration("/**", config); 14 15 return new CorsFilter(configSource); 16 } 17 }
需要配置上述的一段代碼。第二種方式稍微簡單一些。
第二,在啟動類上添加:
public class Application extends WebMvcConfigurerAdapter { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowCredentials(true) .allowedHeaders("*") .allowedOrigins("*") .allowedMethods("*"); } }
Spring 、SpringBoot 和 SpringCloud 的關系?
Spring 最初最核心的兩大核心功能 Spring Ioc 和 Spring Aop 成就了 Spring,Spring 在這兩大核心的功能上不斷的發展,才有了 Spring 事務、Spring Mvc 等一系列偉大的產品,最終成就了 Spring 帝國,到了后期 Spring 幾乎可以解決企業開發中的所有問題。
SpringBoot 是在強大的 Spring 帝國生態基礎上面發展而來,發明 SpringBoot 不是為了取代 Spring ,是為了讓人們更容易的使用 Spring 。
SpringCloud 是一個微服務治理框架,基于SpringBoot實現,它利用 SpringBoot 的開發便利性巧妙地簡化了分布式系統基礎設施的開發。如服務發現注冊、配置中心、消息總線、負載均衡、斷路器、數據監控等,都可以用 SpringBoot 的開發風格做到一鍵啟動和部署。
SpringCloud 是為了解決微服務架構中服務治理而提供的一系列功能的開發框架,并且 SpringCloud 是完全基于 SpringBoot 而開發,SpringCloud 利用 SpringBoot 特性整合了開源行業中優秀的組件,整體對外提供了一套在微服務架構中服務治理的解決方案。
用一組不太合理的包含關系來表達它們之間的關系。
Spring ioc/aop > Spring > SpringBoot > SpringCloud
JPA 和 Hibernate 有哪些區別?JPA 可以支持動態 SQL 嗎?
JPA本身是一種ORM規范(不是ORM框架,因為JPA并未提供ORM實現,只是制定了規范)因為JPA是一種規范,所以,只是提供了一些相關的接口,但是接口并不能直接使用,JPA底層需要某種JPA實現,Hibernate 是 JPA 的一個實現集。
JPA 是根據實體類的注解來創建對應的表和字段,如果需要動態創建表或者字段,需要動態構建對應的實體類,再重新調用Jpa刷新整個Entity。動態SQL,mybatis支持的最好,jpa也可以支持,但是沒有Mybatis那么靈活。
shiro和oauth還有cas他們之間的關系是什么?問下您公司權限是如何設計,還有就是這幾個概念的區別。
cas和oauth是一個解決單點登錄的組件,shiro主要是負責權限安全方面的工作,所以功能點不一致。但往往需要單點登陸和權限控制一起來使用,所以就有 cas+shiro或者oauth+shiro這樣的組合。
token一般是客戶端登錄后服務端生成的令牌,每次訪問服務端會進行校驗,一般保存到內存即可,也可以放到其他介質;redis可以做Session共享,如果前端web服務器有幾臺負載,但是需要保持用戶登錄的狀態,這場景使用比較常見。
我們公司使用oauth+shiro這樣的方式來做后臺權限的管理,oauth負責多后臺統一登錄認證,shiro負責給登錄用戶賦予不同的訪問權限。
各服務之間通信,對Restful和Rpc這2種方式如何做選擇?
在傳統的SOA治理中,使用rpc的居多;SpringCloud默認使用restful進行服務之間的通訊。rpc通訊效率會比restful要高一些,但是對于大多數公司來講,這點效率影響甚微。我建議使用restful這種方式,易于在不同語言實現的服務之間通訊。

浙公網安備 33010602011771號