1. 程式人生 > >【JAVA秒會技術之秒殺面試官】JavaEE常見面試題(一)

【JAVA秒會技術之秒殺面試官】JavaEE常見面試題(一)

parameter 和數 程序 配置 except 查詢 解析 list 就會

1.Struts2中,Action通過什麽方式獲取用戶從頁面輸入的數據,又是通過什麽方法把數據傳給視圖層顯示的?

答:(1)Action從頁面獲取數據的方式有三種:

        ①通過Action屬性接收參數;(例:${pageContext.request.contextPath}/***.action? id=xxxx)

        ②通過域模型獲取參數;(例:ServletActionContext.getRequest().getParameter(arg0))

        ③通過模型驅動獲取參數(例:extends ModelDriven<T>)

(2)Action將數據存入值棧(Value Stack)中,視圖可以通過表達式語言(EL)從值棧中獲取;

2.闡述Struts2中的Action如何編寫,是否采用單例?

答:(1)Struts2的Action有三種寫法:

       ①POJO類——無繼承無實現;

       ②實現Action接口,重寫execute()方法;

       ③繼承ActionSupport(常用);

   (2)Action沒有像Servlet一樣,使用單實例多線程的工作方式,很明顯,每一個Action要接收不同用戶的請求參數,這就意味著Action是有狀態的,因此在設計上使用了,每一個請求對應一個Action的處理方式,所以是多例的。

3.Struts2中,Action並沒有直接收到用戶的請求,那它為什麽可以處理用戶的請求?又憑什麽知道一個請求到底交給哪一個Action來處理?

答:(1)Struts2的核心過濾器收到用戶的請求後,會對用戶的請求進行簡單的預處理(如解析、封裝參數),然後通過反射來創建Action實例,並調用Action中指定的方法來處理用戶請求。

    (2)通知具體調用哪個Action來處理請求的方式,有兩種:

      ①利用配置文件,Struts.xml中配置的<action>標簽來確定;

      ②利用約定,Struts2中可以使用約定(convention)插件。例如:約定xxx總是對應XxxAction,這是對約定優於配置理念的踐行;

4.簡述Struts2異常處理機制?

答:Struts2提供了聲明式的異常處理機制,可以在配置文件中加入如下代碼:

/WEB-INF/pages/error.jsp 5.簡述攔截器的工作原理? 答:在Struts2中,可以實現Interceptor接口或繼承AbstractInterceptor類,來自定義攔截器。 ①接口中的init()方法,在攔截器被創建後立即被調用,它在攔截器的生命周期內只被調用一次,可以在該方法中對相關資源進行必要的初始化; ②每攔截一個請求,intercept()方法就會被調用一次; ③destory()方法將在攔截器銷毀之前被調用。 6.談一下攔截器和過濾器的區別? 答:攔截器和過濾器都可以用來實現橫切關註功能,其區別主要在於: ①攔截器是基於JAVA反射機制的,而過濾器是基於函數回調的 ②過濾器依賴於Servlet容器,而攔截器不依賴於Servlet容器 ③攔截器只能對Action請求起作用(Action中的方法),而過濾器可以對幾乎所有的請求起作用(CSS JSP JS) 7.談一下你的項目選擇Struts2的理由? 答:①Action是POJO類,沒有依賴Servlet API,具有良好的可測試性; ②強大的攔截器,簡化了開發的復雜度; ③支持多種表現層技術:JSP、Freemarker等; ④靈活的驗證方式; ⑤國際化(I18N)支持 ⑥聲明式異常管理; ⑦通過JSON插件簡化Ajax; ⑧通過Spring插件跟Spring整合; 8.Struts2中如何訪問HttpServletRequest、HttpSession和ServletContext三個域對象? 答:有兩種方式: ①通過ServletActionContext的方法獲得; ②通過ServletRequestAware、SessionAware和ServletContextAware接口註入。 9.Struts2中的默認包struts-default有什麽作用? 答:它定義了Struts2內部的眾多攔截器和Result類型,而Struts2很多核心的功能是通過這些內置的攔截器實現,如:從請求中把參數封裝到action、文件上傳和數據校驗等等,都是通過攔截器實現的。在Struts2的配置文件中,自定義的包,繼承了struts-default包,就可以使用Struts2為我們提供這些功能。 10.簡述值棧的原理和生命周期? 答:Value-Stack貫穿整個Action的生命周期,保存在request作用域中,所以它和request的生命周期一樣。當Struts2接受一個請求時,會創建ActionContext、Value-Stack和Action對象,然後把Action存放進Value-Stack,所以Action的實例變量可以通過OGNL訪問。由於Action是多實例的,和使用單例的Servlet不同,每個Action都有一個對應的Value-Stack,Value-Stack存放的數據類型是該Action的實例,以及該Action中的實例變量,Action對象默認保存在棧頂。 11.SessionFactory是線程安全的嗎?Session是線程安全的嗎?兩個線程能共享一個Session嗎? 答:(1)SessionFactory對應Hibernate的一個數據存儲的概念,它是線程安全的,可以被多個線程並發訪問。SessionFactory一般只會在啟動的時候構建。對於應用程序,最好將SessionFactory通過單例的模式進行封裝以便於訪問。 (2)Session是一個輕量級非線程安全的對象(線程間不能共享Session),它表示與數據庫進行交互的一個工作單元。Session是由SessionFactory創建的,在任務完成之後會被關閉。Session是持久層服務對外提供的主要接口。Session會延遲獲取數據庫連接(也就是在需要的時候才會獲取)。為了避免創建太多的session,可以使用TreadLocal來獲取當前的session,無論你調用多少次getCurrentSession()方法,返回的都是同一個session。 12.Session的load和get方法區別是什麽? 答:①如果沒有找到符合條件的記錄,get方法返回null值,而load方法會拋出異常; ②get方法直接返回實體類對象,load方法返回實體類對象的代理; ③在Hibernate3之前,get方法只在一級緩存(內部緩存)中進行數據查找,如果沒有找到對應的數據則越過二級緩存,直接發出SQL語句完成數據的讀取;load方法則可以充分利用二級緩存中現有數據,進行延遲加載。當然從Hibernate3開始,get方法不再是對二級緩存只寫不讀,它也是可以訪問二級緩存的; 簡單的是,對於load()方法,hibernate認為該數據在數據庫中一定存在,可以放心的使用代理來實現延遲加載,如果沒有數據,就會拋出異常,而通過get()方法去取數據,是可以不存在的。 13.闡述Session加載實體對象的過程? 答:①Session在調用數據查詢功能之前,首先會在緩存中進行查詢,在一級緩存中,通過實體類型和主鍵進行查詢,如果一級緩存查找命中且數據狀態合法,則直接返回; ②如果一級緩存沒有命中,接下來Session會在當前NonExists記錄(相當於一個查詢黑名單,如果出現重復的無效查詢可以迅速判斷,從而提升性能)中進行查詢,如果NonExists中存在同樣的查詢條件,則返回null; ③對於load方法,如果一級緩存查詢失敗,則查詢二級緩存,如果二級緩存命中則直接返回; ④如果之前的查詢都未命中,則發出sql語句,如果查詢未發現對應的記錄,則此次查詢添加到Session的NonExists中加以記錄,並返回null; ⑤根據映射配置和sql語句,得到ResultSet,並創建對應的實體對象; ⑥將對象納入Session(一級緩存)管理; ⑦執行攔截器的onload方法(如果有對應的攔截器); ⑧將數據對象納入二級緩存; ⑨返回數據對象。 14.Query接口的list方法和iterate方法有什麽區別? 答:①list()方法返回的每個對象都是完整的(對象中的每個屬性都被表中的字段填充上了),list方法無法利用緩存,它對一級緩存只寫不讀; ②iterate方法可以充分利用一級緩存,它所返回的對象中僅包含了主鍵值(標識符),只有當你對iterator中的對象進行操作時,Hibernate才會向數據庫再次發送SQL語句來獲取該對象的屬性值; ②list方法不會引起N+1查詢問題,而iterate方法會引起N+1查詢問題。 15.Hibernate如何實現分頁查詢? 答:通過Hibernate實現分頁查詢,開發人員只需要提供HQL語句、查詢起始行數(setFirstResult()方法)和最大查詢行數(setMaxResult()方法),並調用Query接口的list()方法,Hibernate會自動生成分頁查詢的SQL語句。

【JAVA秒會技術之秒殺面試官】JavaEE常見面試題(一)