81、JDBC中如何進行事務處理?
答:Connection提供了事務處理的方法,通過調用setAutoCommit(false)可以設置手動提交事務;當事務完成後用commit()顯式提交事務;如果在事務處理過程中發生異常則通過rollback()進行事務回滾。除此之外,從JDBC 3.0中還引入了Savepoint(保存點)的概念,允許通過代碼設置保存點並讓事務回滾到指定的保存點。
82、JDBC能否處理Blob和Clob?
答: Blob是指二進制大對象(Binary Large Object),而Clob是指大字符對象(Character Large Objec),因此其中Blob是為存儲大的二進制數據而設計的,而Clob是為存儲大的文本數據而設計的。JDBC的PreparedStatement和ResultSet都提供了相應的方法來支持Blob和Clob操作。
83、簡述正則表達式及其用途。
答:在編寫處理字符串的程序時,經常會有查找符合某些復雜規則的字符串的需要。正則表達式就是用於描述這些規則的工具。換句話說,正則表達式就是記錄文本規則的代碼。
說明:計算機誕生初期處理的信息幾乎都是數值,但是時過境遷,今天我們使用計算機處理的信息更多的時候不是數值而是字符串,正則表達式就是在進行字符串匹配和處理的時候最為強大的工具,絕大多數語言都提供了對正則表達式的支持。
84、Java中是如何支持正則表達式操作的?
答:Java中的String類提供了支持正則表達式操作的方法,包括:matches()、replaceAll()、replaceFirst()、split()。此外,Java中可以用Pattern類表示正則表達式對象,它提供了豐富的API進行各種正則表達式操作。
面試題: - 如果要從字符串中截取第一個英文左括號之前的字符串,例如:北京市(朝陽區)(西城區)(海澱區),截取結果為:北京市,那麼正則表達式怎麼寫?
import java.util.regex.Matcher;
import java.util.regex.Pattern;
class RegExpTest {
public static void main(String[] args) {
String str = "北京市(朝陽區)(西城區)(海澱區)";
Pattern p = Pattern.compile(".*?(?=\\()");
Matcher m = p.matcher(str);
if(m.find()) {
System.out.println(m.group());
}
}
}
85、獲得一個類的類對象有哪些方式?
答:
方法1:類型.class,例如:String.class
方法2:對象.getClass(),例如:”hello”.getClass()
方法3:Class.forName(),例如:Class.forName(“java.lang.String”)。
86、如何通過反射創建對象?
答:
方法1:通過類對象調用newInstance()方法,例如:String.class.newInstance()
方法2:通過類對象的getConstructor()或getDeclaredConstructor()方法獲得構造器(Constructor)對象並調用其newInstance()方法創建對象,例如:String.class.getConstructor(String.class).newInstance(“Hello”);
87、如何通過反射獲取和設置對象私有字段的值?
答:可以通過類對象的getDeclaredField()方法字段(Field)對象,然後再通過字段對象的setAccessible(true)將其設置為可以訪問,接下來就可以通過get/set方法來獲取/設置字段的值了。
89、簡述一下面向對象的”六原則一法則”。
答:
單一職責原則:一個類只做它該做的事情。(單一職責原則想表達的就是”高內聚”,寫代碼最終極的原則只有六個字”高內聚、低耦合”。
開閉原則:軟件實體應當對擴展開放,對修改關閉。(在理想的狀態下,當我們需要為一個軟件系統增加新功能時,只需要從原來的系統派生出一些新類就可以,不需要修改原來的任何一行代碼。要做到開閉有兩個要點:①抽象是關鍵,一個系統中如果沒有抽象類或接口系統就沒有擴展點;②封裝可變性,將系統中的各種可變因素封裝到一個繼承結構中,如果多個可變因素混雜在一起,系統將變得復雜而換亂,如果不清楚如何封裝可變性,可以參考《設計模式精解》一書中對橋梁模式的講解的章節。)
依賴倒轉原則:面向接口編程。(該原則說得直白和具體一些就是聲明方法的參數類型、方法的返回類型、變量的引用類型時,盡可能使用抽象類型而不用具體類型,因為抽象類型可以被它的任何一個子類型所替代,請參考下面的裡氏替換原則。)
裡氏替換原則:任何時候都可以用子類型替換掉父類型。(關於裡氏替換原則的描述,Barbara Liskov女士的描述比這個要復雜得多,但簡單的說就是能用父類型的地方就一定能使用子類型。裡氏替換原則可以檢查繼承關系是否合理,如果一個繼承關系違背了裡氏替換原則,那麼這個繼承關系一定是錯誤的,需要對代碼進行重構。例如讓貓繼承狗,或者狗繼承貓,又或者讓正方形繼承長方形都是錯誤的繼承關系,因為你很容易找到違反裡氏替換原則的場景。需要注意的是:子類一定是增加父類的能力而不是減少父類的能力,因為子類比父類的能力更多,把能力多的對象當成能力少的對象來用當然沒有任何問題。)
接口隔離原則:接口要小而專,絕不能大而全。(臃腫的接口是對接口的污染,既然接口表示能力,那麼一個接口只應該描述一種能力,接口也應該是高度內聚的。例如,琴棋書畫就應該分別設計為四個接口,而不應設計成一個接口中的四個方法,因為如果設計成一個接口中的四個方法,那麼這個接口很難用,畢竟琴棋書畫四樣都精通的人還是少數,而如果設計成四個接口,會幾項就實現幾個接口,這樣的話每個接口被復用的可能性是很高的。Java中的接口代表能力、代表約定、代表角色,能否正確的使用接口一定是編程水平高低的重要標識。)
合成聚合復用原則:優先使用聚合或合成關系復用代碼。(通過繼承來復用代碼是面向對象程序設計中被濫用得最多的東西,因為所有的教科書都無一例外的對繼承進行了鼓吹從而誤導了初學者,類與類之間簡單的說有三種關系,Is-A關系、Has-A關系、Use-A關系,分別代表繼承、關聯和依賴。其中,關聯關系根據其關聯的強度又可以進一步劃分為關聯、聚合和合成,但說白了都是Has-A關系,合成聚合復用原則想表達的是優先考慮Has-A關系而不是Is-A關系復用代碼,原因嘛可以自己從百度上找到一萬個理由,需要說明的是,即使在Java的API中也有不少濫用繼承的例子,例如Properties類繼承了Hashtable類,Stack類繼承了Vector類,這些繼承明顯就是錯誤的,更好的做法是在Properties類中放置一個Hashtable類型的成員並且將其鍵和值都設置為字符串來存儲數據,而Stack類的設計也應該是在Stack類中放一個Vector對象來存儲數據。記住:任何時候都不要繼承工具類,工具是可以擁有並可以使用的,而不是拿來繼承的。)
迪米特法則:迪米特法則又叫最少知識原則,一個對象應當對其他對象有盡可能少的了解。(迪米特法則簡單的說就是如何做到”低耦合”,門面模式和調停者模式就是對迪米特法則的踐行。對於門面模式可以舉一個簡單的例子,你去一家公司洽談業務,你不需要了解這個公司內部是如何運作的,你甚至可以對這個公司一無所知,去的時候只需要找到公司入口處的前台美女,告訴她們你要做什麼,她們會找到合適的人跟你接洽,前台的美女就是公司這個系統的門面。再復雜的系統都可以為用戶提供一個簡單的門面,Java Web開發中作為前端控制器的Servlet或Filter不就是一個門面嗎,浏覽器對服務器的運作方式一無所知,但是通過前端控制器就能夠根據你的請求得到相應的服務。調停者模式也可以舉一個簡單的例子來說明,例如一台計算機,CPU、內存、硬盤、顯卡、聲卡各種設備需要相互配合才能很好的工作,但是如果這些東西都直接連接到一起,計算機的布線將異常復雜,在這種情況下,主板作為一個調停者的身份出現,它將各個設備連接在一起而不需要每個設備之間直接交換數據,這樣就減小了系統的耦合度和復雜度。
90、簡述一下你了解的設計模式。
答:所謂設計模式,就是一套被反復使用的代碼設計經驗的總結(情境中一個問題經過證實的一個解決方案)。使用設計模式是為了可重用代碼、讓代碼更容易被他人理解、保證代碼可靠性。設計模式使人們可以更加簡單方便的復用成功的設計和體系結構。將已證實的技術表述成設計模式也會使新系統開發者更加容易理解其設計思路。
在GoF的《Design Patterns: Elements of Reusable Object-Oriented Software》中給出了三類(創建型[對類的實例化過程的抽象化]、結構型[描述如何將類或對象結合在一起形成更大的結構]、行為型[對在不同的對象之間劃分責任和算法的抽象化])共23種設計模式,包括:Abstract Factory(抽象工廠模式),Builder(建造者模式),Factory Method(工廠方法模式),Prototype(原始模型模式),Singleton(單例模式);Facade(門面模式),Adapter(適配器模式),Bridge(橋梁模式),Composite(合成模式),Decorator(裝飾模式),Flyweight(享元模式),Proxy(代理模式);Command(命令模式),Interpreter(解釋器模式),Visitor(訪問者模式),Iterator(迭代子模式),Mediator(調停者模式),Memento(備忘錄模式),Observer(觀察者模式),State(狀態模式),Strategy(策略模式),Template Method(模板方法模式), Chain Of Responsibility(責任鏈模式)。
面試被問到關於設計模式的知識時,可以揀最常用的作答,例如:
工廠模式:工廠類可以根據條件生成不同的子類實例,這些子類有一個公共的抽象父類並且實現了相同的方法,但是這些方法針對不同的數據進行了不同的操作(多態方法)。當得到子類的實例後,開發人員可以調用基類中的方法而不必考慮到底返回的是哪一個子類的實例。
代理模式:給一個對象提供一個代理對象,並由代理對象控制原對象的引用。實際開發中,按照使用目的的不同,代理可以分為:遠程代理、虛擬代理、保護代理、Cache代理、防火牆代理、同步化代理、智能引用代理。
適配器模式:把一個類的接口變換成客戶端所期待的另一種接口,從而使原本因接口不匹配而無法在一起使用的類能夠一起工作。
模板方法模式:提供一個抽象類,將部分邏輯以具體方法或構造器的形式實現,然後聲明一些抽象方法來迫使子類實現剩余的邏輯。不同的子類可以以不同的方式實現這些抽象方法(多態實現),從而實現不同的業務邏輯。
除此之外,還可以講講上面提到的門面模式、橋梁模式、單例模式、裝潢模式(Collections工具類和I/O系統中都使用裝潢模式)等,反正基本原則就是揀自己最熟悉的、用得最多的作答,以免言多必失。
92、什麼是UML?
答:UML是統一建模語言(Unified Modeling Language)的縮寫,它發表於1997年,綜合了當時已經存在的面向對象的建模語言、方法和過程,是一個支持模型化和軟件系統開發的圖形化語言,為軟件開發的所有階段提供模型化和可視化支持。使用UML可以幫助溝通與交流,輔助應用設計和文檔的生成,還能夠闡釋系統的結構和行為。
93、UML中有哪些常用的圖?
答:UML定義了多種圖形化的符號來描述軟件系統部分或全部的靜態結構和動態結構,包括:用例圖(use case diagram)、類圖(class diagram)、時序圖(sequence diagram)、協作圖(collaboration diagram)、狀態圖(statechart diagram)、活動圖(activity diagram)、構件圖(component diagram)、部署圖(deployment diagram)等。在這些圖形化符號中,有三種圖最為重要,分別是:用例圖(用來捕獲需求,描述系統的功能,通過該圖可以迅速的了解系統的功能模塊及其關系)、類圖(描述類以及類與類之間的關系,通過該圖可以快速了解系統)、時序圖(描述執行特定任務時對象之間的交互關系以及執行順序,通過該圖可以了解對象能接收的消息也就是說對象能夠向外界提供的服務)。
94、什麼是ORM?
答:對象關系映射(Object-Relational Mapping,簡稱ORM)是一種為了解決程序的面向對象模型與數據庫的關系模型互不匹配問題的技術;簡單的說,ORM 是通過使用描述對象和數據庫之間映射的元數據(可以用XML或者是注解),將Java程序中的對象自動持久化到關系數據庫中或者將關系數據庫表中的行轉換成Java對象,其本質上就是將數據從一種形式轉換到另外一種形式。
95、說一下你對約定優於配置(CoC)的理解。
答:約定優於配置(convention over configuration),也稱作按約定編程,是一種軟件設計范式,旨在減少軟件開發人員需做決定的數量,獲得簡單的好處而又不失靈活性。CoC本質是說,開發人員僅需規定應用中不符約定的部分。例如,如果模型中有個名為Sale的類,那麼數據庫中對應的表就會默認命名為sales。只有在偏離這一約定時,例如將該表命名為products_sold,才需寫有關這個名字的配置。如果您所用工具的約定與你的期待相符,便可省去配置;反之,你可以配置來達到你所期待的方式。遵循約定雖然損失了一定的靈活性,不能隨意安排目錄結構,不能隨意進行函數命名,但是卻能減少配置。更重要的是,遵循約定可以幫助開發人員遵守構建標准,包括各種命名的規范,這對團隊開發是非常有利的。
96、說出Servlet的生命周期
答:Web容器加載Servlet並將其實例化後,Servlet生命周期開始,容器運行其init()方法進行Servlet的初始化;請求到達時調用Servlet的service方法,service方法會調用與請求對應的doGet或doPost等方法;當服務器關閉,項目被卸載時服務器會將Servlet實例銷毀,此時會調用Servlet的destroy方法。
Servlet接口定義了5個方法,其中前三個方法與Servlet生命周期相關:
1.void init(ServletConfig config) throws ServletException
2.void service(ServletRequest req, ServletResponse resp) throws - - ServletException, java.io.IOException
3.void destory()
4.java.lang.String getServletInfo()
5.ServletConfig getServletConfig()
97、轉發(forward)和重定向(redirect)的區別?
答:forward是容器中控制權的轉向,是服務器請求資源,服務器直接訪問目標地址的URL,把那個URL 的響應內容讀取過來,然後把這些內容再發給浏覽器,浏覽器根本不知道服務器發送的內容是從哪兒來的,所以它的地址欄中還是原來的地址。redirect就是服務器端根據邏輯,發送一個狀態碼(302),告訴浏覽器重新去請求那個地址,因此從浏覽器的地址欄中可以看到跳轉後的鏈接地址。前者更加高效,在前者可以滿足需要時,盡量使用轉發(通過RequestDispatcher對象的forward方法,RequestDispatcher對象可以通過ServletRequest對象的getRequestDispatcher方法獲得),並且,這樣也有助於隱藏實際的鏈接;在有些情況下,比如,需要跳轉到一個其它服務器上的資源,則必須使用重定向(通過HttpServletResponse對象調用其sendRedirect方法)。
98、JSP有哪些內置對象?作用分別是什麼?
答:JSP有9個內置對象:
- 1.request:封裝客戶端的請求,其中包含來自GET或POST請求的參數;
- 2.response:封裝服務器對客戶端的響應;
- 3.pageContext:通過該對象可以獲取其他對象;
- 4.session:封裝用戶會話的對象;
- 5.application:封裝服務器運行環境的對象;
- 6.out:輸出服務器響應的輸出流對象;
- 7.config:Web應用的配置對象;
- 8.page:JSP頁面本身(相當於Java程序中的this);
- 9.exception:封裝頁面拋出異常的對象。
【補充】如果用Servlet來生成網頁中的動態內容無疑是非常繁瑣的工作,另一方面,所有的文本和HTML標簽都是硬編碼,即使做出微小的修改,都需要進行重新編譯。JSP解決了Servlet的這些問題,它是Servlet很好的補充,可以專門用作呈現給用戶的視圖(View),而Servlet作為控制器(Controller)專門負責處理用戶請求並轉發或重定向到某個頁面。基於Java的Web開發很多都同時使用了Servlet和JSP。JSP頁面其實是一個Servlet,能夠運行Servlet的服務器(Servlet容器)通常也是JSP容器,可以提供JSP頁面的運行環境,Tomcat就是一個Servlet/JSP容器。第一次請求一個JSP頁面時,Servlet/JSP容器首先將JSP頁面轉換成一個JSP頁面的實現類,這是一個實現了JspPage接口或其子接口HttpJspPage的Java類。JspPage接口是Servlet的子接口,因此每個JSP頁面都是一個Servlet。轉換成功後,容器會編譯Servlet類,之後容器加載和實例化Java字節碼,並執行它通常對Servlet所做的生命周期操作。對同一個JSP頁面的後續請求,容器會查看這個JSP頁面是否被修改過,如果修改過就會重新轉換並重新編譯並執行。如果沒有則執行內存中已經存在的Servlet實例。
99、get和post請求的區別?
答:
①get請求用來從服務器上獲得資源,而post是用來向服務器提交數據;
②get將表單中數據按照name=value的形式,添加到action 所指向的URL 後面,並且兩者使用“?”連接,而各個變量之間使用“&”連接;post是將表單中的數據放在HTML頭部(header),傳遞到action所指向URL;
③get傳輸的數據要受到URL長度限制(1024字節);而post可以傳輸大量的數據,上傳文件只能使用post方式;
④使用get時參數會顯示在地址欄上,如果這些數據不是敏感數據,那麼可以使用get;對於敏感數據還是應用使用post;
⑤get使用MIME類型application/x-www-form-urlencoded的URL 編碼(URL encoding,也叫百分號編碼)文本的格式傳遞參數,保證被傳送的參數由遵循規范的文本組成,例如一個空格的編碼是”%20”。
100、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)。
101、JSP中的四種作用域?
答:page、request、session和application,具體如下:
①page 代表與一個頁面相關的對象和屬性。
②request 代表與Web客戶機發出的一個請求相關的對象和屬性。一個請求可能跨越多個頁面,涉及多個Web 組件;需要在頁面顯示的臨時數據可以置於此作用域
③session代表與某個用戶與服務器建立的一次會話相關的對象和屬性。跟某個用戶相關的數據應該放在用戶自己的session中
④application代表與整個Web應用程序相關的對象和屬性,它實質上是跨越整個Web應用程序,包括多個頁面、請求和會話的一個全局作用域。
102、實現會話跟蹤的技術有哪些?
答:由於HTTP協議本身是無狀態的,服務器為了區分不同的用戶,就需要對用戶會話進行跟蹤,簡單的說就是為用戶進行登記,為用戶分配唯一的ID,下一次用戶在請求中包含此ID,服務器據此判斷到底是哪一個用戶。
①URL 重寫:在URL中添加用戶會話的信息作為請求的參數,或者將唯一的會話ID添加到URL結尾以標識一個會話。
②設置表單隱藏域:將和會話跟蹤相關的字段添加到隱式表單域中,這些信息不會在浏覽器中顯示但是提交表單時會提交給服務器。
這兩種方式很難處理跨越多個頁面的信息傳遞,因為如果每次都要修改URL或在頁面中添加隱式表單域來存儲用戶會話相關信息,事情將變得非常麻煩。
③cookie:cookie有兩種,一種是基於窗口的,浏覽器窗口關閉後,cookie就沒有了;另一種是將信息存儲在一個臨時文件中,並設置存在的時間。當用戶通過浏覽器和服務器建立一次會話後,會話ID就會隨響應信息返回存儲在基於窗口的cookie中,那就意味著只要浏覽器沒有關閉,會話沒有超時,下一次請求時這個會話ID又會提交給服務器讓服務器識別用戶身份。會話中可以為用戶保存信息。會話對象是在服務器內存中的,而基於窗口的cookie是在客戶端內存中的。如果浏覽器禁用了cookie,那麼就需要通過下面兩種方式進行會話跟蹤。當然,在使用cookie時要注意幾點:首先不要在cookie中存放敏感信息;其次cookie存儲的數據量有限(4k),不能將過多的內容存儲cookie中;再者浏覽器通常只允許一個站點最多存放20個cookie。當然,和用戶會話相關的其他信息(除了會話ID)也可以存在cookie方便進行會話跟蹤。
④HttpSession:在所有會話跟蹤技術中,HttpSession對象是最強大也是功能最多的。當一個用戶第一次訪問某個網站時會自動創建HttpSession,每個用戶可以訪問他自己的HttpSession。可以通過HttpServletRequest對象的getSession方法獲得HttpSession,通過HttpSession的setAttribute方法可以將一個值放在HttpSession中,通過調用HttpSession對象的getAttribute方法,同時傳入屬性名就可以獲取保存在HttpSession中的對象。與上面三種方式不同的是,HttpSession放在服務器的內存中,因此不要將過大的對象放在裡面,即使目前的Servlet容器可以在內存將滿時將HttpSession中的對象移到其他存儲設備中,但是這樣勢必影響性能。添加到HttpSession中的值可以是任意Java對象,這個對象最好實現了Serializable接口,這樣Servlet容器在必要的時候可以將其序列化到文件中,否則在序列化時就會出現異常。
103、過濾器有哪些作用和用法?
答: Java Web開發中的過濾器(filter)是從Servlet 2.3規范開始增加的功能,並在Servlet 2.4規范中得到增強。對Web應用來說,過濾器是一個駐留在服務器端的Web組件,它可以截取客戶端和服務器之間的請求與響應信息,並對這些信息進行過濾。當Web容器接受到一個對資源的請求時,它將判斷是否有過濾器與這個資源相關聯。如果有,那麼容器將把請求交給過濾器進行處理。在過濾器中,你可以改變請求的內容,或者重新設置請求的報頭信息,然後再將請求發送給目標資源。當目標資源對請求作出響應時候,容器同樣會將響應先轉發給過濾器,再過濾器中,你可以對響應的內容進行轉換,然後再將響應發送到客戶端。
常見的過濾器用途主要包括:對用戶請求進行統一認證、對用戶的訪問請求進行記錄和審核、對用戶發送的數據進行過濾或替換、轉換圖象格式、對響應內容進行壓縮以減少傳輸量、對請求或響應進行加解密處理、觸發資源訪問事件、對XML的輸出應用XSLT等。
和過濾器相關的接口主要有:Filter、FilterConfig、FilterChain
104、監聽器有哪些作用和用法?
答:Java Web開發中的監聽器(listener)就是application、session、request三個對象創建、銷毀或者往其中添加修改刪除屬性時自動執行代碼的功能組件,如下所示:
①ServletContextListener:對Servlet上下文的創建和銷毀進行監聽。
②ServletContextAttributeListener:監聽Servlet上下文屬性的添加、刪除和替換。
③HttpSessionListener:對Session的創建和銷毀進行監聽。
補充:session的銷毀有兩種情況:1、session超時(可以在web.xml中通過/標簽配置超時時間);2、通過調用session對象的invalidate()方法使session失效。
④HttpSessionAttributeListener:對Session對象中屬性的添加、刪除和替換進行監聽。
⑤ServletRequestListener:對請求對象的初始化和銷毀進行監聽。
⑥ServletRequestAttributeListener:對請求對象屬性的添加、刪除和替換進行監聽。
105、web.xml 的作用?
答:用於配置Web應用的相關信息,如:監聽器(listener)、過濾器(filter)、 Servlet、相關參數、會話超時時間、安全驗證方式、錯誤頁面等。例如:
106、你的項目中使用過哪些JSTL標簽?
答:項目中主要使用了JSTL的核心標簽庫,包括、、、、等,主要用於構造循環和分支結構以控制顯示邏輯。
【說明】雖然JSTL標簽庫提供了core、sql、fmt、xml等標簽庫,但是實際開發中建議只使用核心標簽庫(core),而且最好只使用分支和循環標簽並輔以表達式語言(EL),這樣才能真正做到數據顯示和業務邏輯的分離,這才是最佳實踐。
107、使用標簽庫有什麼好處?如何自定義JSP標簽?
答:使用標簽庫的好處包括以下幾個方面:
1.分離JSP頁面的內容和邏輯,簡化了Web開發;
2.開發者可以創建自定義標簽來封裝業務邏輯和顯示邏輯;
3.標簽具有很好的可移植性、可維護性和可重用性;
4.避免了對Scriptlet(小腳本)的使用(很多公司的項目開發都不允許在JSP中書寫小腳本)
自定義JSP標簽包括以下幾個步驟:
1.編寫一個Java類實現實現Tag/BodyTag/IterationTag接口(通常不直接實現- 這些接口而是繼承TagSupport/BodyTagSupport/SimpleTagSupport類,這是對適配器模式中缺省適配模式的應用)
2.重寫doStartTag()、doEndTag()等方法,定義標簽要完成的功能
3.編寫擴展名為tld的標簽描述文件對自定義標簽進行部署,tld文件通常放在WEB-INF文件夾或其子目錄
4.在JSP頁面中使用taglib指令引用該標簽庫。
108、表達式語言(EL)的隱式對象及其作用?
答:pageContext、initParam(訪問上下文參數)、param(訪問請求參數)、paramValues、header(訪問請求頭)、headerValues、cookie(訪問cookie)、applicationScope(訪問application作用域)、sessionScope(訪問session作用域)、requestScope(訪問request作用域)、pageScope(訪問page作用域)。用法如下所示:
${pageContext.request.method} ${pageContext[][]} ${pageContext.request["method"]} ${pageContext["request"].method} ${initParam.defaultEncoding} ${header["accept-language"]} ${headerValues[][]} ${cookie.jsessionid.value} ${sessionScope.loginUser.username}
【補充】表達式語言的.和[]運算作用是一致的,唯一的差別在於如果訪問的屬性名不符合Java標識符命名規則,例如上面的accept-language就不是一個有效的Java標識符,那麼這時候就只能用[]運算符而不能使用.獲取它的值。
109、表達式語言(EL)支持哪些運算符?
答:除了.和[]運算符,EL還提供了:
算術運算符:+、-、*、/或div、%或mod
關系運算符:==或eq、!=或ne、>或gt、>=或ge、<或lt、<=或le
邏輯運算符:&&或and、||或or、!或not
條件運算符:${statement? A : B}(跟Java的條件運算符類似)
empty運算符:檢查一個值是否為null或者空(數組長度為0或集合中沒有元素也返回true)
110、請對以下Java EE中的名詞進行解釋
答:
1.容器:容器為Java EE應用程序組件提供了運行時支持。容器提供了一份從底層Java EE API到應用程序組件的聯合視圖。Java EE應用程序組件不能直接地與其它Java EE應用程序組件交互。它們通過容器的協議和方法來達成它們之間以及它們與平台服務之間的交互。在應用程序組件和Java EE服務之間插入一個容器,這允許該容器透明地為組件注入必須的服務,例如聲明式事務管理,安全檢查,資源池和狀態管理。
URL:http://www.bianceng.cn/Programming/Java/201608/50404.htm
2.資源適配器:資源適配器是一個系統級的組件,它通常實現了對外部資源管理器的網絡連接。資源適配器能夠擴展Java EE平台的功能。這只需要實現一個Java EE標准服務API(例如JDBC驅動程序),或者定義並實現一個能連接到外部應用程序系統的資源適配器就可以達到。資源適配器也可以提供完整的本地或本地資源的服務。資源適配器接口通過Java EE服務供應商接口(Java EE SPI)來連接Java EE平台。使用Java EE SPI連接到Java EE平台的資源適配器可以和所有的Java EE產品協同工作。
3.JNDI(Java Naming & Directory Interface):Java命名目錄接口,主要提供的功能是:提供一個目錄系統,讓其它各地的應用程序在其上面留下自己的索引,從而滿足快速查找和定位分布式應用程序的功能。
4.JMS(Java Message Service):Java消息服務是用於消息發送的標准API,它支持可靠的“點對點”消息發送和“發布-訂閱”模型。Java EE規范要求JMS供應商同時實現“點對點”消息發送和”發布/訂閱”型消息發送。
5.JTA(Java Transaction API):Java 事務編程接口。Java事務API由兩部分組成:①一個應用程序級的邊界劃分接口,容器和應用程序組件用它來劃分事務邊界;②一個介於事務管理器和資源管理器之間的Java EE SPI級接口。
6.JPA(Java Persistence API):Java持久化API是用於持久化和對象/關系映射管理的標准API。通過使用一個Java域模型來管理關系型數據庫,Java EE規范為應用程序開發者提供了一種對象/關系映射功能。Java EE必須對Java持久化API提供支持。它也可以用在Java SE環境中。
7.JAF(JavaBean Activation FrameWork):JAF API提供了一個框架來處理不同MIME類型的數據,它們源於不同的格式和位置。JavaMail API使用了JAF API。JAF API包含在Java SE中,因此它可以被Java EE應用程序使用。
8.JAAS(Java Authentication and Authorization Service):使服務能夠基於用戶進行驗證和實施訪問控制。它實現了一個Java版的標准的的Plugable Authentication Module (PAM)框架,並支持基於用戶的授權。Java Authorization Service Provider Contract for Containers (JACC) 定義了Java EE應用程序服務器和授權服務提供方之間的協議,允許將自定義的授權服務提供方插入任何Java EE產品中。
9.JMX(Java Management Extension):Java平台企業版管理規范中定義了一種API,通過一種特殊的管理型EJB來管理Java EE服務器。JMX API也提供了一些管理上的支持。
111、你是如何理解控制反轉(IoC)和依賴注入(DI)的?
答:控制反轉 (Inversion of Control, IoC)是把傳統上由程序代碼直接操控的對象的調用權交給容器,通過容器來實現對象組件的裝配和管理。所謂的“控制反轉”就是對組件對象控制權的轉移,從程序代碼本身轉移到了外部容器,由容器來創建對象並管理對象之間的依賴關系。IoC體現了好萊塢原則:“Don’t call me, we will call you”。依賴注入(Dependency Injection,DI)的基本原則是:應用組件不應該負責查找資源或者其他依賴的協作對象。配置對象的工作應該由容器負責,查找資源的邏輯應該從應用組件的代碼中抽取出來,交給容器來完成。DI是對IoC更准確的描述,即組件之間的依賴關系由容器在運行期決定,形象的來說,即由容器動態的將某種依賴關系注入到組件之中。
舉個例子:一個類A需要用到接口B中的方法,那麼就需要為類A和接口B建立關聯或依賴關系,最原始的方法是在類A中創建一個接口B的實現類C的實例,但這種方法需要開發人員自行維護二者的依賴關系,也就是說當依賴關系發生變動的時候需要修改代碼並重新構建整個系統。如果通過一個容器來管理這些對象以及對象的依賴關系,則只需要在類A中定義好用於關聯接口B的方法(構造器或setter方法),將類A和接口B的實現類C放入容器中,通過對容器的配置來實現二者的關聯。
112、請說出Spring 中依賴注入和AOP的實現機制。
答:
實現依賴注入的方式包括:構造器注入、設值注入和接口(回調)注入。Spring中可以通過設值注入(setter方法注入)和構造器注入實現IoC,推薦使用的方式為設值注入。
實現AOP的方式包括:編譯時AOP(需要特殊的編譯器)、運行時AOP(代理模式)、加載時AOP(需要特殊的類加載器)。Spring中使用了運行時的AOP,主要通過代理的方式對原來的代碼進行增強實現。對於實現了接口的類,Spring通過Java的動態代理(請參考Proxy類和InvocationHandler接口)來進行增強;對於沒有實現接口的類,Spring使用第三方字節碼生成工具CGLIB,通過繼承的方式對原有代碼進行增強。
113、你的項目選擇使用Spring框架的原因是什麼?
答:
1.Spring提供了企業級開發的一站式選擇,有大量的功能模塊可供選擇,並且可以根據項目的需要自由取捨。Spring通過POJO簡化了JavaEE開發,低侵入式的編程提供了代碼的持續集成能力和易測試性。
2.Spring框架的核心功能是依賴注入(DI)。DI使得代碼的單元測試更加方便、系統更好維護、代碼也更加靈活。DI代碼自身很容易測試,通過構建實現了應用所需的接口的“模擬”對象就可以進行功能的黑盒測試。DI代碼也更容易復用,因為其“被依賴的”功能封裝在在定義良好的接口中,允許其他對象根據需要將其插入到所需的對象中,這些對象是在其他應用平台中進行配置的。DI使代碼更加靈活,由於其天生的松耦合性,它允許程序員僅需考慮自己所需的接口和其他模塊暴露出來的接口來就可以決定對象之間如何關聯。
3.Spring支持面向切面編程(AOP),允許通過分離應用業務邏輯和系統服務從而進行內聚性的開發。AOP通常用來支持日志、審計、性能和內存監控等功能。
4.Spring還提供了許多實現基本功能的模板類,使得Java EE應用的開發更加容易。例如,JdbcTemplate類和JDBC、JpaTemplate類和JPA,JmsTemplate類和JMS都可以很好地結合起來使用。RestTemplate類非常簡潔,使用這個模板的代碼的可讀性和可維護性也都很好。
5.Spring提供了聲明性事務處理,工作調度,身份認證,成熟的Web MVC框架以及和其他框架的集成,例如Hibernate、MyBatis、JasperReports、JSF、Struts、Tapestry、Seam和Quartz等等。
6.Spring Bean對象可以通過Terracotta在不同的JVM之間共享。這就允許使用已有的Bean並在集群中共享 ,將Spring應用上下文事件變為分布式事件,還可以通過Spring JMX導出集群Bean,使得Spring應用高可用、集群化。
7.Spring傾向於使用非受檢異常(運行時異常)和減少不當try、catch和finally代碼塊,例如JpaTemplate這樣的Spring模板類會負責關閉或釋放數據庫連接,這避免了潛在的外部資源洩露問題並提高了代碼的可讀性。