超詳細的Java面試題總結(四 )之JavaWeb基礎知識總結

Guide哥發表於2018-03-31

系列文章請檢視:

超詳細的Java面試題總結(一)之Java基礎知識篇

超詳細的Java面試題總結(二)之Java基礎知識篇

超詳細的Java面試題總結(三)之Java集合篇常見問題

下面的都是自己之前在學習JavaWeb的時候總結的,對於鞏固JavaWeb的基礎知識應該有很大幫助。後面還會把框架的面試題總結一下。

Servlet總結

在Java Web程式中,Servlet主要負責接收使用者請求HttpServletRequest,在doGet(),doPost()中做相應的處理,並將回應HttpServletResponse反饋給使用者。Servlet可以設定初始化引數,供Servlet內部使用。一個Servlet類只會有一個例項,在它初始化時呼叫init()方法,銷燬時呼叫destroy()方法Servlet需要在web.xml中配置(MyEclipse中建立Servlet會自動配置),一個Servlet可以設定多個URL訪問Servlet不是執行緒安全,因此要謹慎使用類變數。

闡述Servlet和CGI的區別?

CGI的不足之處:

1,需要為每個請求啟動一個操作CGI程式的系統程式。如果請求頻繁,這將會帶來很大的開銷。

2,需要為每個請求載入和執行一個CGI程式,這將帶來很大的開銷

3,需要重複編寫處理網路協議的程式碼以及編碼,這些工作都是非常耗時的。

Servlet的優點:

1,只需要啟動一個作業系統程式以及載入一個JVM,大大降低了系統的開銷

2,如果多個請求需要做同樣處理的時候,這時候只需要載入一個類,這也大大降低了開銷

3,所有動態載入的類可以實現對網路協議以及請求解碼的共享,大大降低了工作量。

4,Servlet能直接和Web伺服器互動,而普通的CGI程式不能。Servlet還能在各個程式之間共享資料,使資料庫連線池之類的功能很容易實現。

補充:Sun Microsystems公司在1996年釋出Servlet技術就是為了和CGI進行競爭,Servlet是一個特殊的Java程式,一個基於Java的Web應用通常包含一個或多個Servlet類。Servlet不能夠自行建立並執行,它是在Servlet容器中執行的,容器將使用者的請求傳遞給Servlet程式,並將Servlet的響應回傳給使用者。通常一個Servlet會關聯一個或多個JSP頁面。以前CGI經常因為效能開銷上的問題被詬病,然而Fast CGI早就已經解決了CGI效率上的問題,所以面試的時候大可不必信口開河的詬病CGI,事實上有很多你熟悉的網站都使用了CGI技術。

參考:《javaweb整合開發王者歸來》P7

Servlet介面中有哪些方法及Servlet生命週期探祕

Servlet介面定義了5個方法,其中前三個方法與Servlet生命週期相關

  • void init(ServletConfig config) throws ServletException
  • void service(ServletRequest req, ServletResponse resp) throws ServletException, java.io.IOException
  • void destory()
  • java.lang.String getServletInfo()
  • ServletConfig getServletConfig()

生命週期: Web容器載入Servlet並將其例項化後,Servlet生命週期開始,容器執行其init()方法進行Servlet的初始化;請求到達時呼叫Servlet的service()方法,service()方法會根據需要呼叫與請求對應的doGet或doPost等方法;當伺服器關閉或專案被解除安裝時伺服器會將Servlet例項銷燬,此時會呼叫Servlet的destroy()方法init方法和destory方法只會執行一次,service方法客戶端每次請求Servlet都會執行。Servlet中有時會用到一些需要初始化與銷燬的資源,因此可以把初始化資源的程式碼放入init方法中,銷燬資源的程式碼放入destroy方法中,這樣就不需要每次處理客戶端的請求都要初始化與銷燬資源。

參考:《javaweb整合開發王者歸來》P81

get和post請求的區別?

①get請求用來從伺服器上獲得資源,而post是用來向伺服器提交資料;

②get將表單中資料按照name=value的形式,新增到action 所指向的URL 後面,並且兩者使用"?"連線,而各個變數之間使用"&"連線;post是將表單中的資料放在HTTP協議的請求頭或訊息體中,傳遞到action所指向URL;

③get傳輸的資料要受到URL長度限制(1024位元組即256個字元);而post可以傳輸大量的資料,上傳檔案通常要使用post方式;

