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