面試問題記錄 三 (JavaWeb、JavaEE)

余月七發表於2021-08-02

前言

這塊還是比較關鍵的,考察你對整個業務流程的熟練度吧,雖然企業級的專案沒有接觸過,但像最基本的內容必須得融會貫通,這一點我感覺自己還是處於淺層,沒有深入的去思考以及練習過,其實就像那句話,“打字速度不夠,說明你敲的程式碼不夠多”,其實有時候最原始的方法是最簡單有效的,雖然會耗大量時間,但一件事有利就有弊,所以還是加強自身程式碼熟練度。
還是那句話,如果文中有明顯錯誤,勞煩請及時糾正我,在這不勝感激!!!


一、JavaWeb

1.解釋一下Servlet以及生命週期?

答:servlet就是sun公司開發動態web程式的一門技術,通過前端請求,伺服器端進行邏輯判斷,完成對前端的響應;生命週期大致可分為三個階段,初始化階段、執行階段、銷燬階段;首先初始化階段會呼叫init()方法對servlet物件的初始化,二是通過呼叫service方法來處理和響應客戶端的請求,三是通過呼叫destroy方法表示伺服器資源已經被移除。而我們一般是通過繼承HttPServlet這個抽象類,因為這個類對servlet預設方法有實現而且也新增自己的方法,然後平時用的較多的就是doPost和doGet方法。

2.Cookie和Session有什麼區別以及工作原理?

答:首先Http協議是無狀態的,所以伺服器端需要確認使用者狀態時,就得有某種機制去記錄;cookie是提供給客戶端的技術,session是提供給伺服器端的技術;客戶端第一次請求伺服器端時,伺服器端會產生一個session物件,來用於儲存客戶資訊,並且每個session都有唯一的sessionID與之對應,用來區分session,然後伺服器端會產生一個cookie,此時cookie中name=JSESSIONID引數,然後value值是和sessionID的值是一樣的,當伺服器端響應給客戶端的同時,將cookie傳送給客戶端,然後客戶端就有一個JSESSIONID與伺服器端sessionID一一對應。當第二次請求時,伺服器端會先用客戶端的JSESSIONID去匹配session中的sessionID。cookie儲存的內容較為不安全,內容是String型別的,而session中儲存在伺服器這塊,較為安全,內容是object型別的。一般是瀏覽器關了後cookie就過期了,當然這也跟設定過期時間有關。

4.談一下SQL隱碼攻擊

答:就是對使用者輸入的資料沒有進行合法性沒有判斷,也沒有過濾,然後攻擊者可以通過特殊的字元提交,改變SQL執行的結果,實現非法操作。基本上後端都是用預編譯PreparedStatement物件,或者增加正規表示式來防止SQL隱碼攻擊。目前瞭解就這麼多。

5.說一下XSS攻擊

答:跨站指令碼攻擊,不需要使用者去登入認證,然後通過合法操作在頁面中注入指令碼,然後操控使用者瀏覽器,類似SQL隱碼攻擊。

6.CSRF攻擊是什麼?如何避免?

答:跨站請求偽造攻擊,誘使使用者登入認證第三方網站,然後通過使用者認證憑證繞過後臺驗證,然後冒充使用者從而去達到某項操作的目的。比如盜取賬號、轉賬、釋出虛假資訊。驗證碼和token都是比較用的多的防範措施。

7.doGet和doPost有什麼區別?

答:兩種方式主要針對get和post方法,而get一般用來獲取資料,因為它請求的資料會附加在URL上,而且get引數有長度限制,get請求還會儲存在瀏覽器記錄中,而post方式更適合提交資料,相比get方式更加安全,因為它是將header先發過去,然後通過伺服器判斷再傳送data,而且它也是放在請求體中的,雖然通過抓包可以看見,但至少比get明文傳輸的稍微安全一些。且post引數大小是無限制。