④使用get時引數會顯示在位址列上,如果這些資料不是敏感資料,那麼可以使用get;對於敏感資料還是應用使用post;

⑤get使用MIME型別application/x-www-form-urlencoded的URL編碼(也叫百分號編碼)文字的格式傳遞引數,保證被傳送的引數由遵循規範的文字組成,例如一個空格的編碼是"%20"。

補充:GET方式提交表單的典型應用是搜尋引擎。GET方式就是被設計為查詢用的。

什麼情況下呼叫doGet()和doPost()?

Form標籤裡的method的屬性為get時呼叫doGet(),為post時呼叫doPost()。

轉發(Forward)和重定向(Redirect)的區別?

轉發是伺服器行為,重定向是客戶端行為。

轉發(Forword) 通過RequestDispatcher物件的forward(HttpServletRequest request,HttpServletResponse response)方法實現的。RequestDispatcher可以通過HttpServletRequest 的getRequestDispatcher()方法獲得。例如下面的程式碼就是跳轉到login_success.jsp頁面。

     request.getRequestDispatcher("login_success.jsp").forward(request, response);
複製程式碼

重定向(Redirect) 是利用伺服器返回的狀態嗎來實現的。客戶端瀏覽器請求伺服器的時候,伺服器會返回一個狀態碼。伺服器通過HttpServletRequestResponse的setStatus(int status)方法設定狀態碼。如果伺服器返回301或者302,則瀏覽器會到新的網址重新請求該資源。

  1. 從位址列顯示來說

forward是伺服器請求資源,伺服器直接訪問目標地址的URL,把那個URL的響應內容讀取過來,然後把這些內容再發給瀏覽器.瀏覽器根本不知道伺服器傳送的內容從哪裡來的,所以它的位址列還是原來的地址. redirect是服務端根據邏輯,傳送一個狀態碼,告訴瀏覽器重新去請求那個地址.所以位址列顯示的是新的URL.

  1. 從資料共享來說

forward:轉發頁面和轉發到的頁面可以共享request裡面的資料. redirect:不能共享資料.

  1. 從運用地方來說

forward:一般用於使用者登陸的時候,根據角色轉發到相應的模組. redirect:一般用於使用者登出登陸時返回主頁面和跳轉到其它的網站等

  1. 從效率來說

forward:高. redirect:低.

自動重新整理(Refresh)

自動重新整理不僅可以實現一段時間之後自動跳轉到另一個頁面,還可以實現一段時間之後自動重新整理本頁面。Servlet中通過HttpServletResponse物件設定Header屬性實現自動重新整理例如:

Response.setHeader("Refresh","1000;URL=http://localhost:8080/servlet/example.htm");
複製程式碼

其中1000為時間,單位為毫秒。URL指定就是要跳轉的頁面(如果設定自己的路徑,就會實現沒過一秒自動重新整理本頁面一次)

Servlet與執行緒安全

Servlet不是執行緒安全的,多執行緒併發的讀寫會導致資料不同步的問題。 解決的辦法是儘量不要定義name屬性,而是要把name變數分別定義在doGet()和doPost()方法內。雖然使用synchronized(name){}語句塊可以解決問題,但是會造成執行緒的等待,不是很科學的辦法。 注意:多執行緒的併發的讀寫Servlet類屬性會導致資料不同步。但是如果只是併發地讀取屬性而不寫入,則不存在資料不同步的問題。因此Servlet裡的只讀屬性最好定義為final型別的。

參考:《javaweb整合開發王者歸來》P92

JSP和Servlet是什麼關係?

其實這個問題在上面已經闡述過了,Servlet是一個特殊的Java程式,它執行於伺服器的JVM中,能夠依靠伺服器的支援向瀏覽器提供顯示內容。JSP本質上是Servlet的一種簡易形式,JSP會被伺服器處理成一個類似於Servlet的Java程式,可以簡化頁面內容的生成。Servlet和JSP最主要的不同點在於,Servlet的應用邏輯是在Java檔案中,並且完全從表示層中的HTML分離開來。而JSP的情況是Java和HTML可以組合成一個副檔名為.jsp的檔案。有人說,Servlet就是在Java中寫HTML,而JSP就是在HTML中寫Java程式碼,當然這個說法是很片面且不夠準確的。JSP側重於檢視,Servlet更側重於控制邏輯,在MVC架構模式中,JSP適合充當檢視(view)而Servlet適合充當控制器(controller)。

