面試心得與總結-——答案整理
1.一個常見的誤解是以為session在有客戶端訪問時就被建立,然而事實是直到某server端程式呼叫 HttpServletRequest.getSession(true)這樣的語句時才被建立,注意如果JSP沒有顯示的使用<% @page session="false"%> 關閉session,則JSP檔案在編譯成Servlet時將會自動加上這樣一條語句 HttpSession session = HttpServletRequest.getSession(true);這也是JSP中隱含的session物件的來歷。由於session會消耗記憶體資源,因此,如果不打算使用session,應該在所有的JSP中關閉它。
2.Session刪除的時間是:
1)Session超時:超時指的是連續一定時間伺服器沒有收到該Session所對應客戶端的請求,並且這個時間超過了伺服器設定的Session超時的最大時間。
2)程式呼叫HttpSession.invalidate()下載
3)伺服器關閉或服務停止
3.session的id是從哪裡來的,sessionID是如何使用的:當客戶端第一次請求session物件時候,伺服器會為客戶端建立一個session,並將通過特殊演算法算出一個session的ID,用來標識該session物件,當瀏覽器下次(session繼續有效時)請求別的資源的時候,瀏覽器會偷偷地將sessionID放置到請求頭中,伺服器接收到請求後就得到該請求的sessionID,伺服器找到該id的session返還給請求者(Servlet)使用。一個會話只能有一個session物件,對session來說是隻認id不認人
4.如何做到在瀏覽器關閉時刪除session下載
嚴格的講,做不到這一點。可以做一點努力的辦法是在所有的客戶端頁面裡使用javascript程式碼window.oncolose來監視瀏覽器的關閉動作,然後向伺服器傳送一個請求來刪除session。但是對於瀏覽器崩潰或者強行殺死程序這些非常規手段仍然無能為力
5.跨應用程式的session共享下載
常常有這樣的情況,一個大專案被分割成若干小專案開發,為了能夠互不干擾,要求每個小專案作為一個單獨的web應用程式開發,可是到了最後突然發現某幾個小專案之間需要共享一些資訊,或者想使用session來實現SSO(single sign on),在session中儲存login的使用者資訊,最自然的要求是應用程式間能夠訪問彼此的session。
然而按照Servlet規範,session的作用範圍應該僅僅限於當前應用程式下,不同的應用程式之間是不能夠互相訪問對方的session的。各個應用伺服器從實際效果上都遵守了這一規範,但是實現的細節卻可能各有不同,因此解決跨應用程式session共享的方法也各不相同。
首先來看一下Tomcat是如何實現web應用程式之間session的隔離的,從 Tomcat設定的cookie路徑來看,它對不同的應用程式設定的cookie路徑是不同的,這樣不同的應用程式所用的session id是不同的,因此即使在同一個瀏覽器窗口裡訪問不同的應用程式,傳送給伺服器的session id也可以是不同的。下載
6.訪問*.html的靜態資源因為不會被編譯為Servlet,也就不涉及session的問題
7.有個HttpSessionListener是怎麼回事下載
你可以建立這樣的listener去監控session的建立和銷燬事件,使得在發生這樣的事件時你可以做一些相應的工作。注意是session的建立和銷燬動作觸發listener,而不是相反。類似的與HttpSession有關的listener還有HttpSessionBindingListener,HttpSessionActivationListener和HttpSessionAttributeListener
10.
3.J3.JSP的常用指令下載
isErrorPage(是否能使用Exception物件),isELIgnored(是否忽略表示式)
三個編譯指令為:page、include、taglib。注意與jsp行為的區別,這三個指令值在編譯期間的,動作或者行為是在執行期間。
1:page指令:(用來指明該jsp頁面的一些屬性)通常位於jsp頁面的頂端,同一個頁面可以有多個page指令。在page指令的屬性中,IsErrorPage屬性,設定本 JSP 頁面是否為錯誤處理程式。如果該頁面本身己是錯誤處理頁面,則無須使用 errorPage 屬性。errorPage屬性表示出現錯誤以後跳轉到哪一個網頁。
2:include指令,使用 include 指令,可以將一個外部檔案嵌入到當前 JSP 檔案中,同時解析這個頁面中的 JSP 語句(如果有的話)。這是個靜態的 include 語旬,不會檢查所包含 JSP 頁面的變化。如果被嵌入的檔案經常需要改變,建議使用<jsp:include>操作指令,因為它是動態的include 語句。
3:taglib指令,該指令用來指明jsp頁面內使用的jsp標籤庫,有兩個屬性uri(類庫地址)和prefix;
4、什麼情況下呼叫doGet()和doPost()?下載
Jsp頁面中的form標籤裡的method屬性為get時呼叫doGet(),為post時呼叫doPost()。
一般的運用都會在doget方法中呼叫doPost方法,那樣不管是對於get請求方式還是post請求方式都可以用doPost()方法處理。
1、通過表單提交到的servlet,看form的method是get還是post
2、通過連結<a href....>訪問的servlet,doGet
3、直接在IE位址列中鍵入的servlet地址,doGet下載
1、get是吧引數資料佇列加到提交表單的Action屬性所指的url中,值和表單內各個欄位--對應,在url中可以看到。
2、Get是不安全的,因為在傳輸過程,資料被放在請求的URL章,而如今現有的很多伺服器,代理伺服器或者使用者代理都會將請求URL記錄到日誌檔案中,然後放在某個地方,這樣就可能會有一些隱私的資訊被第三方看到
3、Get傳輸的資料量小,這主要是因為受URL長度限制;而Post方式提交,所以在上傳檔案只能使用Post
4、servlet的生命週期下載
(在繼承HttpServlet幾類的時候,其實可以說明什麼都不用寫,因為HttpServlet是一個抽象類,裡面沒有抽象方法要求我們必須實現,而是對對我們常用的doGet,doPost方法進行了簡單的定義,我們要寫自己的Servlet,就要繼承HttpServlet類,然後顯示的定義和httpServlet中類一直方法簽名進行覆蓋,在httpServlet類中的service方法會通過判斷請求的是get還是post方法,然後呼叫doget方法還是dopost方法,因此我們也可以直接覆蓋HttpServlet中的service方法,這要不管什麼什麼請求都可以用一個方法來解決掉,忽略了get和post方法。在HttpServlet類的父類是一個GenericServlet,該類就與servlet的初始化關係比較大了,該類中定義init()方法,service方法,destroy()方法,我們在自己的servlet中可以也可以顯示覆蓋這幾個方法,這幾個方法被上層呼叫的順序是先呼叫init()方法,然後是呼叫servcie方法,最後呼叫destroy()方法,我們可以在這幾個方法中寫入自己的方法,以決定呼叫每一個servlet之前或者銷燬之前都做什麼樣的動作)
web容器載入servlet(這裡所說的servlet從GenericServlet方法開始說起,之後子類都屬於該個servlet),生命週期開始。通過呼叫servlet的init()方法進行servlet的初始化。通過呼叫service()方法實現,根據請求的不同調用不同的do***()方法。結束服務,web容器呼叫servlet的destroy()方法。
Servlet生命週期分為三個階段:下載
1,初始化階段 呼叫init()方法
2,響應客戶請求階段 呼叫service()方法
3,終止階段 呼叫destroy()方法(在這兒是銷燬的時候呼叫destroy方法進行關閉資源等,而不是呼叫destroy()方法就可以銷燬servlet例項,具體怎麼銷燬,我暫時不知道,有可能該servlet例項長時間不用的話容器直接交給虛擬機器銷燬)
一個servlet被載入記憶體以後,除非手動銷燬或者關閉伺服器,否則是不會被銷燬的。
5、如何現實servlet的單執行緒模式下載
1:如果是通過jsp實現servlet單執行緒,則可以通過如下設定
<%@ page isThreadSafe=”false”%>,(記憶:之所以是false,是因為此時不用sychronized修飾每一個servlet物件的service方法了,所以就不是執行緒安全的)此時該servlet方法繼承SimpleThreadModel介面,該介面是一個空介面,實現了該介面的servlet容器能保證只有一個執行緒呼叫該servlet的service方法,是保證servlet一次只能有一個請求,但是由於service方法都是執行緒私有,這樣設計的目的是為了只有一個執行緒呼叫service方法,則在service中呼叫的成員屬性就不會出現執行緒被兩個執行緒同時更改的效果,此時達到加syschronized的目的(這樣也就不用加鎖了,節省了開支),但是在讓一個servlet同一時刻只處理一個servlet,這樣嚴重影響了容器的效能,所以會建立很多個繼承了SimpleThreadModel的servlet的多個例項,然後存入servlet例項池,才能提高效能,所以這樣的servlet並不是單例的。
2:Servlet容器預設是隻建立一個servlet物件,:多個執行緒可以同時呼叫一個例項的service方法,所以在servlet中一般是不要用到成員屬性,(要用的話就要加鎖,這種事最安全的,繼承SimpleThreadModel被認為是不安全的,因為他不加鎖同步)。下載
3:servlet不是執行緒安全的;用到成員屬性時需要加鎖同步。
6、頁面間物件傳遞的方法下載
request,session,application,cookie等
Request,session,application都是在伺服器端傳值,而cookie是在客戶端和伺服器端傳值。
7、四種會話跟蹤技術下載
1:(儲存使用者和伺服器之間會話狀態及資訊科技叫會話跟蹤技術),我們之前所說的只有三種,隱藏表單,url重定向,cookie,是因為我們用這三種來傳輸sessionid,他們的目的也是為了跟蹤技術,如果沒有session,他們也能一定程度上的實現跟蹤;所以說跟蹤技術其實是四種,cookie,url重定向,隱藏表單,session;
8、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):刪除請求中的一個屬性
9、Servlet執行時一般實現哪幾個方法?
public void init(ServletConfig config)
public ServletConfig getServletConfig()
public String getServletInfo()
public void service(ServletRequest request,ServletResponse response)
public void destroy()JSP
10、跨域請求
1:做過跨越多個網站的Ajax開發的朋友都知道,如果在A網站中,我們希望使用Ajax來獲得B網站中的特定內容,如果A網站與B網站不在同一個域中,那麼就出現了跨域訪問問題。下載
2:IE對於跨域訪問的處理是,彈出警告框,提醒使用者。如果使用者將該網站納入可信任網站,或者調低安全級別,那麼這個問題IE就不會在提醒你。
FireFox等其它非微軟的瀏覽器遇到跨域訪問,則解決方案統一是拒絕訪問。
3:跨域訪問的解決方式3中
1,<iframe src="http://localhost:8080/CmsUI/2.html" id="i">
2.使用javascript的<script src>標籤的src,我們最常用了,去下載別的庫檔案
3.使用jsonp實現跨域
下載4.瀏覽器的“同源策略(SOP:Same Origin Policy)”。 簡而言之,就是瀏覽器限制指令碼程式只能和同協議、同域名、同埠的指令碼進行互動,這包括共享和傳遞變數等。cookie的傳遞也是遵從同樣策略。這就造成一些涉及到多個伺服器的應用在整合時一些麻煩。跨域訪問的問題造成A站點的Ajax程式碼無法訪問B站點的資料。
5:跨域訪問瀏覽器會阻止;
11.說出在JSP頁面裡是怎麼分頁的?下載
頁面需要儲存以下引數:總行數:根據sql語句得到總行數,每頁顯示行數:設定值,當前頁數:請求引數,頁面根據當前頁數和每頁行數計算出當前頁第一行行數,定位結果集到此行,對結果集取出每頁顯示行數的行即可
21:filter的作用是什麼?主要實現什麼方法?doFilter()方法中引數request,response的全稱是什麼?
1:filter使使用者可以改變一個request和修改一個response,它並不是一個servlet,不能產生一個response。它能在一個request到達servlet之前預處理request,也可以在離開servlet時處理response.換句話說,filter其實是一個“servlet chaining”(servlet鏈)。
2:一個filter包括:在servlet呼叫之前截獲在servlet呼叫之前檢查servlet的request根據需要修改request頭和request資料,根據需要修改response頭和response資料,在servlet呼叫之後截獲。
3:Filter介面定義了三個方法:1, void setFilterConfig(FilterConfig config); //設定filter的配置物件。
2, FilterConfig getFilterConfig();//返回filter的配置物件 下載
過濾器中的servlet的FilterConfig物件和servlet中ServletConfig物件的作用一樣,就是在web配置檔案中讀取該servlet或者給filter的配置的一些資訊,如區域性變數名之類的。
3, doFilter(ServletRequest req,ServletResponse res,FilterChain chain);//執行filer工作。
request 全稱:HttpServletRequest,response全稱:HttpServletResponse
4:過濾器鏈:ApplicationFilterChain這個是不是覺得和流水線的valve的設計模式很像呢,將各個過濾器加入到該鏈中,然後將該鏈的物件傳給doFilter方法(doFilter(ServletRaquest request, ServletResponse response, FilterChain chain))然後第一個Filter處理器處理完以後,呼叫過濾器鏈上的第二個Filter的doFilter方法,當doFilter是最後一個方法的時候,就呼叫servlet的service方法。因為servlet的init()方法是servlet在載入的時候就執行,而且只執行一次,因此就他肯定是在Filter被呼叫之前的。
22,我們沒有寫servlet的構造方法,那麼容器是怎麼建立servlet的例項呢?
容器會自動為servlet寫一個無參的構造方法,並通過Class.forName(className).newInstance()來建立servlet例項
12:單點登入怎麼實現?
1:單點登入SSO(Single Sign On)說得簡單點就是在一個多系統共存的環境下,使用者在一處登入後,就不用在其他系統中登入,也就是使用者的一次登入能得到其他所有系統的信任。單點登入在大型網站裡使用得非常頻繁,例如像阿里巴巴這樣的網站,在網站的背後是成百上千的子系統,
方法1:將登入的session持久化到資料庫,在訪問另一的主機上的應用的時候遍歷資料庫中的session,通過sessionid找到對應的session來辨別。(我自己的思路)(持久化到快取伺服器中也可以,就是不可靠,這樣就不用每訪問一次就去資料庫中找,)
方法2:使用最簡單的方法就是cookie,在第一層登入成功以後,給客戶端一個cookie,然後每次訪問別的子系統的時候,都帶上該cookie資訊,就ok啦。(缺點,不安全,不能跨域登入)
方法3:普遍採用的方案,當第一次登入成功以後,伺服器產生可以免登入的url傳送到客戶端,客戶端用免登入的url去訪問分系統的時候,分系統就驗證該客戶端的一些資訊,驗證通過就免登入,不通過就不允許登入,這樣的問題也就有,服務端還是得儲存相關的臨時信任資料,有可能不是session,但是這裡就可以用快取了,一般臨時資訊不需要持久化。