面試題總結-最新

瓜瓜東西發表於2014-08-04

1 tomcat 載入順序

當我們啟動一個tomcat的服務的時候,jar包和claess檔案是是以怎麼樣的順序被載入進來的?

 

載入順序:

1. $java_home/lib目錄下的java核心api 

2. $java_home/lib/ext目錄下的java擴充套件jar

3. java-classpath/-Djava.class.path所指的目錄下的類與jar

4. $CATALINA_HOME/common目錄下按照資料夾的順序從上往下依次載入

5. $CATALINA_HOME/server目錄下按照資料夾的順序從上往下依次載入

6. $CATALINA_BASE/shared目錄下按照資料夾的順序從上往下依次載入

7. 我們的專案路徑/WEB-INF/classes下的class檔案

8. 我們的專案路徑/WEB-INF/lib下的jar檔案

 

在同一個資料夾下,jar包是按順序從上到下依次載入

 

      ClassLoader雙親委託模式載入機制我們可以知道,假設兩個包名和類名完全相同的class檔案不再同一個jar包,如果一個class檔案已經被載入java虛擬機器裡了,那麼後面的相同的class檔案就不會被載入了。

2 tomcat 版本7和6的區別

今天開始在單位推廣 Tomcat7 ,竟然碰到了好多問題。到現在才剛剛解決的差不多。在此介紹一下。

Tomcat6下邊程式執行極其正常換了 Tomcat7 忽然不能用的都來看看了~

 

-------------------- ---------- ---------- ----------

 

第一個問題是關於資料庫驅動程式載入。受資料庫驅動異常困擾的同胞們,Tomcat7 下邊因為 Tomcat 限定了類載入執行時靜態程式碼的執行,需要在生成物件的時候才能夠真正執行,所以在 Tomcat6 以前大家熟悉的資料庫驅動程式載入方式:

[html] view plaincopyprint?

1.  Class<?> cls = com.mysql.jdbc.Driver.class;  

或者

[html] view plaincopyprint?

1.  Class.forName("com.mysql.jdbc.Driver");  

都已經不能用了。在使用 DriverManager 生成的資料庫連線的時候,會出現“No suitable driverfound for jdbc”這個異常。

 

現在正確的資料庫驅動程式載入方式,要求生成資料庫驅動類的物件。推薦

[html] view plaincopyprint?

1.  com.mysql.jdbc.Driver.class.newInstance();  

這種方式不用處理異常,而且生成的無用物件會最短時間被垃圾回收。

當然了,也可以用一個引用型別變數把此物件接出來,但沒有什麼實際用途吧……

[html] view plaincopyprint?

1.  java.sql.Driver driver = com.mysql.jdbc.Driver.class.newInstance();  

其中 java.sql.Driver 是各個資料庫管理系統提供的驅動程式類的介面,屬於 JDBC 規範,適合用 import java.sql.Driver; 進行縮寫。

 

-------------------- ---------- ---------- ----------

 

第二個問題,是執行緒啟動的問題。因為 Tomcat7 或者 -server 方式執行的爪哇虛擬機器(JVM)的一些我尚未掌握的保護機制,所以當一個執行緒經歷空迴圈時,就會被架空。

[html] view plaincopyprint?

1.  while(flag) { }  

於是通過 flag 作為執行緒控制變數的控制方法,就沒辦法繼續使用了。這個時候,要時常跳過這個人工卡死的執行緒,以便其能夠總在執行而不會真的陷入僵死。

[html] view plaincopyprint?

1.  while(flag) { Thread.yield(); }  

 

-------------------- ---------- ---------- ----------

 

Tomcat7 的配置檔案中,Context 配置,debug 屬性被取消了,如果依然使用,會報出一個警告。

同時 unpackWAR 屬性的預設值,在 Tomcat6 時是 true ,意味著預設狀態將會解壓 .war 然後再執行;而 Tomcat7 變成了預設 false ,不展開。

 

-------------------- ---------- ---------- ----------

 