JSP工作原理:

JSP是一種Servlet,但是與HttpServlet的工作方式不太一樣。HttpServlet是先由原始碼編譯為class檔案後部署到伺服器下,為先編譯後部署。而JSP則是先部署後編譯。JSP會在客戶端第一次請求JSP檔案時被編譯為HttpJspPage類(介面Servlet的一個子類)。該類會被伺服器臨時存放在伺服器工作目錄裡面。下面通過例項給大家介紹。 工程JspLoginDemo下有一個名為login.jsp的Jsp檔案,把工程第一次部署到伺服器上後訪問這個Jsp檔案,我們發現這個目錄下多了下圖這兩個東東。 .class檔案便是JSP對應的Servlet。編譯完畢後再執行class檔案來響應客戶端請求。以後客戶端訪問login.jsp的時候,Tomcat將不再重新編譯JSP檔案,而是直接呼叫class檔案來響應客戶端請求。

JSP工作原理
由於JSP只會在客戶端第一次請求的時候被編譯 ,因此第一次請求JSP時會感覺比較慢,之後就會感覺快很多。如果把伺服器儲存的class檔案刪除,伺服器也會重新編譯JSP。

開發Web程式時經常需要修改JSP。Tomcat能夠自動檢測到JSP程式的改動。如果檢測到JSP原始碼發生了改動。Tomcat會在下次客戶端請求JSP時重新編譯JSP,而不需要重啟Tomcat。這種自動檢測功能是預設開啟的,檢測改動會消耗少量的時間,在部署Web應用的時候可以在web.xml中將它關掉。

參考:《javaweb整合開發王者歸來》P97

JSP有哪些內建物件?作用分別是什麼?

JSP內建物件 - CSDN部落格

JSP有9個內建物件:

  • request:封裝客戶端的請求,其中包含來自GET或POST請求的引數;
  • response:封裝伺服器對客戶端的響應;
  • pageContext:通過該物件可以獲取其他物件;
  • session:封裝使用者會話的物件;
  • application:封裝伺服器執行環境的物件;
  • out:輸出伺服器響應的輸出流物件;
  • config:Web應用的配置物件;
  • page:JSP頁面本身(相當於Java程式中的this);
  • exception:封裝頁面丟擲異常的物件。

Request物件的主要方法有哪些?

  • setAttribute(String name,Object):設定名字為name的request 的引數值
  • getAttribute(String name):返回由name指定的屬性值
  • getAttributeNames():返回request 物件所有屬性的名字集合,結果是一個列舉的例項
  • getCookies():返回客戶端的所有 Cookie 物件,結果是一個Cookie 陣列
  • getCharacterEncoding() :返回請求中的字元編碼方式 = getContentLength() :返回請求的 Body的長度
  • getHeader(String name) :獲得HTTP協議定義的檔案頭資訊
  • getHeaders(String name) :返回指定名字的request Header 的所有值,結果是一個列舉的例項
  • getHeaderNames() :返回所以request Header 的名字,結果是一個列舉的例項
  • getInputStream() :返回請求的輸入流,用於獲得請求中的資料
  • getMethod() :獲得客戶端向伺服器端傳送資料的方法
  • getParameter(String name) :獲得客戶端傳送給伺服器端的有 name指定的引數值
  • getParameterNames() :獲得客戶端傳送給伺服器端的所有引數的名字,結果是一個列舉的例項
  • getParameterValues(String name):獲得有name指定的引數的所有值
  • getProtocol():獲取客戶端向伺服器端傳送資料所依據的協議名稱
  • getQueryString() :獲得查詢字串
  • getRequestURI() :獲取發出請求字串的客戶端地址
  • getRemoteAddr():獲取客戶端的 IP 地址
  • getRemoteHost() :獲取客戶端的名字
  • getSession([Boolean create]) :返回和請求相關 Session
  • getServerName() :獲取伺服器的名字
  • getServletPath():獲取客戶端所請求的指令碼檔案的路徑
  • getServerPort():獲取伺服器的埠號
  • removeAttribute(String name):刪除請求中的一個屬性

request.getAttribute()和 request.getParameter()有何區別?

從獲取方向來看:

getParameter()是獲取 POST/GET 傳遞的引數值;

getAttribute()是獲取物件容器中的資料值;

從用途來看:

