Java 面试知识点解析(七)——Web篇
- 前言:
在遨游了一番 Java Web 的世界之后,發(fā)現(xiàn)了自己的一些缺失,所以就著一篇深度好文:知名互聯(lián)網(wǎng)公司校招 Java 開(kāi)發(fā)崗面試知識(shí)點(diǎn)解析?,來(lái)好好的對(duì) Java 知識(shí)點(diǎn)進(jìn)行復(fù)習(xí)和學(xué)習(xí)一番,大部分內(nèi)容參照自這一篇文章,有一些自己補(bǔ)充的,也算是重新學(xué)習(xí)一下 Java 吧。
前序文章鏈接:
Java 面試知識(shí)點(diǎn)解析(一)——基礎(chǔ)知識(shí)篇
Java 面試知識(shí)點(diǎn)解析(二)——高并發(fā)編程篇
Java 面試知識(shí)點(diǎn)解析(三)——JVM篇
Java 面試知識(shí)點(diǎn)解析(四)——版本特性篇
Java 面試知識(shí)點(diǎn)解析(五)——網(wǎng)絡(luò)協(xié)議篇
Java 面試知識(shí)點(diǎn)解析(六)——數(shù)據(jù)庫(kù)篇
(一)J2EE 相關(guān)知識(shí)點(diǎn)
不涉及任何框架,對(duì) J2EE 相關(guān)知識(shí)點(diǎn)的解析
1)Servlet 的生命周期?
在 Web 容器中,Servlet 主要經(jīng)歷 4 個(gè)階段,如下圖:
1. 加載 Servlet:當(dāng) Tomcat 第一次訪問(wèn) Servlet 的時(shí)候,Tomcat 會(huì)負(fù)責(zé)創(chuàng)建 Servlet 的實(shí)例。
2. 初始化 Servlet:當(dāng) Servlet 被實(shí)例化之后,Tomcat 會(huì)調(diào)用 init() 方法來(lái)初始化這個(gè)對(duì)象。
3. 處理服務(wù):當(dāng)瀏覽器訪問(wèn) Servlet 的時(shí)候,Servlet 會(huì)調(diào)用 service() 方法處理請(qǐng)求。
4. 銷(xiāo)毀:當(dāng) Tomcat 關(guān)閉或者檢測(cè)到 Servlet 要從 Tomcat 刪除的時(shí)候,會(huì)自動(dòng)調(diào)用 destroy() 方法,讓該實(shí)例所占用的資源釋放掉。一個(gè) Servlet 如果長(zhǎng)時(shí)間不被使用的話,也會(huì)被 Tomcat 自動(dòng)銷(xiāo)毀。
- 簡(jiǎn)單總結(jié):只要訪問(wèn) Servlet ,就會(huì)調(diào)用其對(duì)應(yīng)的 service() 方法,init() 方法只會(huì)在第一次訪問(wèn) Serlvet 的時(shí)候才會(huì)被調(diào)用。
2)Servlet 的請(qǐng)求流程?
瀏覽器發(fā)出請(qǐng)求:?http://localhost:80/xxx1/xxx2?(80端口可以默認(rèn)不寫(xiě),因?yàn)檫@是http協(xié)議默認(rèn)的端口,平時(shí)我們?cè)L問(wèn)https://www.baidu.com/?時(shí)其實(shí)訪問(wèn)的是https://www.baidu.com:80/)
- http:協(xié)議名稱(chēng)
- localhost:訪問(wèn)的是互聯(lián)網(wǎng)中的哪一臺(tái)計(jì)算機(jī)
- 80:從主機(jī)當(dāng)中找到對(duì)應(yīng) 80 端口的程序?(這里即為 Tomcat 服務(wù)器)
- /xxx1:當(dāng)前項(xiàng)目的上下文路徑?(即在 server.xml 中配置主機(jī)時(shí)配置的?path屬性)
- /xxx2:當(dāng)前請(qǐng)求的資源名
<Context docBase="D:\javaPros\test\webapp" path="xxx1" />
判斷哪一個(gè)<Context />元素的?path屬性?屬性為?xxx1
- 若找不到,則返回?404錯(cuò)誤
- 若找到了,則解析該<Context />元素,得到docBase屬性,獲取當(dāng)前訪問(wèn) Web 項(xiàng)目的跟的絕對(duì)路徑:D:\javaPros\test\webapp
判斷?web.xml?文件中是否有?<url-pattern>?的文本內(nèi)容為?/xxx2
- 若找不到,則返回?404錯(cuò)誤
- 若找到了,則繼續(xù)獲取該資源對(duì)應(yīng) Servlet 類(lèi)的全限名稱(chēng):?xxx.xxx
使用反射調(diào)用構(gòu)造器,創(chuàng)建對(duì)應(yīng)的對(duì)象
obj = Class.forName("xxx.xxx").newInstance();
把當(dāng)前創(chuàng)建的?Servlet 對(duì)象,存放在緩存之中,供給下一次的使用.
cache.put("xxx.xxx",obj);
創(chuàng)建?ServletConfig 對(duì)象,并調(diào)用?init()?方法
obj.init(config);
創(chuàng)建?ServletRequest 對(duì)象和 ServletResponse 對(duì)象,并調(diào)用?service()方法
obj.service(req,resp);
在?service()?方法中對(duì)瀏覽器作出響應(yīng)操作。
3)Servlet 是單例的嗎?為什么?
Servlet 是單例的,瀏覽器多次對(duì)Servlet的請(qǐng)求,一般情況下,服務(wù)器只創(chuàng)建一個(gè)Servlet對(duì)象,也就是說(shuō),Servlet對(duì)象一旦創(chuàng)建了,就會(huì)駐留在內(nèi)存中,為后續(xù)的請(qǐng)求做服務(wù),直到服務(wù)器關(guān)閉。
4)GET 和 POST 的區(qū)別
要知道,GET 和 POST 都是請(qǐng)求方式
1. GET:
瀏覽器器地址欄:http://localhost/test.html?name=wmyskxz&sex=male
這里提交了兩個(gè)參數(shù),一個(gè)是name屬性值為wmyskxz,另一個(gè)是sex屬性值為male,這是一種直接的請(qǐng)求方式,在請(qǐng)求資源后面跟上???符號(hào)與參數(shù)連接,其他的參數(shù)使用?&?符號(hào)連接。
- 缺點(diǎn):
1.暴露請(qǐng)求信息,不安全
2.請(qǐng)求信息不能超過(guò)1kb,可傳輸?shù)男畔⒂邢?#xff0c;不能上傳圖片
2. POST:
瀏覽器地址欄:http://localhost/test.html#
- 優(yōu)點(diǎn):
1.隱藏了請(qǐng)求信息,較安全(但仍可以通過(guò)相關(guān)工具訪問(wèn)到數(shù)據(jù))
2.POST 方式沒(méi)有限制請(qǐng)求的數(shù)據(jù)大小,可以做圖片的上傳
5)Tomcat 中如何解決中文亂碼問(wèn)題?
在?Tomcat 服務(wù)器中,接受請(qǐng)求的時(shí)候,默認(rèn)的編碼方式為 ISO-8859-1,而該編碼方式只占一個(gè)字節(jié),不支持中文(兩個(gè)字節(jié)),所以當(dāng)我們做請(qǐng)求的時(shí)候,會(huì)出現(xiàn)亂碼的問(wèn)題
解決方案:
1.對(duì)亂碼使用?ISO-8859-1?解碼,轉(zhuǎn)換成byte數(shù)組,恢復(fù)為二進(jìn)制
byte[] data = name.getBytes("ISO-8859-1");
2.對(duì)byte數(shù)組重新進(jìn)行 UTF-8 編碼:
name = new String(data,"UTF-8");
但是這樣會(huì)出現(xiàn)一個(gè)問(wèn)題,那就是當(dāng)表單數(shù)據(jù)太多的時(shí)候,這樣反復(fù)解碼-編碼,會(huì)很繁瑣。
終極解決方案:
1.對(duì)于 POST 請(qǐng)求:
設(shè)置請(qǐng)求的編碼方式:request.setCharacterEncoding("UTF-8");
注意:必須在獲取第一個(gè)參數(shù)之前設(shè)置,并且該方式只對(duì) POST 方式有效。
2.對(duì)于 GET 請(qǐng)求:
重新設(shè)置 Tomcat 的編碼方式,修改 Tomcat 的配置文件:
Tomcat根目錄/conf/server.xml(修改端口的那一行)
6)forward 與 redirect 的區(qū)別
1.請(qǐng)求轉(zhuǎn)發(fā)(forward)
又叫做直接轉(zhuǎn)發(fā)方式,客戶(hù)端和瀏覽器只發(fā)出一次請(qǐng)求,Servlet、HTML、JSP或其它信息資源,由第二個(gè)信息資源響應(yīng)該請(qǐng)求,在請(qǐng)求對(duì)象request中,保存的對(duì)象對(duì)于每個(gè)信息資源是共享的。
比如:從 AServlet 請(qǐng)求轉(zhuǎn)發(fā)到 BServlet
- 語(yǔ)法:
參數(shù):?path,要跳轉(zhuǎn)到的資源路徑:上下文路徑 / 資源路徑
特點(diǎn):
1.地址欄中的地址【不會(huì)】改變,通常看作是服務(wù)端的跳轉(zhuǎn)
2.只有一個(gè)請(qǐng)求
3.資源是共享的
也就是說(shuō)在兩個(gè) Servlet 中可以共享請(qǐng)求的資源,可以通過(guò)request.setAttribute(String var1,Object var2)設(shè)置要共享的數(shù)據(jù)資源,并通過(guò)request.getAttribute(String var1);來(lái)獲取傳遞的資源
4.【可以】訪問(wèn) WEB-INF 中的資源
WEB-INF?文件夾是 Java Web 應(yīng)用的默認(rèn)安全目錄,即客戶(hù)端無(wú)法直接訪問(wèn),只有服務(wù)端可以訪問(wèn)的目錄。如果想在頁(yè)面中直接訪問(wèn)其中的文件,必須通過(guò)web.xml文件對(duì)要訪問(wèn)的文件進(jìn)行相應(yīng)映射才能訪問(wèn)。
注意:在實(shí)際的開(kāi)發(fā)中,可以把不希望用戶(hù)直接訪問(wèn)到(通過(guò)瀏覽器輸入地址欄)的網(wǎng)頁(yè)放在文件夾中通過(guò)此方式訪問(wèn)。
5.請(qǐng)求轉(zhuǎn)發(fā)【不能】跨域訪問(wèn)
所謂的同域,是指域名,協(xié)議,端口均相同
2.URl 重定向(redirect)
又叫做間接轉(zhuǎn)發(fā)方式(Redirect)實(shí)際是兩次HTTP請(qǐng)求,服務(wù)器端在響應(yīng)第一次請(qǐng)求的時(shí)候,讓瀏覽器再向另外一個(gè)URL發(fā)出請(qǐng)求,從而達(dá)到轉(zhuǎn)發(fā)的目的。
比如:從AServlet重定向到BServlet
- 語(yǔ)法:
參數(shù):location,轉(zhuǎn)發(fā)到的資源路徑
特點(diǎn):
1.地址欄中的地址【會(huì)】發(fā)生改變,通常看作是客戶(hù)端跳轉(zhuǎn)
2.有兩個(gè)請(qǐng)求
3.在兩個(gè) Servlet 中不可以共享請(qǐng)求中的數(shù)據(jù)
4.最終的響應(yīng)由 BServlet 來(lái)決定,和 AServlet 沒(méi)有關(guān)系
5.【不可以】訪問(wèn) WEB-INF 中的資源
6.請(qǐng)求轉(zhuǎn)發(fā)【能】跨域訪問(wèn)
就像是在網(wǎng)頁(yè)中點(diǎn)開(kāi)了新的鏈接一樣
- 總結(jié):URL 重定向相當(dāng)于是將重定向的資源路徑,重新復(fù)制到瀏覽器地址欄中按下回車(chē)一樣,重新發(fā)送一次新的請(qǐng)求。
7)JSP 的執(zhí)行原理?
當(dāng)訪問(wèn)一個(gè) JSP 頁(yè)面時(shí),該頁(yè)面請(qǐng)求將會(huì)講給服務(wù)器中的?JSP 引擎去處理,它負(fù)責(zé)解釋和執(zhí)行 JSP 頁(yè)面,每個(gè) JSP 頁(yè)面在第一次被訪問(wèn)時(shí),JSP 引擎就會(huì)將它翻譯成一個(gè)繼承自?org.apache.jasper.runtime.HttpJspBase類(lèi)的?Servlet 源程序,接著再編譯成 class 類(lèi)文件,再由 Web 容器像調(diào)用普通 Servlet 程序一樣的方式來(lái)裝載和解釋執(zhí)行這個(gè)由 JSP 頁(yè)面翻譯成的 Servlet 程序。
8)request.getAttribute() 和 request.getParameter() 有何區(qū)別?
request.getParameter() 通常用來(lái)接收接收表單的get或者post提交過(guò)來(lái)的參數(shù);而request.getAttribute()一般和setAttribute()搭配使用,只有先set之后才能通過(guò)get方法獲取到Object類(lèi)型的數(shù)據(jù)
getAttribute 返回的是對(duì)象,而getParameter 返回的是字符串
getAttribute 和 setAttribute 只是在 web 容器內(nèi)流轉(zhuǎn),僅僅是請(qǐng)求處理階段;而 getParameter 取到的數(shù)據(jù)是通過(guò)容器來(lái)獲取的。
9)JSP 與 Servlet 的區(qū)別?
10)JSP 靜態(tài)包含和動(dòng)態(tài)包含的區(qū)別?
(1)靜態(tài)包含:編譯指令包含
<%@include file="被包含的頁(yè)面的路徑"%>
包含的時(shí)機(jī):在 JSP 文件被翻譯的時(shí)候合并在一起,最終翻譯得到一個(gè) class文件
(2)動(dòng)態(tài)包含:動(dòng)作指令包含
<jsp:include page="被包含頁(yè)面的路徑"></jsp:include>
包含的時(shí)機(jī):在運(yùn)行階段合并代碼,最終得到兩個(gè) class 文件
(3)動(dòng)態(tài)包含和靜態(tài)包含的選擇:
- 如果被包含的頁(yè)面如果是靜態(tài)頁(yè)面,那么使用靜態(tài)包含;
- 如果被包含的如果是動(dòng)態(tài)頁(yè)面,那么使用動(dòng)態(tài)包含。
11)JSP 有哪些內(nèi)置對(duì)象?作用分別是什么?
JSP 共有以下 9 個(gè)內(nèi)置的對(duì)象:
12)JSTL 是什么?優(yōu)點(diǎn)有哪些?
JSTL(JSP StandardTagLibrary,JSP標(biāo)準(zhǔn)標(biāo)簽庫(kù))是一個(gè)不斷完善的開(kāi)放源代碼的JSP標(biāo)簽庫(kù),由四個(gè)定制標(biāo)記庫(kù)(core、format、xml和sql)和一對(duì)通用標(biāo)記庫(kù)驗(yàn)證器(ScriptFreeTLV和PermittedTaglibsTLV)組成。優(yōu)點(diǎn)有:
在應(yīng)用程序服務(wù)器之間提供了一致的接口,最大程序地提高了WEB應(yīng)用在各應(yīng)用服務(wù)器之間的移植。
簡(jiǎn)化了JSP和WEB應(yīng)用程序的開(kāi)發(fā)。
以一種統(tǒng)一的方式減少了JSP中的scriptlet代碼數(shù)量,可以達(dá)到?jīng)]有任何scriptlet代碼的程序。在我們公司的項(xiàng)目中是不允許有任何的scriptlet代碼出現(xiàn)在JSP中。
允許JSP設(shè)計(jì)工具與WEB應(yīng)用程序開(kāi)發(fā)的進(jìn)一步集成。相信不久就會(huì)有支持JSTL的IDE開(kāi)發(fā)工具出現(xiàn)。
13)什么是 Cookie?Session 和 Cookie 有什么區(qū)別?
Cookie 技術(shù)
Cookie 是一種會(huì)話技術(shù),用于將用戶(hù)的信息保存在客戶(hù)端上。Cookie 英文直接翻譯過(guò)來(lái)就是小甜品,Cookie 的作用呢,通俗的說(shuō)就是當(dāng)一個(gè)用戶(hù)通過(guò) HTTP 訪問(wèn)一個(gè)服務(wù)器時(shí),這個(gè)服務(wù)器會(huì)將一些 Key/Value 鍵值對(duì)返回給客戶(hù)端瀏覽器,并給這些數(shù)據(jù)加上一些限制條件,在條件符合時(shí)這個(gè)用戶(hù)下次訪問(wèn)這個(gè)服務(wù)器時(shí),數(shù)據(jù)又被完整地帶回給服務(wù)器。
這個(gè)作用就像是你去超市購(gòu)物時(shí),第一次給你辦了一張購(gòu)物卡,在這個(gè)購(gòu)物卡里存放了一些你的個(gè)人信息,下次你再來(lái)這個(gè)超市的時(shí)候,你就只需要帶上你的購(gòu)物卡,直接購(gòu)物就好了。
Session 技術(shù)
Session:會(huì)話,從瀏覽器打開(kāi)開(kāi)始,直到瀏覽器關(guān)閉結(jié)束,無(wú)論在這個(gè)網(wǎng)站中訪問(wèn)了多少頁(yè)面,點(diǎn)擊了多少鏈接,都屬于同一個(gè)會(huì)話。Session 也可以稱(chēng)為會(huì)話 Cookie
- 特點(diǎn):服務(wù)端技術(shù),將數(shù)據(jù)保存在服務(wù)器
Cookie 與 Session 的區(qū)別
- Cookie 的數(shù)據(jù)是存放在客戶(hù)的瀏覽器上,Session 數(shù)據(jù)放在服務(wù)器上;
- Cookie 不是很安全,別人可以分析存放在本地的 Cookie 并進(jìn)行 Cookie 欺騙,如果考慮安全問(wèn)題則應(yīng)當(dāng)使用 Session;
- Session 會(huì)在一定時(shí)間內(nèi)保存在服務(wù)器上,當(dāng)訪問(wèn)增多,會(huì)比較占用服務(wù)器的資源,所以如果考慮性能問(wèn)題,則應(yīng)當(dāng)使用 Cookie;
- 單個(gè) Cookie 在客戶(hù)端的限制是 3k ,就是說(shuō)一個(gè)站點(diǎn)在客戶(hù)端存放的 Cookie 不能超過(guò) 3k。
總結(jié):?將登錄信息等重要信息存放為 Session;其他信息如果需要保留,可以存放在 Cookie 中。
14)什么是過(guò)濾器?
過(guò)濾器就是 Servlet 的高級(jí)特性之一,就是一個(gè)具有攔截/過(guò)濾功能的一個(gè)東西,在生活中過(guò)濾器可以是香煙濾嘴,濾紙,凈水器,空氣凈化器等,在 Web 中僅僅是一個(gè)實(shí)現(xiàn)了 Filter 接口的 Java 類(lèi)而已。
- 特點(diǎn):雙向,攔截請(qǐng)求,攔截響應(yīng)
- 作用:
過(guò)濾器可以對(duì)所有的請(qǐng)求或者響應(yīng)做攔截操作
15)為什么在 Web 開(kāi)發(fā)中需要用到過(guò)濾器?
- 問(wèn)題:為什么非得使用過(guò)濾器,我直接在 Servlet 中作判斷不行嗎?
- 開(kāi)發(fā)遵循的原則:
1.DRY原則(Don't Reeat Yourself,不要重復(fù)你自己):重復(fù),意味著維護(hù)的成本很高。
2.責(zé)任分離原則:誰(shuí)擅長(zhǎng)什么功能就做什么功能,Servlet 擅長(zhǎng)的是邏輯而不是處理請(qǐng)求
舉一個(gè)實(shí)際的例子:(處理 POST 請(qǐng)求中文編碼的問(wèn)題)
- Web 中過(guò)濾器的作用:
1.可以在請(qǐng)求資源之前設(shè)置請(qǐng)求的編碼
2.可以進(jìn)行登錄校驗(yàn)
3.可以進(jìn)行請(qǐng)求參數(shù)的內(nèi)容的過(guò)濾
4.數(shù)據(jù)壓縮 / 數(shù)據(jù)加密 / 數(shù)據(jù)格式的轉(zhuǎn)換
5.可以設(shè)置瀏覽器相關(guān)的數(shù)據(jù)
16)MVC 模式?
MVC模式(Model-View-Controller)是軟件工程中的一種軟件架構(gòu)模式,把軟件系統(tǒng)分為三個(gè)基本部分:模型(Model)、視圖(View)和控制器(Controller):
- Controller——負(fù)責(zé)轉(zhuǎn)發(fā)請(qǐng)求,對(duì)請(qǐng)求進(jìn)行處理
- View——負(fù)責(zé)界面顯示
- Model——業(yè)務(wù)功能編寫(xiě)(例如算法實(shí)現(xiàn))、數(shù)據(jù)庫(kù)設(shè)計(jì)以及數(shù)據(jù)存取操作實(shí)現(xiàn)
在JSP/Servlet開(kāi)發(fā)的軟件系統(tǒng)中,這三個(gè)部分的描述如下所示:
1.Web瀏覽器發(fā)送HTTP請(qǐng)求到服務(wù)端,被Controller(Servlet)獲取并進(jìn)行處理(例如參數(shù)解析、請(qǐng)求轉(zhuǎn)發(fā))
2.Controller(Servlet)調(diào)用核心業(yè)務(wù)邏輯——Model部分,獲得結(jié)果
3.Controller(Servlet)將邏輯處理結(jié)果交給View(JSP),動(dòng)態(tài)輸出HTML內(nèi)容
4.動(dòng)態(tài)生成的HTML內(nèi)容返回到瀏覽器顯示
MVC模式在Web開(kāi)發(fā)中的好處是非常明顯,它規(guī)避了JSP與Servlet各自的短板,Servlet只負(fù)責(zé)業(yè)務(wù)邏輯而不會(huì)通過(guò)out.append()動(dòng)態(tài)生成HTML代碼;JSP中也不會(huì)充斥著大量的業(yè)務(wù)代碼。這大大提高了代碼的可讀性和可維護(hù)性。
- 參考:知乎@David
(二)框架相關(guān)知識(shí)
由于我沒(méi)有接觸和學(xué)習(xí)過(guò) Hibernate 和 Struts 這兩個(gè)框架,所以細(xì)節(jié)方面的東西請(qǐng)讀者自行收集...
1)什么是框架?
框架是指完成一定功能的半成品。
框架能夠幫助我們完成的是:項(xiàng)目的整體框架、一些基礎(chǔ)功能、規(guī)定了類(lèi)和對(duì)象如何創(chuàng)建,如何協(xié)作等,當(dāng)我們開(kāi)發(fā)一個(gè)項(xiàng)目時(shí),框架幫助我們完成了一部分功能,我們自己再完成一部分,那這個(gè)項(xiàng)目就完成了。
2)什么是 Spring ?
Spring 是一個(gè)輕量級(jí)的 DI / IoC 和 AOP 容器的開(kāi)源框架,來(lái)源于 Rod Johnson 在其著作《Expert one on one J2EE design and development》中闡述的部分理念和原型衍生而來(lái)。
Spring 提倡以?“最少侵入”?的方式來(lái)管理應(yīng)用中的代碼,這意味著我們可以隨時(shí)安裝或者卸載 Spring
- 適用范圍:任何 Java 應(yīng)用
- Spring 的根本使命:簡(jiǎn)化 Java 開(kāi)發(fā)
3)什么是非侵入式設(shè)計(jì)?
從框架的角度可以理解為:無(wú)需繼承框架提供的任何類(lèi)
這樣我們?cè)诟鼡Q框架時(shí),之前寫(xiě)過(guò)的代碼幾乎可以繼續(xù)使用。
4)Spring 有什么優(yōu)勢(shì)?
- 低侵入 / 低耦合 (降低組件之間的耦合度,實(shí)現(xiàn)軟件各層之間的解耦)
- 聲明式事務(wù)管理(基于切面和慣例)
- 方便集成其他框架(如MyBatis、Hibernate)
- 降低 Java 開(kāi)發(fā)難度
- Spring 框架中包括了 J2EE 三層的每一層的解決方案(一站式)
Spring 的框架結(jié)構(gòu)
- Data Access/Integration層包含有JDBC、ORM、OXM、JMS和Transaction模塊。
- Web層包含了Web、Web-Servlet、WebSocket、Web-Porlet模塊。
- AOP模塊提供了一個(gè)符合AOP聯(lián)盟標(biāo)準(zhǔn)的面向切面編程的實(shí)現(xiàn)。
- Core Container(核心容器):包含有Beans、Core、Context和SpEL模塊。
- Test模塊支持使用JUnit和TestNG對(duì)Spring組件進(jìn)行測(cè)試。
5)Spring IoC 和 DI 分別是什么?
Spring IoC
IoC:Inverse of Control(控制反轉(zhuǎn)),讀作?“反轉(zhuǎn)控制”,更好理解,不是什么技術(shù),而是一種設(shè)計(jì)思想,就是將原本在程序中手動(dòng)創(chuàng)建對(duì)象的控制權(quán),交由Spring框架來(lái)管理。
- 正控:若要使用某個(gè)對(duì)象,需要自己去負(fù)責(zé)對(duì)象的創(chuàng)建
- 反控:若要使用某個(gè)對(duì)象,只需要從 Spring 容器中獲取需要使用的對(duì)象,不關(guān)心對(duì)象的創(chuàng)建過(guò)程,也就是把創(chuàng)建對(duì)象的控制權(quán)反轉(zhuǎn)給了Spring框架
- 好萊塢法則:Don’t call me ,I’ll call you
為了便于理解我們這里舉一個(gè)鮮明的例子:
在現(xiàn)實(shí)生活中,人們要用到一樣?xùn)|西的時(shí)候,第一反應(yīng)就是去找到這件東西,比如想喝新鮮橙汁,在沒(méi)有飲品店的日子里,最直觀的做法就是:買(mǎi)果汁機(jī)、買(mǎi)橙子,然后準(zhǔn)備開(kāi)水。值得注意的是:這些都是你自己“主動(dòng)”創(chuàng)造的過(guò)程,也就是說(shuō)一杯橙汁需要你自己創(chuàng)造。
然而到了今時(shí)今日,由于飲品店的盛行,當(dāng)我們想喝橙汁時(shí),第一想法就轉(zhuǎn)換成了找到飲品店的聯(lián)系方式,通過(guò)電話等渠道描述你的需要、地址、聯(lián)系方式等,下訂單等待,過(guò)一會(huì)兒就會(huì)有人送來(lái)橙汁了。
請(qǐng)注意你并沒(méi)有“主動(dòng)”去創(chuàng)造橙汁,橙汁是由飲品店創(chuàng)造的,而不是你,然而也完全達(dá)到了你的要求,甚至比你創(chuàng)造的要好上那么一些。
- 總結(jié):?這就是一種控制反轉(zhuǎn)的理念,上述的例子已經(jīng)很好的說(shuō)明了問(wèn)題,我們?cè)賮?lái)描述一下控制反轉(zhuǎn)的概念:控制反轉(zhuǎn)是一種通過(guò)描述(在 Java 中可以是 XML 或者注解)并通過(guò)第三方(Spring)去產(chǎn)生或獲取特定對(duì)象的方式。
- 好處:?① 降低對(duì)象之間的耦合;② 我們不需要理解一個(gè)類(lèi)的具體實(shí)現(xiàn),只需要知道它有什么用就好了(直接向 IoC 容器拿)
DI:Dependency Injection(依賴(lài)注入)
指 Spring 創(chuàng)建對(duì)象的過(guò)程中,將對(duì)象依賴(lài)屬性(簡(jiǎn)單值,集合,對(duì)象)通過(guò)配置設(shè)值給該對(duì)象
兩者的區(qū)別
IoC 和 DI 其實(shí)是同一個(gè)概念的不同角度描述,DI 相對(duì) IoC 而言,明確描述了 “被注入對(duì)象依賴(lài) IoC 容器配置依賴(lài)對(duì)象”。
你也可以簡(jiǎn)單的理解為:IoC 是目的,是一種思想,而 DI 是手段,是一種設(shè)計(jì)模式。
6)BeanFactory 和 ApplicationContext 的區(qū)別
1.BeanFactory:
是Spring中最底層的接口,只提供了最簡(jiǎn)單的IoC功能,負(fù)責(zé)配置,創(chuàng)建和管理bean。在應(yīng)用中,一般不使用 BeanFactory,而推薦使ApplicationContext(應(yīng)用上下文),原因如下。
2.ApplicationContext:
⑴. 繼承了 BeanFactory,擁有了基本的 IoC 功能;
⑵. 除此之外,ApplicationContext 還提供了以下功能:
① 支持國(guó)際化;② 支持消息機(jī)制;③ 支持統(tǒng)一的資源加載;④ 支持AOP功能;
- 注意:?ApplicationContext 和 BeanFactory 相比,最主要的區(qū)別在于 BeanFactory 是延遲加載,舉個(gè)例子:如果 Bean 沒(méi)有完全注入,BeanFactory 加載后,會(huì)在你第一次調(diào)用 getBean 方法才會(huì)拋出異常;而 ApplicationContext 會(huì)在初始化的時(shí)候就加載并且檢查,這樣的好處是可以及時(shí)檢查依賴(lài)是否完全注入;所以通常我們會(huì)選擇 ApplicationContext。
7)IoC 是如何實(shí)現(xiàn)的
最后我們簡(jiǎn)單說(shuō)說(shuō)IoC是如何實(shí)現(xiàn)的。想象一下如果我們自己來(lái)實(shí)現(xiàn)這個(gè)依賴(lài)注入的功能,我們?cè)趺磥?lái)做? 無(wú)外乎:
我們發(fā)現(xiàn)其實(shí)自己來(lái)實(shí)現(xiàn)也不是很難,Spring實(shí)際也就是這么做的。這么看的話其實(shí)IoC就是一個(gè)工廠模式的升級(jí)版!當(dāng)然要做一個(gè)成熟的IoC框架,還是非常多細(xì)致的工作要做,Spring不僅提供了一個(gè)已經(jīng)成為業(yè)界標(biāo)準(zhǔn)的Java IoC框架,還提供了更多強(qiáng)大的功能,所以大家就別去造輪子啦!希望了解IoC更多實(shí)現(xiàn)細(xì)節(jié)不妨通過(guò)學(xué)習(xí)Spring的源碼來(lái)加深理解!
引用地址:這里
8)Spring 配置 Bean 有幾種方式?
在 Spring 中提供了 3 種方法進(jìn)行配置:
- 在 XML 文件中顯式配置
- 在 Java 的接口和類(lèi)中實(shí)現(xiàn)配置
- 隱式 Bean 的發(fā)現(xiàn)機(jī)制和自動(dòng)裝配原則
方式選擇的原則
在現(xiàn)實(shí)的工作中,這 3 種方式都會(huì)被用到,并且在學(xué)習(xí)和工作之中常常混合使用,所以這里給出一些關(guān)于這 3 種優(yōu)先級(jí)的建議:
1.最優(yōu)先:通過(guò)隱式 Bean 的發(fā)現(xiàn)機(jī)制和自動(dòng)裝配的原則。
基于約定由于配置的原則,這種方式應(yīng)該是最優(yōu)先的
- 好處:減少程序開(kāi)發(fā)者的決定權(quán),簡(jiǎn)單又不失靈活。
2.其次:Java 接口和類(lèi)中配置實(shí)現(xiàn)配置
在沒(méi)有辦法使用自動(dòng)裝配原則的情況下應(yīng)該優(yōu)先考慮此類(lèi)方法
- 好處:避免 XML 配置的泛濫,也更為容易。
- 典型場(chǎng)景:一個(gè)父類(lèi)有多個(gè)子類(lèi),比如學(xué)生類(lèi)有兩個(gè)子類(lèi),一個(gè)男學(xué)生類(lèi)和女學(xué)生類(lèi),通過(guò) IoC 容器初始化一個(gè)學(xué)生類(lèi),容器將無(wú)法知道使用哪個(gè)子類(lèi)去初始化,這個(gè)時(shí)候可以使用 Java 的注解配置去指定。
3.最后:XML 方式配置
在上述方法都無(wú)法使用的情況下,那么也只能選擇 XML 配置的方式。
- 好處:簡(jiǎn)單易懂(當(dāng)然,特別是對(duì)于初學(xué)者)
- 典型場(chǎng)景:當(dāng)使用第三方類(lèi)的時(shí)候,有些類(lèi)并不是我們開(kāi)發(fā)的,我們無(wú)法修改里面的代碼,這個(gè)時(shí)候就通過(guò) XML 的方式配置使用了。
9)介紹一下 Spring AOP
AOP 即 Aspect Oriented Program 面向切面編程
首先,在面向切面編程的思想里面,把功能分為核心業(yè)務(wù)功能,和周邊功能。
- 所謂的核心業(yè)務(wù),比如登陸,增加數(shù)據(jù),刪除數(shù)據(jù)都叫核心業(yè)務(wù)
- 所謂的周邊功能,比如性能統(tǒng)計(jì),日志,事務(wù)管理等等
周邊功能在 Spring 的面向切面編程AOP思想里,即被定義為切面
在面向切面編程AOP的思想里面,核心業(yè)務(wù)功能和切面功能分別獨(dú)立進(jìn)行開(kāi)發(fā),然后把切面功能和核心業(yè)務(wù)功能 "編織" 在一起,這就叫 AOP
還是來(lái)舉一個(gè)鮮明的例子:
在上面的例子中,包租婆的核心業(yè)務(wù)就是簽合同,收房租,那么這就夠了,灰色框起來(lái)的部分都是重復(fù)且邊緣的事,交給中介商就好了,這就是 AOP 的一個(gè)思想:讓關(guān)注點(diǎn)代碼與業(yè)務(wù)代碼分離!
10)Spring 中 Bean 的作用域
在默認(rèn)的情況下,Spring IoC 容器只會(huì)對(duì)一個(gè) Bean 創(chuàng)建一個(gè)實(shí)例,但有時(shí)候,我們希望能夠通過(guò) Spring IoC 容器獲取多個(gè)實(shí)例,我們可以通過(guò)?@Scope?注解或者?<bean>?元素中的?scope?屬性來(lái)設(shè)置,例如:
// XML 中設(shè)置作用域 <bean id="" class="" scope="prototype" /> // 使用注解設(shè)置作用域 @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)Spring 提供了 5 種作用域,它會(huì)根據(jù)情況來(lái)決定是否生成新的對(duì)象:
| singleton(單例) | 在Spring IoC容器中僅存在一個(gè)Bean實(shí)例 (默認(rèn)的scope) |
| prototype(多例) | 每次從容器中調(diào)用Bean時(shí),都返回一個(gè)新的實(shí)例,即每次調(diào)用getBean()時(shí) ,相當(dāng)于執(zhí)行new XxxBean():不會(huì)在容器啟動(dòng)時(shí)創(chuàng)建對(duì)象 |
| request(請(qǐng)求) | 用于web開(kāi)發(fā),將Bean放入request范圍 ,request.setAttribute("xxx") , 在同一個(gè)request 獲得同一個(gè)Bean |
| session(會(huì)話) | 用于web開(kāi)發(fā),將Bean 放入Session范圍,在同一個(gè)Session 獲得同一個(gè)Bean |
| globalSession(全局會(huì)話) | 一般用于 Porlet 應(yīng)用環(huán)境 , 分布式系統(tǒng)存在全局 session 概念(單點(diǎn)登錄),如果不是 porlet 環(huán)境,globalSession 等同于 Session |
在開(kāi)發(fā)中主要使用?scope="singleton"、scope="prototype",對(duì)于MVC中的Action使用prototype類(lèi)型,其他使用singleton,Spring容器會(huì)管理 Action 對(duì)象的創(chuàng)建,此時(shí)把 Action 的作用域設(shè)置為 prototype.
擴(kuò)展閱讀:@Profile 注解?、?條件化裝配 Bean
11)Spring 面試問(wèn)答 Top 25
更多戳這里:Spring面試問(wèn)答Top 25
12)Spring MVC 的請(qǐng)求流程
每當(dāng)用戶(hù)在 Web 瀏覽器中點(diǎn)擊鏈接或者提交表單的時(shí)候,請(qǐng)求就開(kāi)始工作了,像是郵遞員一樣,從離開(kāi)瀏覽器開(kāi)始到獲取響應(yīng)返回,它會(huì)經(jīng)歷很多站點(diǎn),在每一個(gè)站點(diǎn)都會(huì)留下一些信息同時(shí)也會(huì)帶上其他信息,下圖為 Spring MVC 的請(qǐng)求流程:
第一站:DispatcherServlet
從請(qǐng)求離開(kāi)瀏覽器以后,第一站到達(dá)的就是 DispatcherServlet,看名字這是一個(gè) Servlet,通過(guò) J2EE 的學(xué)習(xí),我們知道 Servlet 可以攔截并處理 HTTP 請(qǐng)求,DispatcherServlet 會(huì)攔截所有的請(qǐng)求,并且將這些請(qǐng)求發(fā)送給 Spring MVC 控制器。
<servlet><servlet-name>dispatcher</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><load-on-startup>1</load-on-startup> </servlet> <servlet-mapping><servlet-name>dispatcher</servlet-name><!-- 攔截所有的請(qǐng)求 --><url-pattern>/</url-pattern> </servlet-mapping>- DispatcherServlet 的任務(wù)就是攔截請(qǐng)求發(fā)送給 Spring MVC 控制器。
第二站:處理器映射(HandlerMapping)
- 問(wèn)題:典型的應(yīng)用程序中可能會(huì)有多個(gè)控制器,這些請(qǐng)求到底應(yīng)該發(fā)給哪一個(gè)控制器呢?
所以 DispatcherServlet 會(huì)查詢(xún)一個(gè)或多個(gè)處理器映射來(lái)確定請(qǐng)求的下一站在哪里,處理器映射會(huì)根據(jù)請(qǐng)求所攜帶的 URL 信息來(lái)進(jìn)行決策,例如上面的例子中,我們通過(guò)配置 simpleUrlHandlerMapping 來(lái)將 /hello 地址交給 helloController 處理:
<bean id="simpleUrlHandlerMapping"class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"><property name="mappings"><props><!-- /hello 路徑的請(qǐng)求交給 id 為 helloController 的控制器處理--><prop key="/hello">helloController</prop></props></property> </bean> <bean id="helloController" class="controller.HelloController"></bean>第三站:控制器
一旦選擇了合適的控制器, DispatcherServlet 會(huì)將請(qǐng)求發(fā)送給選中的控制器,到了控制器,請(qǐng)求會(huì)卸下其負(fù)載(用戶(hù)提交的請(qǐng)求)等待控制器處理完這些信息:
public ModelAndView handleRequest(javax.servlet.http.HttpServletRequest httpServletRequest, javax.servlet.http.HttpServletResponse httpServletResponse) throws Exception {// 處理邏輯.... }第四站:返回 DispatcherServlet
當(dāng)控制器在完成邏輯處理后,通常會(huì)產(chǎn)生一些信息,這些信息就是需要返回給用戶(hù)并在瀏覽器上顯示的信息,它們被稱(chēng)為模型(Model)。僅僅返回原始的信息時(shí)不夠的——這些信息需要以用戶(hù)友好的方式進(jìn)行格式化,一般會(huì)是 HTML,所以,信息需要發(fā)送給一個(gè)視圖(view),通常會(huì)是 JSP。
控制器所做的最后一件事就是將模型數(shù)據(jù)打包,并且表示出用于渲染輸出的視圖名(邏輯視圖名)。它接下來(lái)會(huì)將請(qǐng)求連同模型和視圖名發(fā)送回 DispatcherServlet。
public ModelAndView handleRequest(javax.servlet.http.HttpServletRequest httpServletRequest, javax.servlet.http.HttpServletResponse httpServletResponse) throws Exception {// 處理邏輯....// 返回給 DispatcherServletreturn mav; }第五站:視圖解析器
這樣以來(lái),控制器就不會(huì)和特定的視圖相耦合,傳遞給 DispatcherServlet 的視圖名并不直接表示某個(gè)特定的 JSP。(實(shí)際上,它甚至不能確定視圖就是 JSP)相反,它傳遞的僅僅是一個(gè)邏輯名稱(chēng),這個(gè)名稱(chēng)將會(huì)用來(lái)查找產(chǎn)生結(jié)果的真正視圖。
DispatcherServlet 將會(huì)使用視圖解析器(view resolver)來(lái)將邏輯視圖名匹配為一個(gè)特定的視圖實(shí)現(xiàn),它可能是也可能不是 JSP
上面的例子是直接綁定到了 index.jsp 視圖
第六站:視圖
既然 DispatcherServlet 已經(jīng)知道由哪個(gè)視圖渲染結(jié)果了,那請(qǐng)求的任務(wù)基本上也就完成了。
它的最后一站是視圖的實(shí)現(xiàn),在這里它交付模型數(shù)據(jù),請(qǐng)求的任務(wù)也就完成了。視圖使用模型數(shù)據(jù)渲染出結(jié)果,這個(gè)輸出結(jié)果會(huì)通過(guò)響應(yīng)對(duì)象傳遞給客戶(hù)端。
<%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8" isELIgnored="false"%><h1>${message}</h1>更多 Spring-MVC 內(nèi)容:Spring MVC【入門(mén)】就這一篇
13)什么是 ORM?
對(duì)象關(guān)系映射(Object-Relational Mapping,簡(jiǎn)稱(chēng)ORM)是一種為了解決程序的面向?qū)ο竽P团c數(shù)據(jù)庫(kù)的關(guān)系模型互不匹配問(wèn)題的技術(shù);
簡(jiǎn)單的說(shuō),ORM是通過(guò)使用描述對(duì)象和數(shù)據(jù)庫(kù)之間映射的元數(shù)據(jù)(在Java中可以用XML或者是注解),將程序中的對(duì)象自動(dòng)持久化到關(guān)系數(shù)據(jù)庫(kù)中或者將關(guān)系數(shù)據(jù)庫(kù)表中的行轉(zhuǎn)換成Java對(duì)象,其本質(zhì)上就是將數(shù)據(jù)從一種形式轉(zhuǎn)換到另外一種形式。
14)為什么要使用 MyBatis ?
在我們傳統(tǒng)的 JDBC?中,我們除了需要自己提供 SQL 外,還必須操作 Connection、Statment、ResultSet,不僅如此,為了訪問(wèn)不同的表,不同字段的數(shù)據(jù),我們需要些很多雷同模板化的代碼,閑的繁瑣又枯燥。
而我們?cè)谑褂昧?MyBatis?之后,只需要提供 SQL 語(yǔ)句就好了,其余的諸如:建立連接、操作 Statment、ResultSet,處理 JDBC 相關(guān)異常等等都可以交給 MyBatis 去處理,我們的關(guān)注點(diǎn)于是可以就此集中在 SQL 語(yǔ)句上,關(guān)注在增刪改查這些操作層面上。
并且 MyBatis 支持使用簡(jiǎn)單的 XML 或注解來(lái)配置和映射原生信息,將接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java對(duì)象)映射成數(shù)據(jù)庫(kù)中的記錄。
15)MyBatis 中占位符?#?和?$?的區(qū)別
區(qū)別如下:
16)MyBatis 緩存結(jié)構(gòu)
在 Web 系統(tǒng)中,最重要的操作就是查詢(xún)數(shù)據(jù)庫(kù)中的數(shù)據(jù)。但是有些時(shí)候查詢(xún)數(shù)據(jù)的頻率非常高,這是很耗費(fèi)數(shù)據(jù)庫(kù)資源的,往往會(huì)導(dǎo)致數(shù)據(jù)庫(kù)查詢(xún)效率極低,影響客戶(hù)的操作體驗(yàn)。于是我們可以將一些變動(dòng)不大且訪問(wèn)頻率高的數(shù)據(jù),放置在一個(gè)緩存容器中,用戶(hù)下一次查詢(xún)時(shí)就從緩存容器中獲取結(jié)果。
- MyBatis 擁有自己的緩存結(jié)構(gòu),可以用來(lái)緩解數(shù)據(jù)庫(kù)壓力,加快查詢(xún)速度。
- MyBatis 一級(jí)緩存是一個(gè) SqlSession 級(jí)別,同一個(gè) SqlSession 只能訪問(wèn)自己的一級(jí)緩存的數(shù)據(jù)
- 二級(jí)緩存是跨sqlSession,是 mapper 級(jí)別的緩存,對(duì)于 mapper 級(jí)別的緩存不同的sqlsession是可以共享的。
更多深入MyBatis的內(nèi)容戳這里:MyBatis(2)——MyBatis 深入學(xué)習(xí)
17)MyBatis 與 Spring 整合
戳這里:MyBatis 與 Spring 整合
18)IDEA 整合 SSM 框架學(xué)習(xí)
戳這里IDEA 整合 SSM 框架學(xué)習(xí)
19)MVC 三種模式
在早期 Java Web 的開(kāi)發(fā)中,統(tǒng)一把顯示層、控制層、數(shù)據(jù)層的操作全部交給 JSP 或者 JavaBean 來(lái)進(jìn)行處理,我們稱(chēng)之為?Model1:
- 出現(xiàn)的弊端:
- JSP 和 Java Bean 之間嚴(yán)重耦合,Java 代碼和 HTML 代碼也耦合在了一起
- 要求開(kāi)發(fā)者不僅要掌握 Java ,還要有高超的前端水平
- 前端和后端相互依賴(lài),前端需要等待后端完成,后端也依賴(lài)前端完成,才能進(jìn)行有效的測(cè)試
- 代碼難以復(fù)用
正因?yàn)樯厦娴姆N種弊端,所以很快這種方式就被 Servlet + JSP + Java Bean 所替代了,早期的 MVC 模型(Model2)就像下圖這樣:
首先用戶(hù)的請(qǐng)求會(huì)到達(dá) Servlet,然后根據(jù)請(qǐng)求調(diào)用相應(yīng)的 Java Bean,并把所有的顯示結(jié)果交給 JSP 去完成,這樣的模式我們就稱(chēng)為 MVC 模式。
- M 代表 模型(Model)
模型是什么呢? 模型就是數(shù)據(jù),就是 dao,bean - V 代表 視圖(View)
視圖是什么呢? 就是網(wǎng)頁(yè), JSP,用來(lái)展示模型中的數(shù)據(jù) - C 代表 控制器(controller)
控制器是什么? 控制器的作用就是把不同的數(shù)據(jù)(Model),顯示在不同的視圖(View)上,Servlet 扮演的就是這樣的角色。
擴(kuò)展閱讀:Web開(kāi)發(fā)模式
Spring MVC 的架構(gòu)
為解決持久層中一直未處理好的數(shù)據(jù)庫(kù)事務(wù)的編程,又為了迎合 NoSQL 的強(qiáng)勢(shì)崛起,Spring MVC 給出了方案:
傳統(tǒng)的模型層被拆分為了業(yè)務(wù)層(Service)和數(shù)據(jù)訪問(wèn)層(DAO,Data Access Object)。在 Service 下可以通過(guò) Spring 的聲明式事務(wù)操作數(shù)據(jù)訪問(wèn)層,而在業(yè)務(wù)層上還允許我們?cè)L問(wèn) NoSQL ,這樣就能夠滿(mǎn)足異軍突起的 NoSQL 的使用了,它可以大大提高互聯(lián)網(wǎng)系統(tǒng)的性能。
- 特點(diǎn):
結(jié)構(gòu)松散,幾乎可以在 Spring MVC 中使用各類(lèi)視圖
松耦合,各個(gè)模塊分離
與 Spring 無(wú)縫集成
20)分頁(yè)?
戳這里:Java Web -【分頁(yè)功能】詳解
21)什么是 Spring Boot ?
- 它使用?“習(xí)慣優(yōu)于配置”?(項(xiàng)目中存在大量的配置,此外還內(nèi)置一個(gè)習(xí)慣性的配置,讓你無(wú)須)的理念讓你的項(xiàng)目快速運(yùn)行起來(lái)。
- 它并不是什么新的框架,而是默認(rèn)配置了很多框架的使用方式,就像 Maven 整合了所有的 jar 包一樣,Spring Boot 整合了所有框架(引自:springboot(一):入門(mén)篇——純潔的微笑)
22)使用 Spring Boot 有什么好處?
回顧我們之前的 SSM 項(xiàng)目,搭建過(guò)程還是比較繁瑣的,需要:
- 1)配置 web.xml,加載 spring 和 spring mvc
- 2)配置數(shù)據(jù)庫(kù)連接、配置日志文件
- 3)配置家在配置文件的讀取,開(kāi)啟注解
- 4)配置mapper文件
- .....
而使用 Spring Boot 來(lái)開(kāi)發(fā)項(xiàng)目則只需要非常少的幾個(gè)配置就可以搭建起來(lái)一個(gè) Web 項(xiàng)目,并且利用 IDEA 可以自動(dòng)生成生成,這簡(jiǎn)直是太爽了...
- 劃重點(diǎn):簡(jiǎn)單、快速、方便地搭建項(xiàng)目;對(duì)主流開(kāi)發(fā)框架的無(wú)配置集成;極大提高了開(kāi)發(fā)、部署效率。
Spring Boot 由于筆者還沒(méi)有深入學(xué)習(xí)..所以細(xì)節(jié)部分請(qǐng)讀者自行收集...
歡迎轉(zhuǎn)載,轉(zhuǎn)載請(qǐng)注明出處!
簡(jiǎn)書(shū)ID:@我沒(méi)有三顆心臟
github:wmyskxz
總結(jié)
以上是生活随笔為你收集整理的Java 面试知识点解析(七)——Web篇的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Java 面试知识点解析(六)——数据库
- 下一篇: Java8中的流操作-基本使用性能测试