[提一些需要知道的JSP知識,個人感覺這一方面的知識還是要懂的]

JSP與Servlet的區別?

答:JSP本質上就是Servlet,JSP首先通過翻譯成servlet,然後再將servlet編譯成“.class”檔案,然後其中java程式碼在伺服器端執行,最終通過out.write()方法將HTML內容傳送到瀏覽器進行解析。
image

JSP內建物件

答:九大內建物件,1是request封裝客戶端請求,2是response封裝伺服器端請求,3是pageContext通過該物件可以獲得其他物件,4是session封裝使用者會話的物件,5是application封裝伺服器端執行環境的物件,6是page JSP本身物件,7是config web應用配置物件,8是out 輸出伺服器端響應的輸出流物件,9是exception封裝頁面丟擲異常的物件。

JSP作用域

答:四種作用域;page表示一個頁面相關的物件和屬性;request表示客戶端向伺服器發出的請求,產生的資料,臨時性的,常見於新聞這型別;session表示一次會話,就是傳送請求後,產生的資料,一會還有用。比如購物車;application表示傳送的請求,產生的資料,一個使用者用完別的使用者還能繼續用,全域性作用域。


二、JavaEE

I.Spring

1.說一下IOC

答:IOC就是控制反轉,控制就是傳統的是由程式本身建立物件,現在交給spring容器去建立,反轉就是程式不去建立物件而是去被動的接收物件;而具體的一種實現方式就是依賴注入,注入方式的話就有構造器注入(預設無參構造,有參通過下標、引數名、型別賦值)和setter方式注入、註解方式注入;而依賴就是bean物件的建立是由容器完成的,注入就是bean物件中的屬性都由容器來注入。最終還是為了解耦合。
參考文章:《Spring:原始碼解讀Spring IOC原理》https://www.cnblogs.com/ITtangtang/p/3978349.html

2.說一下AOP

答:理解AOP的話,就得首先對Java的代理模式有認識;代理模式的話可以去看一下這個狂神的視訊【https://www.bilibili.com/video/BV1WE411d7Dv?p=17】
AOP面向切面程式設計,簡單說就是那些與業務無關,卻為業務模組所共同呼叫的邏輯或責任封裝起來,便於減少系統的重複程式碼,降低模組之間的耦合度,並有利於未來的可操作性和可維護性
參考文章:《Spring3:AOP》 https://www.cnblogs.com/xrq730/p/4919025.html

3.Bean的作用域

答:官方文件作用域有六種,一是單例模式也就是單個bean定義範圍只有單個例項,二是原型模式,每次從容器中get時,就會產生新的例項,剩下的request(一次請求中存活)、session(一個session會話中存活)、application(全域性存活)、websocket都在web中用到。

4.Bean的自動裝配

答:兩種裝配,一是xml中的顯式配置、java中的顯式配置、二是隱式自動裝配bean(一種是byName會自動在容器上下文中找和自己物件set方法後面值對應的bean id,即需要保證所有的bean的id唯一;一種是byType會在容器上下文中找,和自己物件屬性型別相同的bean,即需要保證所有bean的class唯一);


II.SpringMVC

1.說一下SpringMVC的流程?

答:首先URL請求會傳送到前端控制器DispatcherServlet,然後DispatcherServlet尋找HandlerMapping處理器對映,通過HandlerExcution根據URL尋找處理器Handler,然後將資訊返回給DispatchServlet前端控制器,然後前端控制器去請求處理器介面卡HandlerAdapter,該介面卡通過給Controller去執行Handler,最後將檢視邏輯名或模型資料返回給前端控制器,然後前端控制器去呼叫檢視解析器去解析邏輯檢視名,然後將資訊返回給前端控制器,前端控制器再去呼叫具體檢視。
參考以下兩圖:
image
image


III.MyBatis

1.談一下你對MyBatis的理解?

