- 前言:
在遨遊了一番 Java Web 的世界以後,發現了本身的一些缺失,因此就着一篇深度好文:知名互聯網公司校招 Java 開發崗面試知識點解析 ,來好好的對 Java 知識點進行復習和學習一番,大部份內容參照自這一篇文章,有一些本身補充的,也算是從新學習一下 Java 吧。javascript
前序文章連接:html
Java 面試知識點解析(六)——數據庫篇spring
不涉及任何框架,對 J2EE 相關知識點的解析sql
在 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 自動銷燬。
瀏覽器發出請求: http://localhost:80/xxx1/xxx2
(80端口能夠默認不寫,由於這是http協議默認的端口,平時咱們訪問https://www.baidu.com/
時其實訪問的是https://www.baidu.com:80/
)
服務器解析請求信息:
解析 Tomcat 服務器根目錄下的 /config/server.xml 文件:
<Context docBase="D:\javaPros\test\webapp" path="xxx1" />
判斷哪個<Context />
元素的 path屬性 屬性爲 xxx1
<Context />
元素,獲得docBase
屬性,獲取當前訪問 Web 項目的跟的絕對路徑:D:\javaPros\test\webapp
從D:\javaPros\test\webapp
下的 WEB-INF 下找到 web.xml 文件
判斷 web.xml 文件中是否有 <url-pattern>
的文本內容爲 /xxx2
判斷 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() 方法中對瀏覽器做出響應操做。
Servlet 是單例的,瀏覽器屢次對Servlet的請求,通常狀況下,服務器只建立一個Servlet對象,也就是說,Servlet對象一旦建立了,就會駐留在內存中,爲後續的請求作服務,直到服務器關閉。
要知道,GET 和 POST 都是請求方式
瀏覽器器地址欄:http://localhost/test.html?name=wmyskxz&sex=male
這裏提交了兩個參數,一個是name
屬性值爲wmyskxz
,另外一個是sex
屬性值爲male
,這是一種直接的請求方式,在請求資源後面跟上 ? 符號與參數鏈接,其餘的參數使用 & 符號鏈接。
瀏覽器地址欄:http://localhost/test.html#
在 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(修改端口的那一行)
又叫作直接轉發方式,客戶端和瀏覽器只發出一次請求,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.請求轉發【不能】跨域訪問
所謂的同域,是指域名,協議,端口均相同
又叫作間接轉發方式(Redirect)實際是兩次HTTP請求,服務器端在響應第一次請求的時候,讓瀏覽器再向另一個URL發出請求,從而達到轉發的目的。
好比:從AServlet重定向到BServlet
response.sendRedirect(String location);
參數:location
,轉發到的資源路徑
特色:
1.地址欄中的地址【會】發生改變,一般看做是客戶端跳轉
2.有兩個請求
3.在兩個 Servlet 中不能夠共享請求中的數據
4.最終的響應由 BServlet 來決定,和 AServlet 沒有關係
5.【不能夠】訪問 WEB-INF 中的資源
6.請求轉發【能】跨域訪問
就像是在網頁中點開了新的連接同樣
當訪問一個 JSP 頁面時,該頁面請求將會講給服務器中的 JSP 引擎去處理,它負責解釋和執行 JSP 頁面,每一個 JSP 頁面在第一次被訪問時,JSP 引擎就會將它翻譯成一個繼承自 org.apache.jasper.runtime.HttpJspBase
類的 Servlet 源程序,接着再編譯成 class 類文件,再由 Web 容器像調用普通 Servlet 程序同樣的方式來裝載和解釋執行這個由 JSP 頁面翻譯成的 Servlet 程序。
request.getParameter() 一般用來接收接收表單的get或者post提交過來的參數;而request.getAttribute()通常和setAttribute()搭配使用,只有先set以後才能經過get方法獲取到Object類型的數據
getAttribute 返回的是對象,而getParameter 返回的是字符串
getAttribute 和 setAttribute 只是在 web 容器內流轉,僅僅是請求處理階段;而 getParameter 取到的數據是經過容器來獲取的。
<%@include file="被包含的頁面的路徑"%>
包含的時機:在 JSP 文件被翻譯的時候合併在一塊兒,最終翻譯獲得一個 class文件
<jsp:include page="被包含頁面的路徑"></jsp:include>
包含的時機:在運行階段合併代碼,最終獲得兩個 class 文件
JSP 共有如下 9 個內置的對象:
JSTL(JSP StandardTagLibrary,JSP標準標籤庫)是一個不斷完善的開放源代碼的JSP標籤庫,由四個定製標記庫(core、format、xml和sql)和一對通用標記庫驗證器(ScriptFreeTLV和PermittedTaglibsTLV)組成。優勢有:
在應用程序服務器之間提供了一致的接口,最大程序地提升了WEB應用在各應用服務器之間的移植。
簡化了JSP和WEB應用程序的開發。
以一種統一的方式減小了JSP中的scriptlet代碼數量,能夠達到沒有任何scriptlet代碼的程序。在咱們公司的項目中是不容許有任何的scriptlet代碼出如今JSP中。
容許JSP設計工具與WEB應用程序開發的進一步集成。相信不久就會有支持JSTL的IDE開發工具出現。
Cookie 是一種會話技術,用於將用戶的信息保存在客戶端上。Cookie 英文直接翻譯過來就是小甜品,Cookie 的做用呢,通俗的說就是當一個用戶經過 HTTP 訪問一個服務器時,這個服務器會將一些 Key/Value 鍵值對返回給客戶端瀏覽器,並給這些數據加上一些限制條件,在條件符合時這個用戶下次訪問這個服務器時,數據又被完整地帶回給服務器。
這個做用就像是你去超市購物時,第一次給你辦了一張購物卡,在這個購物卡里存放了一些你的我的信息,下次你再來這個超市的時候,你就只須要帶上你的購物卡,直接購物就行了。
Session:會話,從瀏覽器打開開始,直到瀏覽器關閉結束,不管在這個網站中訪問了多少頁面,點擊了多少連接,都屬於同一個會話。Session 也能夠稱爲會話 Cookie
總結: 將登陸信息等重要信息存放爲 Session;其餘信息若是須要保留,能夠存放在 Cookie 中。
過濾器就是 Servlet 的高級特性之一,就是一個具備攔截/過濾功能的一個東西,在生活中過濾器能夠是香菸濾嘴,濾紙,淨水器,空氣淨化器等,在 Web 中僅僅是一個實現了 Filter 接口的 Java 類而已。
舉一個實際的例子:(處理 POST 請求中文編碼的問題)
MVC模式(Model-View-Controller)是軟件工程中的一種軟件架構模式,把軟件系統分爲三個基本部分:模型(Model)、視圖(View)和控制器(Controller):
在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中也不會充斥着大量的業務代碼。這大大提升了代碼的可讀性和可維護性。
因爲我沒有接觸和學習過 Hibernate 和 Struts 這兩個框架,因此細節方面的東西請讀者自行收集...
框架是指完成必定功能的半成品。
框架可以幫助咱們完成的是:項目的總體框架、一些基礎功能、規定了類和對象如何建立,如何協做等,當咱們開發一個項目時,框架幫助咱們完成了一部分功能,咱們本身再完成一部分,那這個項目就完成了。
Spring 是一個輕量級的 DI / IoC 和 AOP 容器的開源框架,來源於 Rod Johnson 在其著做《Expert one on one J2EE design and development》中闡述的部分理念和原型衍生而來。
Spring 提倡以 「最少侵入」 的方式來管理應用中的代碼,這意味着咱們能夠隨時安裝或者卸載 Spring
從框架的角度能夠理解爲:無需繼承框架提供的任何類
這樣咱們在更換框架時,以前寫過的代碼幾乎能夠繼續使用。
IoC:Inverse of Control(控制反轉),讀做 「反轉控制」,更好理解,不是什麼技術,而是一種設計思想,就是將本來在程序中手動建立對象的控制權,交由Spring框架來管理。
爲了便於理解咱們這裏舉一個鮮明的例子:
在現實生活中,人們要用到同樣東西的時候,第一反應就是去找到這件東西,好比想喝新鮮橙汁,在沒有飲品店的日子裏,最直觀的作法就是:買果汁機、買橙子,而後準備開水。值得注意的是:這些都是你本身「主動」創造的過程,也就是說一杯橙汁須要你本身創造。
然而到了今時今日,因爲飲品店的盛行,當咱們想喝橙汁時,第一想法就轉換成了找到飲品店的聯繫方式,經過電話等渠道描述你的須要、地址、聯繫方式等,下訂單等待,過一下子就會有人送來橙汁了。
請注意你並無「主動」去創造橙汁,橙汁是由飲品店創造的,而不是你,然而也徹底達到了你的要求,甚至比你創造的要好上那麼一些。
指 Spring 建立對象的過程當中,將對象依賴屬性(簡單值,集合,對象)經過配置設值給該對象
IoC 和 DI 實際上是同一個概念的不一樣角度描述,DI 相對 IoC 而言,明確描述了 「被注入對象依賴 IoC 容器配置依賴對象」。
你也能夠簡單的理解爲:IoC 是目的,是一種思想,而 DI 是手段,是一種設計模式。
1.BeanFactory:
是Spring中最底層的接口,只提供了最簡單的IoC功能,負責配置,建立和管理bean。在應用中,通常不使用 BeanFactory,而推薦使ApplicationContext(應用上下文),緣由以下。
2.ApplicationContext:
⑴. 繼承了 BeanFactory,擁有了基本的 IoC 功能;
⑵. 除此以外,ApplicationContext 還提供瞭如下功能:
① 支持國際化;② 支持消息機制;③ 支持統一的資源加載;④ 支持AOP功能;
最後咱們簡單說說IoC是如何實現的。想象一下若是咱們本身來實現這個依賴注入的功能,咱們怎麼來作? 無外乎:
咱們發現其實本身來實現也不是很難,Spring實際也就是這麼作的。這麼看的話其實IoC就是一個工廠模式的升級版!固然要作一個成熟的IoC框架,仍是很是多細緻的工做要作,Spring不只提供了一個已經成爲業界標準的Java IoC框架,還提供了更多強大的功能,因此你們就別去造輪子啦!但願瞭解IoC更多實現細節不妨經過學習Spring的源碼來加深理解!
引用地址:這裏
在 Spring 中提供了 3 種方法進行配置:
在現實的工做中,這 3 種方式都會被用到,而且在學習和工做之中經常混合使用,因此這裏給出一些關於這 3 種優先級的建議:
1.最優先:經過隱式 Bean 的發現機制和自動裝配的原則。
基於約定因爲配置的原則,這種方式應該是最優先的
2.其次:Java 接口和類中配置實現配置
在沒有辦法使用自動裝配原則的狀況下應該優先考慮此類方法
3.最後:XML 方式配置
在上述方法都沒法使用的狀況下,那麼也只能選擇 XML 配置的方式。
AOP 即 Aspect Oriented Program 面向切面編程
首先,在面向切面編程的思想裏面,把功能分爲核心業務功能,和周邊功能。
周邊功能在 Spring 的面向切面編程AOP思想裏,即被定義爲切面
在面向切面編程AOP的思想裏面,核心業務功能和切面功能分別獨立進行開發,而後把切面功能和核心業務功能 "編織" 在一塊兒,這就叫 AOP
仍是來舉一個鮮明的例子:
在上面的例子中,包租婆的核心業務就是籤合同,收房租,那麼這就夠了,灰色框起來的部分都是重複且邊緣的事,交給中介商就行了,這就是 AOP 的一個思想:讓關注點代碼與業務代碼分離!
在默認的狀況下,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
更多戳這裏:Spring面試問答Top 25
每當用戶在 Web 瀏覽器中點擊連接或者提交表單的時候,請求就開始工做了,像是郵遞員同樣,從離開瀏覽器開始到獲取響應返回,它會經歷不少站點,在每個站點都會留下一些信息同時也會帶上其餘信息,下圖爲 Spring MVC 的請求流程:
從請求離開瀏覽器之後,第一站到達的就是 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 會查詢一個或多個處理器映射來肯定請求的下一站在哪裏,處理器映射會根據請求所攜帶的 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 { // 處理邏輯 .... }
當控制器在完成邏輯處理後,一般會產生一些信息,這些信息就是須要返回給用戶並在瀏覽器上顯示的信息,它們被稱爲模型(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【入門】就這一篇
對象關係映射(Object-Relational Mapping,簡稱ORM)是一種爲了解決程序的面向對象模型與數據庫的關係模型互不匹配問題的技術;
簡單的說,ORM是經過使用描述對象和數據庫之間映射的元數據(在Java中能夠用XML或者是註解),將程序中的對象自動持久化到關係數據庫中或者將關係數據庫表中的行轉換成Java對象,其本質上就是將數據從一種形式轉換到另一種形式。
在咱們傳統的 JDBC 中,咱們除了須要本身提供 SQL 外,還必須操做 Connection、Statment、ResultSet,不只如此,爲了訪問不一樣的表,不一樣字段的數據,咱們須要些不少雷同模板化的代碼,閒的繁瑣又枯燥。
而咱們在使用了 MyBatis 以後,只須要提供 SQL 語句就行了,其他的諸如:創建鏈接、操做 Statment、ResultSet,處理 JDBC 相關異常等等均可以交給 MyBatis 去處理,咱們的關注點因而能夠就此集中在 SQL 語句上,關注在增刪改查這些操做層面上。
而且 MyBatis 支持使用簡單的 XML 或註解來配置和映射原生信息,將接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java對象)映射成數據庫中的記錄。
#
和 $
的區別區別以下:
#
符號將傳入的數據都當作一個字符串,會對自動傳入的數據加一個雙引號$
符號將傳入的數據直接顯示生成SQL中。#
符號存在預編譯的過程,,對問號賦值,防止SQL注入。$
符號是直譯的方式,通常用在orderby {列名} 語句中。#
號就不要用$
符號在 Web 系統中,最重要的操做就是查詢數據庫中的數據。可是有些時候查詢數據的頻率很是高,這是很耗費數據庫資源的,每每會致使數據庫查詢效率極低,影響客戶的操做體驗。因而咱們能夠將一些變更不大且訪問頻率高的數據,放置在一個緩存容器中,用戶下一次查詢時就從緩存容器中獲取結果。
更多深刻MyBatis的內容戳這裏:MyBatis(2)——MyBatis 深刻學習
在早期 Java Web 的開發中,統一把顯示層、控制層、數據層的操做所有交給 JSP 或者 JavaBean 來進行處理,咱們稱之爲 Model1:
正由於上面的種種弊端,因此很快這種方式就被 Servlet + JSP + Java Bean 所替代了,早期的 MVC 模型(Model2)就像下圖這樣:
首先用戶的請求會到達 Servlet,而後根據請求調用相應的 Java Bean,並把全部的顯示結果交給 JSP 去完成,這樣的模式咱們就稱爲 MVC 模式。
擴展閱讀:Web開發模式
爲解決持久層中一直未處理好的數據庫事務的編程,又爲了迎合 NoSQL 的強勢崛起,Spring MVC 給出了方案:
傳統的模型層被拆分爲了業務層(Service)和數據訪問層(DAO,Data Access Object)。在 Service 下能夠經過 Spring 的聲明式事務操做數據訪問層,而在業務層上還容許咱們訪問 NoSQL ,這樣就可以知足異軍突起的 NoSQL 的使用了,它能夠大大提升互聯網系統的性能。
回顧咱們以前的 SSM 項目,搭建過程仍是比較繁瑣的,須要:
而使用 Spring Boot 來開發項目則只須要很是少的幾個配置就能夠搭建起來一個 Web 項目,而且利用 IDEA 能夠自動生成生成,這簡直是太爽了...
Spring Boot 因爲筆者尚未深刻學習..因此細節部分請讀者自行收集...
歡迎轉載,轉載請註明出處!轉載自@我沒有三顆心臟