另外還有一個並不是 Tomcat7 新有的特點。之前conf/Catalina/localhost 下邊會自動建立 ROOT.xml ,現在不會了。然後之前此目錄下的配置檔案,會以其中 path 屬性指明的路徑為應用路徑;現在則會以 XML 檔案的名字作為應用路徑。如果大家想製作一個不需要填寫應用路徑就可以訪問的應用,請記得一定要自己建立一個 ROOT.xml ,區分大小寫,然後在其中編寫 <Context> 片段。

[html] view plaincopyprint?

1.  <Context  

2.          crossContext="true"  

3.          privileged="true"  

4.          path=""  

5.          docBase="/usr/local/example.war"  

6.          reloadable="false"  

7.          unpackWAR="true"  

8.          cachingAllowed="true"  

9.          cacheMaxSize="1024"  

10.     ></Context>  

這個例子比較全。其中

crossContext="true" ,是允許應用通過 ServletContext.getContext() 去拿到一個通往別的應用 request dispatcher 。當然了,這種方法無法跨越現在 Tomcat 支援的虛擬主機界限。也就是說,能夠穿透訪問的,必須是和當前應用在一個 <Host> 之中的應用。

privileged="true" 意味著 Tomcat 自身的應用,比如· Tomcat Manager,可以被當前這個應用訪問。根據官方文件的解釋,這個機理是改變應用的類載入器為 Server classloader 。我想,這種改變,會令應用程式發現 Tomcat 本身的類,都能夠從應用自己的類載入器上尋找到。從而實現對 Tomcat 自身應用程式方法的呼叫。

path docBase 不用多說,都要指定這二個屬性的。其中 docBase 可以是目錄也可以是結構完整的 .war 檔案。

reloadable="true" 意味著 Tomcat 將提供對應用類路徑(/WEB-INF/classes/ /WEB-INF/lib/ )的監測。當這裡邊有內容改變並且其類已經被爪哇虛擬機器(JVM)載入的時候,Tomcat 可以自行重新載入此類。不過此功能對 Tomcat 的穩定服務影響不小,除錯環境可以使用,生產環境還是算了吧——當然,這只是我的個人建議。

unpackWAR 就如字面意思,unpackWAR="true" 意味著 Tomcat 會儲存 .war 包的解壓結果,然後直接對解壓結果進行執行。我個人認為,考慮到爪哇虛擬機器的類載入機制,每個類都僅載入一回,但是頁面內容卻沒有類似的有效快取,所以 .war 還是解壓執行的比較好。而且日誌也將造成 unpackWAR="false" 形同災難。

cachingAllowed="true" 意味著開啟了 Tomcat7 的靜態快取功能。靜態檔案包括 JavaScript 程式、圖片聲音等允許網路訪問的檔案以及 HTML 頁面。

cacheMaxSize 是靜態快取功能緩衝區大小的設定。單位是 MB ,也就是 1024KB 。例子中設為 1024 ,意味著 1GB

 

3 jdk7/6區別

首先是模組化特性:現在的 Java7也是採用了模組的劃分方式來提速,一些不是必須的模組並沒有下載和安裝,因此在使用全新的Java7的虛擬機器的時候會發現真的很快,當虛擬機器需要用到某些功能的時候,再下載和啟用相應的模組,這樣使得最初需要下載的虛擬機器大小得到了有效的控制。同時對啟動速度也有了很大的改善。如果你對 OpenJDK的架構比較熟悉,你甚至可以定製JDK的模組。

其次是多語言支援:這裡的多語言不是指中文英文之類的語言,而是說Java7的虛擬機器對多種動態程式語言增加了支援,比如:Rubby Python等等。對這些動態語言的支援極大地擴充套件了Java虛擬機器的能力。對於那些熟悉這些動態語言的程式設計師而言,在使用Java虛擬機器的過程中同樣可以使用它們熟悉的語言進行功能的編寫,而這些語言是跑在功能強大的JVM之上的。

再有是開發者的開發效率得到了改善:Java7通過多種特性來增強開發效率。比如對語言本身做了一些細小的改變來簡化程式的編寫,在多執行緒併發與控制方面:輕量級的分離與合併框架,一個支援併發訪問的HashMap等等。通過註解增強程式的靜態檢查。提供了一些新的API用於檔案系統的訪問、非同步的輸入輸出操作、Socket通道的配置與繫結、多點資料包的傳送等等。