getParameter用於客戶端重定向時,即點選了連結或提交按扭時傳值用,即用於在用表單或url重定向傳值時接收資料用。

getAttribute用於伺服器端重定向時,即在 sevlet 中使用了 forward 函式,或 struts 中使用了 mapping.findForward。 getAttribute 只能收到程式用 setAttribute 傳過來的值。

另外,可以用 setAttribute,getAttribute 傳送接收物件.而 getParameter 顯然只能傳字串。 setAttribute 是應用伺服器把這個物件放在該頁面所對應的一塊記憶體中去,當你的頁面伺服器重定向到另一個頁面時,應用伺服器會把這塊記憶體拷貝另一個頁面所對應的記憶體中。這樣getAttribute就能取得你所設下的值,當然這種方法可以傳物件。session也一樣,只是物件在記憶體中的生命週期不一樣而已。getParameter只是應用伺服器在分析你送上來的 request頁面的文字時,取得你設在表單或 url 重定向時的值。

總結:

getParameter 返回的是String,用於讀取提交的表單中的值;(獲取之後會根據實際需要轉換為自己需要的相應型別,比如整型,日期型別啊等等)

getAttribute 返回的是Object,需進行轉換,可用setAttribute 設定成任意物件,使用很靈活,可隨時用

include指令include的行為的區別

include指令: JSP可以通過include指令來包含其他檔案。被包含的檔案可以是JSP檔案、HTML檔案或文字檔案。包含的檔案就好像是該JSP檔案的一部分,會被同時編譯執行。 語法格式如下: <%@ include file="檔案相對 url 地址" %>

include動作: jsp:include動作元素用來包含靜態和動態的檔案。該動作把指定檔案插入正在生成的頁面。語法格式如下: <jsp:include page="相對 URL 地址" flush="true" />

JSP九大內建物件,七大動作,三大指令-

JSP九大內建物件,七大動作,三大指令總結

講解JSP中的四種作用域

JSP中的四種作用域包括page、request、session和application,具體來說:

  • page代表與一個頁面相關的物件和屬性。
  • request代表與Web客戶機發出的一個請求相關的物件和屬性。一個請求可能跨越多個頁面,涉及多個Web元件;需要在頁面顯示的臨時資料可以置於此作用域。
  • session代表與某個使用者與伺服器建立的一次會話相關的物件和屬性。跟某個使用者相關的資料應該放在使用者自己的session中。
  • application代表與整個Web應用程式相關的物件和屬性,它實質上是跨越整個Web應用程式,包括多個頁面、請求和會話的一個全域性作用域。

如何實現JSP或Servlet的單執行緒模式?

對於JSP頁面,可以通過page指令進行設定。 <%@page isThreadSafe=”false”%>

對於Servlet,可以讓自定義的Servlet實現SingleThreadModel標識介面。

說明:如果將JSP或Servlet設定成單執行緒工作模式,會導致每個請求建立一個Servlet例項,這種實踐將導致嚴重的效能問題(伺服器的記憶體壓力很大,還會導致頻繁的垃圾回收),所以通常情況下並不會這麼做。

實現會話跟蹤的技術有哪些?

  1. 使用Cookie

向客戶端傳送Cookie

Cookie c =new Cookie("name","value"); //建立Cookie 
c.setMaxAge(60*60*24); //設定最大時效,此處設定的最大時效為一天
response.addCookie(c); //把Cookie放入到HTTP響應中
複製程式碼

從客戶端讀取Cookie

String name ="name"; 
Cookie[]cookies =request.getCookies(); 
if(cookies !=null){ 
   for(int i= 0;i<cookies.length;i++){ 
    Cookie cookie =cookies[i]; 
    if(name.equals(cookis.getName())) 
    //something is here. 
    //you can get the value 
    cookie.getValue(); 
       
   }
 }

複製程式碼

優點: 資料可以持久儲存,不需要伺服器資源,簡單,基於文字的Key-Value

缺點: 大小受到限制,使用者可以禁用Cookie功能,由於儲存在本地,有一定的安全風險。

  1. URL 重寫

在URL中新增使用者會話的資訊作為請求的引數,或者將唯一的會話ID新增到URL結尾以標識一個會話。

優點: 在Cookie被禁用的時候依然可以使用

缺點: 必須對網站的URL進行編碼,所有頁面必須動態生成,不能用預先記錄下來的URL進行訪問。

