基礎面試題

 

- [Servlet總結]
- [闡述Servlet和CGI的區別?]
- [CGI的不足之處:]
- [Servlet的優勢:]
- [Servlet接口中有哪些方法及Servlet生命週期探祕]
- [get和post請求的區別](#get和post請求的區別)
- [什麼狀況下調用doGet()和doPost()]
- [轉發(Forward)和重定向(Redirect)的區別]
- [自動刷新\(Refresh\)]
- [Servlet與線程安全]
- [JSP和Servlet是什麼關係]
- [JSP工做原理]
- [JSP有哪些內置對象、做用分別是什麼]
- [Request對象的主要方法有哪些]
- [request.getAttribute\(\)和 request.getParameter\(\)有何區別]
- [include指令include的行爲的區別]
- [JSP九大內置對象,七大動做,三大指令]
- [講解JSP中的四種做用域]
- [如何實現JSP或Servlet的單線程模式]
- [實現會話跟蹤的技術有哪些]
- [Cookie和Session的的區別]html

 

## Servlet總結java

在Java Web程序中,**Servlet**主要負責接收用戶請求**HttpServletRequest**,在**doGet()**,**doPost()**中作相應的處理,並將迴應**HttpServletResponse**反饋給用戶。Servlet能夠設置初始化參數,供Servlet內部使用。一個Servlet類只會有一個實例,在它初始化時調用**init()方法**,銷燬時調用**destroy()方法**。**Servlet須要在web.xml中配置**(MyEclipse中建立Servlet會自動配置),**一個Servlet能夠設置多個URL訪問**。**Servlet不是線程安全**,所以要謹慎使用類變量。web

 

## 闡述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請求用來從服務器上得到資源,而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方式就是被設計爲查詢用的。

還有另一種回答。推薦你們看一下:

- https://www.zhihu.com/question/28586791
- https://mp.weixin.qq.com/s?__biz=MzI3NzIzMzg3Mw==&mid=100000054&idx=1&sn=71f6c214f3833d9ca20b9f7dcd9d33e4#rd

## 什麼狀況下調用doGet()和doPost()
Form標籤裏的method的屬性爲get時調用doGet(),爲post時調用doPost()。

 

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

**轉發是服務器行爲,重定向是客戶端行爲。**

**轉發(Forword)**
經過RequestDispatcher對象的forward(HttpServletRequest request,HttpServletResponse response)方法實現的。RequestDispatcher能夠經過HttpServletRequest 的getRequestDispatcher()方法得到。例以下面的代碼就是跳轉到login_success.jsp頁面。
```java
request.getRequestDispatcher("login_success.jsp").forward(request, response);
```
**重定向(Redirect)** 是利用服務器返回的狀態嗎來實現的。客戶端瀏覽器請求服務器的時候,服務器會返回一個狀態碼。服務器經過HttpServletRequestResponse的setStatus(int status)方法設置狀態碼。若是服務器返回301或者302,則瀏覽器會到新的網址從新請求該資源。

1. **從地址欄顯示來講**

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

2. **從數據共享來講**

forward:轉發頁面和轉發到的頁面能夠共享request裏面的數據.
redirect:不能共享數據.

3. **從運用地方來講**

forward:通常用於用戶登錄的時候,根據角色轉發到相應的模塊.
redirect:通常用於用戶註銷登錄時返回主頁面和跳轉到其它的網站等

4. 從效率來講

forward:高.
redirect:低.

 

## 自動刷新(Refresh)
自動刷新不只能夠實現一段時間以後自動跳轉到另外一個頁面,還能夠實現一段時間以後自動刷新本頁面。Servlet中經過HttpServletResponse對象設置Header屬性實現自動刷新例如:
```java
Response.setHeader("Refresh","5;URL=http://localhost:8080/servlet/example.htm");
```
其中5爲時間,單位爲秒。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工做原理](https://user-gold-cdn.xitu.io/2018/3/31/1627bee073079a28?w=675&h=292&f=jpeg&s=133553)
因爲JSP只會在客戶端第一次請求的時候被編譯 ,所以第一次請求JSP時會感受比較慢,以後就會感受快不少。若是把服務器保存的class文件刪除,服務器也會從新編譯JSP。

開發Web程序時常常須要修改JSP。Tomcat可以自動檢測到JSP程序的改動。若是檢測到JSP源代碼發生了改動。Tomcat會在下次客戶端請求JSP時從新編譯JSP,而不須要重啓Tomcat。這種自動檢測功能是默認開啓的,檢測改動會消耗少許的時間,在部署Web應用的時候能夠在web.xml中將它關掉。

 

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

 

## JSP有哪些內置對象、做用分別是什麼
[JSP內置對象 - CSDN博客 ](http://blog.csdn.net/qq_34337272/article/details/64310849 )

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 地址" %>

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

 

## JSP九大內置對象,七大動做,三大指令
[JSP九大內置對象,七大動做,三大指令總結](http://blog.csdn.net/qq_34337272/article/details/64310849)

 

## 講解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
```java
Cookie c =new Cookie("name","value"); //建立Cookie
c.setMaxAge(60*60*24); //設置最大時效,此處設置的最大時效爲一天
response.addCookie(c); //把Cookie放入到HTTP響應中
```
從客戶端讀取Cookie
```java
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功能,因爲保存在本地,有必定的安全風險。

2. URL 重寫

在URL中添加用戶會話的信息做爲請求的參數,或者將惟一的會話ID添加到URL結尾以標識一個會話。

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

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

3.隱藏的表單域
```html
<input type="hidden" name ="session" value="..."/>
```

優勢:Cookie被禁時可使用

缺點:全部頁面必須是表單提交以後的結果。

 

4. 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的比較

相關文章
相關標籤/搜索