最後是執行效率的提高,也是給人感覺最真切體驗的特性:壓縮了64位的物件指標,Java7通過對物件指標由 64位壓縮到與32位指標相匹配的技術使得記憶體和記憶體帶塊的消耗得到了很大的降低因而提高了執行效率。此外還提供了新的垃圾回收機制(G1)來降低垃圾回收的負載和增強垃圾回收的效果。G1垃圾回收機制擁有更低的暫停率和更好的可預測性。

 

4 hibernate 事務

 

5 jquery選擇器

jQuery 元素選擇器
jQuery
使用 CSS 選擇器來選取 HTML 元素。

$("p")
選取 <p> 元素。

$("p.intro")
選取所有 class="intro" <p> 元素。

$("p#demo")
選取 id="demo" 的第一個 <p> 元素。
jQuery
屬性選擇器
jQuery
使用 XPath 表示式來選擇帶有給定屬性的元素。

$("[href]")
選取所有帶有 href 屬性的元素。

$("[href='#']")
選取所有帶有 href 值等於 "#" 的元素。

$("[href!='#']")
選取所有帶有 href 值不等於 "#" 的元素。

$("[href$='.jpg']")
選取所有 href 值以 ".jpg" 結尾的元素。
jQuery CSS
選擇器
jQuery CSS
選擇器可用於改變 HTML 元素的 CSS 屬性。

$("p").css("background-color","red");

 

6 jquery/extjs的核心

jQuery是為了改變javascript的編碼方式而設計的

7 hibernate方言

Hibernate底層依然使用SQL語句來執行資料庫操作,雖然所有關係型資料庫都支援使用標準SQL語句,但所有資料庫都對標準SQL進行了一些擴充套件,所以在語法細節上存在一些差異,因此Hibernate需要根據資料庫來識別這些差異。

舉例來說,我們在MySQL資料庫裡進行分頁查詢,只需使用limit關鍵字就可以了;而標準SQL並不支援limit關鍵字,例如Oracle則需要使用行內檢視的方式來進行分頁。同樣的應用程式,當我們在不同資料庫之間遷移時,底層資料庫的訪問細節會發生改變,而Hibernate也為這種改變做好了準備,現在我們需要做的是:告訴Hibernate應用程式的底層即將使用哪種資料庫——這就是資料庫方言。

一旦我們為Hibernate設定了合適的資料庫方言,Hibernate將可以自動應付底層資料庫訪問所存在的細節差異。

不同資料庫所應使用的方言如表5.1所示。

表 不同資料庫及其對應方言

關聯式資料庫

方 言

DB2

org.hibernate.dialect.DB2Dialect

DB2 AS/400

org.hibernate.dialect.DB2400Dialect

DB2 OS390

org.hibernate.dialect.DB2390Dialect

PostgreSQL

org.hibernate.dialect.PostgreSQLDialect

MySQL

org.hibernate.dialect.MySQLDialect

MySQL with InnoDB

org.hibernate.dialect.MySQLInnoDBDialect

MySQL with MyISAM

org.hibernate.dialect.MySQLMyISAMDialect