3.隱藏的表單域

<input type="hidden" name ="session" value="..."/>
複製程式碼

優點: Cookie被禁時可以使用

缺點: 所有頁面必須是表單提交之後的結果。

  1. HttpSession

在所有會話跟蹤技術中,HttpSession物件是最強大也是功能最多的。當一個使用者第一次訪問某個網站時會自動建立 HttpSession,每個使用者可以訪問他自己的HttpSession。可以通過HttpServletRequest物件的getSession方 法獲得HttpSession,通過HttpSession的setAttribute方法可以將一個值放在HttpSession中,通過呼叫 HttpSession物件的getAttribute方法,同時傳入屬性名就可以獲取儲存在HttpSession中的物件。與上面三種方式不同的 是,HttpSession放在伺服器的記憶體中,因此不要將過大的物件放在裡面,即使目前的Servlet容器可以在記憶體將滿時將HttpSession 中的物件移到其他儲存裝置中,但是這樣勢必影響效能。新增到HttpSession中的值可以是任意Java物件,這個物件最好實現了 Serializable介面,這樣Servlet容器在必要的時候可以將其序列化到檔案中,否則在序列化時就會出現異常。

Cookie和Session的的區別?

  1. 由於HTTP協議是無狀態的協議,所以服務端需要記錄使用者的狀態時,就需要用某種機制來識具體的使用者,這個機制就是Session.典型的場景比如購物車,當你點選下單按鈕時,由於HTTP協議無狀態,所以並不知道是哪個使用者操作的,所以服務端要為特定的使用者建立了特定的Session,用用於標識這個使用者,並且跟蹤使用者,這樣才知道購物車裡面有幾本書。這個Session是儲存在服務端的,有一個唯一標識。在服務端儲存Session的方法很多,記憶體、資料庫、檔案都有。叢集的時候也要考慮Session的轉移,在大型的網站,一般會有專門的Session伺服器叢集,用來儲存使用者會話,這個時候 Session 資訊都是放在記憶體的,使用一些快取服務比如Memcached之類的來放 Session。
  2. 思考一下服務端如何識別特定的客戶?這個時候Cookie就登場了。每次HTTP請求的時候,客戶端都會傳送相應的Cookie資訊到服務端。實際上大多數的應用都是用 Cookie 來實現Session跟蹤的,第一次建立Session的時候,服務端會在HTTP協議中告訴客戶端,需要在 Cookie 裡面記錄一個Session ID,以後每次請求把這個會話ID傳送到伺服器,我就知道你是誰了。有人問,如果客戶端的瀏覽器禁用了 Cookie 怎麼辦?一般這種情況下,會使用一種叫做URL重寫的技術來進行會話跟蹤,即每次HTTP互動,URL後面都會被附加上一個諸如 sid=xxxxx 這樣的引數,服務端據此來識別使用者。
  3. Cookie其實還可以用在一些方便使用者的場景下,設想你某次登陸過一個網站,下次登入的時候不想再次輸入賬號了,怎麼辦?這個資訊可以寫到Cookie裡面,訪問網站的時候,網站頁面的指令碼可以讀取這個資訊,就自動幫你把使用者名稱給填了,能夠方便一下使用者。這也是Cookie名稱的由來,給使用者的一點甜頭。所以,總結一下:Session是在服務端儲存的一個資料結構,用來跟蹤使用者的狀態,這個資料可以儲存在叢集、資料庫、檔案中;Cookie是客戶端儲存使用者資訊的一種機制,用來記錄使用者的一些資訊,也是實現Session的一種方式。

參考:

https://www.zhihu.com/question/19786827/answer/28752144

《javaweb整合開發王者歸來》P158 Cookie和Session的比較

2018/3/31 20:45
現在寢室一片漆黑,趁著電腦還有電把之前學習JavaWeb基礎總結的東西在這裡分享一下。今天停了一天電,現在這個電還沒來電。電腦快沒電了,大家再見。 這些只是JavaWeb基礎知識的一部分,後面會持續更新

分享一下現在寢室的情景,還沒來電,全是黑的:

超詳細的Java面試題總結(四 )之JavaWeb基礎知識總結


歡迎關注我的微信公眾號:"Java面試通關手冊"(堅持原創,分享各種Java學習資源,面試題,優質文章,以及企業級Java實戰專案回覆關鍵字免費領取)::

微信公眾號

相關文章