答:MyBatis就是簡化了資料庫連線和操作,通過xml檔案或註解來對映原生型別,介面和簡單的實體類,而且沒有第三方的依賴。因為以前JDBC的話,在Java中運算元據庫,首先要載入驅動,配置一些連線引數,而且資料返回結果需要一個個遍歷賦值給我們寫的POJO,當需要變更一些驅動資訊時,會消耗很大一部分時間,而且都是重複性的工作,所以MyBatis的話就簡化了開發,鬆解了耦合。

2. #{} 與 ${} 的區別

答:#號是可以防止SQL隱碼攻擊問題,因為是預編譯的,相當於jdbc中佔位符“?”;$符號是直接替換的值,不安全的。能用#{}儘量用#{}。

3.MyBatis和MyBatis-Plus有什麼區別?

答:相對於Mybatis的話,以前需要每寫一個DAO就要有一個Mapper去對應運算元據庫,而Mybatis-Plus對mybatis做了增強,也就是將平時一些常用的CRUD運算元據庫語句做了封裝,簡化了一些重複性的操作。

4.MyBatis的一級快取和二級快取是怎樣的?

答:預設情況下,一級快取開啟,也就是SQLSession級別的快取,本地快取;二級快取基於namespace級別的快取,需要手動開啟,而且MyBatis為了提高擴充套件性,在其中定義了cache介面,通過介面去實現二級快取。


IV.SpringBoot

1.SpringBoot與普通的SpringMVC開發的區別?

答:SpringMVC是基於servlet的一個MVC框架主要解決WEB開發的問題,通過xml配置統一開發前端檢視和後端邏輯,提供一種輕度耦合的方式來開發web應用;SpringBoot專注於微服務方面的介面開發,和前端解耦,同時也解決了Spring配置的複雜,簡化了SpringMVC的開發流程;從而提供一種與Spring框架緊密結合用於提升開發者體驗的工具,同時它也整合了大量的第三方庫配置。
具體的理解可自行網上搜尋文章查閱,還是感覺只有在專案中才能更加的去理解這一部分的知識,所以平時還是要多做一些demo來梳理自己的對開發技術的理解

2.SpringBoot的核心註解有哪些?