Oracle(any version

org.hibernate.dialect.OracleDialect

Oracle 9i

org.hibernate.dialect.Oracle9iDialect

Oracle 10g

org.hibernate.dialect.Oracle10gDialect

 

Sybase

org.hibernate.dialect.SybaseDialect

Sybase Anywhere

org.hibernate.dialect.SybaseAnywhereDialect

Microsoft SQL Server

org.hibernate.dialect.SQLServerDialect

SAP DB

org.hibernate.dialect.SAPDBDialect

Informix

org.hibernate.dialect.InformixDialect

HypersonicSQL

org.hibernate.dialect.HSQLDialect

Ingres

org.hibernate.dialect.IngresDialect

Progress

org.hibernate.dialect.ProgressDialect

Mckoi SQL

org.hibernate.dialect.MckoiDialect

Interbase

org.hibernate.dialect.InterbaseDialect

Pointbase

org.hibernate.dialect.PointbaseDialect

FrontBase

org.hibernate.dialect.FrontbaseDialect

Firebird

org.hibernate.dialect.FirebirdDialect

如果一個系統可能執行於多種資料庫,或者同時使用多種資料庫,那麼,使用Hibernate將會給你帶來很多的方便,想信很多接觸Hibernate的人都會體會到。Hibernate底層是通過dialect包來對各種資料庫的差異進行抽象的。Dialect類中實現每種資料庫相同的東西,而不同資料庫對應會有該類的一個擴充套件實現,最終通過DialectFactory來決定建立哪一個類。通常我們都會指定hibernate.dialect屬性,那直接建立該屬性對應的類。如果我們沒有指定該屬性,那麼由Hibernate自己決定選擇合適的方言。在DialectFactory中初始化各種資料庫對應的方言的Map,以資料庫產品名為key,以方言的包裝物件為value。Hibernate自動選擇方言時,會通過JDBC的DatabaseMetadata取得資料庫的產品名稱,根據名稱取得對應的方言。DialectFactory中對該Map的初始化的部分程式碼如下:

  1. // TODO : this is the stuff it'd be nice to move to a properties file or some other easily user-editable place
  2. private static final Map MAPPERS = new HashMap();
  3. static {
  4. // detectors...
  5. MAPPERS.put( "HSQL Database Engine", new VersionInsensitiveMapper( "org.hibernate.dialect.HSQLDialect" ) );
  6. MAPPERS.put( "H2", new VersionInsensitiveMapper( "org.hibernate.dialect.H2Dialect" ) );
  7. MAPPERS.put( "MySQL", new VersionInsensitiveMapper( "org.hibernate.dialect.MySQLDialect" ) );
  8. MAPPERS.put( "PostgreSQL", new VersionInsensitiveMapper( "org.hibernate.dialect.PostgreSQLDialect" ) );
  9. MAPPERS.put( "Apache Derby", new VersionInsensitiveMapper( "org.hibernate.dialect.DerbyDialect" ) );
  10. <SPAN>...</SPAN> 原本上,這種自動選擇的方式,會給我們帶來方便,只可惜,從以上的程式碼的註釋中可以知道,目前這一部分的初始化是通過硬編碼的,只有在以後的版本才會移動到配置檔案或其他容易使用者編譯的地方,否則,我們可以非常容易的新增我們的配置供Hibernate進行自動選擇。而經常我們所使用的資料庫驅動程式所取到的資料庫產品名稱會跟以上硬編碼的不同,所以最終我們還是得自己配置資料庫方言。

由於我們的系統中用到了好幾個資料來源,經常也是對應不同型別的資料庫,並且資料來源都是由容器提供的,在首次部署時經常因為資料庫型別變了而忘了修改對應的資料庫方言,而出了問題,這給實施人員帶來了很多的不便。不過目前除了對各種資料庫提供與以上硬編碼相同的資料庫產品名稱的驅動程式外,我們就只能自己動手了

 

8 閉包例項

9 原型例項

 

10 tomcat目錄結構

首先來了解一下Tomcat5.5的目錄結構:

/bin:存放windows或Linux平臺上啟動和關閉Tomcat的指令碼檔案

/conf:存放Tomcat伺服器的各種全域性配置檔案,其中包括server.xml(Tomcat的主要配置檔案)、tomcat-users.xml和web.xml等配置檔案

/server/lib:存放Tomcat伺服器所需的各種JAR檔案(但是不能被web應用訪問)

/server/webapps:存放Tomcat自帶的兩個web應用admin應用和 manager應用

/common/lib:存放Tomcat伺服器以及所有web應用都可以訪問的jar檔案

/shared/lib:存放所有web應用都可以訪問的jar檔案(但是不能被Tomcat伺服器訪問)

/logs:存放Tomcat執行時的日誌檔案

/src:存放Tomcat的原始碼

/webapps:Tomcat的主要Web釋出目錄,預設情況下把Web應用檔案放於此目錄

/work:Tomcat將JSP生成的Servlet原始檔和位元組碼檔案放到這個目錄下

/temp:存放Tomcat執行時所產生的臨時檔案

 

而Tomcat6.0的目錄結構則比5.5簡化了很多 目錄如下:

/bin:存放windows或Linux平臺上啟動和關閉Tomcat的指令碼檔案

/conf:存放Tomcat伺服器的各種全域性配置檔案,其中包括server.xml(Tomcat的主要配置檔案)、tomcat-users.xml和web.xml等配置檔案

/lib:存放所需的所有jar檔案(整合了原來tomcat5.5中的common/share/server三個目錄下的所有jar)

/logs:存放Tomcat執行時的日誌檔案

/temp:存放Tomcat執行時所產生的臨時檔案

/webapps:Tomcat的主要Web釋出目錄,預設情況下把Web應用檔案放於此目錄(原/server/webapps下的manager等應用也已轉移至此)

/work:Tomcat將JSP生成的Servlet原始檔和位元組碼檔案放到這個目錄下

 

Tomcat6.x與5.x在目錄上最大的區別就是將所有的lib包直接置於 CATALINA_HOME/lib目錄下

 

11 開啟多個tomcat

11.1回答一:

前些時日,出於某種需要,需要同時啟動多個Tomcat伺服器,在網上查了半天,才找到解決的辦法,拿出來分享一下,嘿嘿。

我所用Tomcat伺服器都為zip版,非安裝版。以兩個為例:
安裝第二個Tomcat完成後,到安裝目錄下的conf子目錄中開啟server.xml檔案,查詢以下三處:

  (1) 修改http訪問埠(預設為8080埠)

         

<Connector   className="org.apache.coyote.tomcat4.CoyoteConnector"   port="8080"  
                               minProcessors
="5"   maxProcessors="75"   
                                enableLookups
="true"   redirectPort="8443"   
                                acceptCount
="100"   debug="0"   connectionTimeout="20000"   
                                useURIValidationHack
="false"   disableUploadTimeout="true"   /> 


(大概在86行左右)將8080修改為第一個tomcat不在使用的埠號。此處所設的埠號即是以後訪問web時所用的埠號。  


  (2) 修改Shutdown埠(預設為8005埠)

   

<Server port="8005" shutdown="SHUTDOWN" debug="0">


 
  (大概在13行左右)將8005修改為沒有在使用的埠號,例如8095   


  (3) 修改JVM啟動埠(預設為8009埠)

         

   < Connector    className ="org.apache.coyote.tomcat4.CoyoteConnector"   
                                port
 ="8009"    minProcessors ="5"    maxProcessors="75"    
                                enableLookups
 ="true"    redirectPort ="8443"    
                                acceptCount
 ="10"    debug ="0"    connectionTimeout="20000"   
                                useURIValidationHack
 ="false"    
                               protocolHandlerClassName
 ="org.apache.jk.server.JkCoyoteHandler" />


  (大概在107行左右)將8009修改為沒有在使用的埠號,例如8099   
   

這樣就沒問題了。

11.2 方案2

刪除環境變數中的CATALINA_HOME和CATALINA_BASE (關鍵)

比如我想同是啟動N個tomcat

複製N個tomcat原始檔包(當然如果在同一資料夾下需要手動重新命名一下)

分別修改安裝目錄下的conf子目錄中的server.xml檔案:

a.修改http訪問埠(預設為8080埠),將8080修改為tomcat唯一的,其他tomcat不在使用的埠號。此處所設的埠號即是以後訪問web時所用的埠號。

b.修改Shutdown埠(默 認為8005埠),將8005修改為唯一的的埠號,例如8055。

c.修改8009埠,將8009修改為沒有在使用的埠號,例如8099(注 意:N個檔案中對應的埠號要都不一樣)

 

依次啟動N個tomcat。 答:對就是改server.xml把共用的埠分開就行了

 

 

另外,

若用MyEclipse來啟動Tomcat的話,那麼配置Tomcat的版本必須不一樣才能同時配置上去,比如,同時配置四個Tomcat6是不可能的,但是Tomcat4,5,6,7是可以同時配置的!

 

相關文章