答:目前是知道@SpringBootApplication複合註解,因為它包含了SpringBootConfiguration(標註當前類是配置類)、EnableAutoConfiguration(根據我們新增的jar元件來完成預設配置,比如mvc的配置和tomcat)、ComponentScan(掃描當前包以及子包中被Component、Controller、Service、Repository註解標記的類並納入Spring容器進行管理);@Controller表示這個類是個控制類,@RequestMapping一般是使用Rest風格,比如@GetMapping、@PostMapping等等;@CrossOrigin解決跨域訪問問題;@AutoWired是Spring的自動裝配;(其實像後面的這些註解都是Spring和SpringMVC中的,嚴格意義上來講我覺得也不算SpringBoot的,只有像第一個複合註解才是比較核心的,目前也是瞭解這麼多,還需後期不斷深入的學習理解

3.SpringBoot的自動裝配原理是怎樣的?

答:這個點我感覺自己把握也不是很好,所以找了點一些內容
狂神筆記內容:

//表示這是一個配置類,和以前編寫的配置檔案一樣,也可以給容器中新增元件;
@Configuration 

//啟動指定類的ConfigurationProperties功能;
  //進入這個HttpProperties檢視,將配置檔案中對應的值和HttpProperties繫結起來;
  //並把HttpProperties加入到ioc容器中
@EnableConfigurationProperties({HttpProperties.class}) 

//Spring底層@Conditional註解
  //根據不同的條件判斷,如果滿足指定的條件,整個配置類裡面的配置就會生效;
  //這裡的意思就是判斷當前應用是否是web應用,如果是,當前配置類生效
@ConditionalOnWebApplication(
    type = Type.SERVLET
)

//判斷當前專案有沒有這個類CharacterEncodingFilter;SpringMVC中進行亂碼解決的過濾器;
@ConditionalOnClass({CharacterEncodingFilter.class})

//判斷配置檔案中是否存在某個配置:spring.http.encoding.enabled;
  //如果不存在,判斷也是成立的
  //即使我們配置檔案中不配置pring.http.encoding.enabled=true,也是預設生效的;
@ConditionalOnProperty(
    prefix = "spring.http.encoding",
    value = {"enabled"},
    matchIfMissing = true
)

public class HttpEncodingAutoConfiguration {
    //他已經和SpringBoot的配置檔案對映了
    private final Encoding properties;
    //只有一個有參構造器的情況下,引數的值就會從容器中拿
    public HttpEncodingAutoConfiguration(HttpProperties properties) {
        this.properties = properties.getEncoding();
    }
    
    //給容器中新增一個元件,這個元件的某些值需要從properties中獲取
    @Bean
    @ConditionalOnMissingBean //判斷容器沒有這個元件?
    public CharacterEncodingFilter characterEncodingFilter() {
        CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
        filter.setEncoding(this.properties.getCharset().name());
        filter.setForceRequestEncoding(this.properties.shouldForce(org.springframework.boot.autoconfigure.http.HttpProperties.Encoding.Type.REQUEST));
        filter.setForceResponseEncoding(this.properties.shouldForce(org.springframework.boot.autoconfigure.http.HttpProperties.Encoding.Type.RESPONSE));
        return filter;
    }
    //。。。。。。。
}



 一句話總結 :根據當前不同的條件判斷,決定這個配置類是否生效!
 一但這個配置類生效;這個配置類就會給容器中新增各種元件; 
 
 這些元件的屬性是從對應的 properties 類中獲取的,這些類裡面的每一個屬性又是和配置檔案繫結的; 
 所有在配置檔案中能配置的屬性都是在 xxxxProperties 類中封裝著; 
 配置檔案能配置什麼就可以參照某個功能對應的這個屬性類 


//從配置檔案中獲取指定的值和bean的屬性進行繫結
@ConfigurationProperties(prefix = "spring.http") 
public class HttpProperties {
    // .....
}



精髓

1、SpringBoot 啟動會載入大量的自動配置類

2、我們看我們需要的功能有沒有在 SpringBoot 預設寫好的自動配置類當中;

3、我們再來看這個自動配置類中到底配置了哪些元件;(只要我們要用的元件存在在其中,我們就不需要再手動配置了)

4、給容器中自動配置類新增元件的時候,會從 properties 類中獲取某些屬性。我們只需要在配置檔案中指定這些屬性的值即可;

xxxxAutoConfigurartion:自動配置類;給容器中新增元件

xxxxProperties: 封裝配置檔案中相關屬性;

參考文章:《這樣講 SpringBoot 自動配置原理,你應該能明白了吧》《SpringBoot自動配置原理
本人無打廣告嫌疑!!!!


三、JVM

1.說說JVM記憶體結構?

答:ProcessOn上找的一張圖,看標註應該是尚矽谷的圖,感覺這個圖還是能初步認識JVM。
image
還有三張圖連結放這,自行檢視,感覺還是解釋的比較全面。
JVM記憶體模型完整版【https://www.processon.com/view/5ea7a1b9e401fd21c196eb17?fromnew=1
JVM相關知識https://www.processon.com/view/5ec5d7c60791290fe0768668?fromnew=1
JVM【https://www.processon.com/view/5c749debe4b0f9fba6921d15?fromnew=1

2.為什麼用雙親委派機制,它是什麼?

答:首先當某一個類載入器載入“.class”檔案的時候,會把任務交給上級類載入器,進行遞迴操作,也就是當上級類載入器都沒有載入,當前載入器才會去載入這個類;就比如:先從BootStrapClassLoader根載入器找,找不到則在ExtClassLoder擴充套件載入器找,如果還找不到,才會在當前AppClassLoader應用程式載入器找(一般是執行main方法)。雙親委派機制,它防止了去載入同一個“.class”檔案,而且保證了核心“.class”檔案被篡改,這樣保證了Class執行安全。
image
image


最後

關於這塊的知識,感覺還是注重實踐,因為許多概念上的東西,不通過自己去敲,去練的話,對這方面處於一種只知皮毛的狀態;其實我感覺我個人也是在表面上漂著,沒有去靜下心來去認真的思考過一個問題而且也沒有認真的去看過JDK的原始碼;一路走來,感覺就是沒真正的扎進去,通過幾次簡單的面試其實就能感覺到自己在 哪些方面的缺失,可以幫助自己找到更多的缺點。

那在這我也想總結一下自己的學習方式:對某塊東西的認識先從視訊看起,因為我感覺視訊還是快的,視訊和書各有各的好處吧,我感覺視訊可以快速入門,而且中間出現的錯誤也會有個影響;看完視訊的話,像JavaEE方面的知識點,個人覺得看官方文件來的比較快,比較有權威一點,畢竟網上的文章太多了,或者也可以通過某些人整理的簡化的官方文件,再去了解真正的官方文件。最後還是就是動手,個人感覺自己動的手太少了,所以對一些東西的理解不是很深;然後在一段時間內去總結一下自己學的東西,必須要總結,這樣可以提高自己的邏輯以及以後查閱起來自己學的知識點方便一些,可以簡單記錄,也可以詳細記錄,但一般我感覺能讓幾個月之後的自己看到自己寫的東西可以瞬間想起來整個思路的話就其實很好。

剩下的就是關於微服務這塊的知識,個人感覺這塊知識單單從平時的demo學習的話,理解其實比較淺,還是覺得應該在實習的時候去真正接觸專案的時候,再來去深入的學習一下這方面的知識,雖然現在很卷,但是實習的話,面試官也不會對分散式微服務問的太多,最多問一下一些基礎。當然可能畢業後,問的點比較多了。

也祝看到此篇隨筆的小夥伴,面試順利,成功拿到心儀Offer!!!


題外話

最近,也是偶然間看到了一個視訊,叫《經濟機器是怎樣執行的》,感覺像我這樣的經濟小白很有啟蒙作用!視訊的話B站有,可以直接搜。(放個有字幕的視訊連結地址:經濟機器是怎樣執行的 Ray Dalio(字幕)

人物介紹
雷·達利奧(英語:Raymond Dalio,1949年8月8日)出生於紐約,現居康乃狄克州費爾菲爾德縣,是美國的著名對衝基金經理、慈善家。瑞·達利奧是橋水基金公司的創始人兼執行長,而橋水基金於2013年被列為全世界最大的避險基金公司 [2][3]。達利奧於2017出版了關於企業管理金融經濟學的著作《原則》。根據彭博社報導,截至2019年1月,他是世界上最富有的100個人中的第79位[4]
早年生活
瑞·達利奧出生在一個義大利裔家庭,他的父親是一位音樂家。12歲時在林克斯高爾夫球場打工並受到那些僱主的耳濡目染下開始把賺來的錢拿來炒股。買進了人生第一支股票東北航空公司(Northeast Airlines)。而購買東北航空股票的原因是因為東北航空股價較低,瑞・逹利奧當時以為買的股數越多賺的錢也越多。最後結果是幸運的,成功賺了兩倍的錢,但其實是因為東北航空在即將破產之際被收購,才不至讓初買股票的瑞・逹利奧血本無歸。以後瑞·達利奧先後就讀於長島大學哈佛大學,並取得金融學本科學位和工商管理碩士學位。

如果有興趣的話可以去了解一下,感覺還是很有意思的,下面是MBA智庫中的介紹
連結https://wiki.mbalib.com/wiki/%E7%91%9E%E8%BE%BE%E5%88%A9%E6%AC%A7

相關文章