jboss之啟動加載過程詳解


今天看了看jboss的boot.log和server.log日志,結合自己的理解和其他的資料,現對jboss的啟動和加載過程做出如下總結;

boot.xml是服務器的啟動過程的日志,不涉及后續的操作過程

server.xml是操作過程的日志,比如部署文件,加載資源等等,是更加詳細的,其中包含了啟動的過程

本文以JBoss Application Server 4.2.1 GA(以下簡稱JBoss)為例,介紹它在Windows平台上的啟動過程。為了方便敘述,對平台環境做以下假定:Java運行時的安裝路徑為C:/Java,JBoss的安裝路徑為C:/JBoss。

既然用100% Java編寫的JBoss具有跨平台的特性,那為什么還要強調Windows平台呢?這是因為,JBoss的啟動是從平台相關的腳本文件開始的,而在不同 平台上的腳本文件是不同的。例如,Window平台上的腳本文件是run.bat,linux平台上的腳本是run.sh。兩個文件的內容有很大不同,功 能也許差不多,無非是配置啟動環境,但是也有可能存在平台相關的因素。我只看了run.bat,對run.sh並不了解,為謹慎起見,我只介紹 run.bat,對run.sh不作闡述。

在介紹JBoss啟動過程之前,我想先介紹一下JBoss的結構特征,這將有利於大家理解啟動過程。JBoss基於JMX框架,它的結構就是一個 MBeanSserver以及一些掛在MBeanServer上的MBean。MBean提供功能,MBeanServer是MBean之間的通信總線。 JMX框架的好處就是給JBoss帶來了高度的靈活性、可配置性。可配置性也是JBoss的核心理念之一,幾乎所有的JBoss部件都可以被替換。 JBoss通過系統屬性、配置文件等多種方法,幫助實現高度的可配置性。我們可以通過設置系統屬性,或者通過編輯配置文件,來定制自己的JBoss版本。這種可配置性體現在JBoss的各個角落,啟動過程只能窺一斑,若欲知全豹,可以研究一下JBoss的EJB容器等其它部件。

介紹完JBoss的結構特征,我們開始進入JBoss的啟動過程。整個過程可以分為六個階段,下面將依次介紹。

一、執行啟動腳本,配置啟動環境

JBoss的啟動過程從執行run.bat開始,run.bat的主要工作就是配置啟動環境。

JBoss的啟動環境其實是一些啟動參數,例如JBoss的安裝路徑、java命令的參數、JBoss的類路徑等。

如果在配置過程中發生錯誤,run.bat的執行將被中斷。

run.bat將配置以下啟動參數:

JBOSS_HOME

JBoss的安裝路徑,其值為C:/JBoss

PATH

將C:/JBoss/bin/native添加到PATH中,native下的文件是平台相關的,可以優化JBoss的性能。

JAVA

java.exe文件的路徑,其值為C:/Java/bin/java

JAVA_OPTSB

java命令的參數,其值為-Dprogram.name=run.bat –server-Xms128m –Xmx512m –Dsun.rmi.dgc.client.gcInterval=3600000 –Dsun.rmi.dgc.server.gcInterval=3600000

JBOSS_CLASSPATH

JBoss的啟動類路徑,其值為C:/Java/lib/tools.jar;C:/JBoss/bin/run.jar。JBoss的啟動前期需要的類文件都在這兩個jar中。

如果沒有設置系統環境變量JAVA_HOME,那么run.bat的執行將被中斷,JBoss啟動失敗。因此,在安裝好JBoss后,一定要設

置JAVA_HOME系統環境變量。

如果run.bat執行順利,那么在最后,將會執行以下命令:

C:/Java/bin/java -Dprogram.name=run.bat –server-Xms128m –Xmx512m –Dsun.rmi.dgc.

client.gcInterval=3600000 –Dsun.rmi.dgc.client.gcInterval=3600000 -Djava.endorsed.dirs=

C:/JBoss/lib/endorsed –classpath C:/Java/lib/tools.jar;C:/JBoss/bin/run.jar org.jboss.Main/%*

%*代表run.bat后面的啟動參數。

從這條命令開始,真正運行JBoss的代碼。

二、JBoss啟動的入口

JBoss的魔術從Main.main方法開始。Main這個類位於run.jar中。Main.main方法創建了一個名為”jboss”的線程 組,然后創建並運行該線程組的線程”main”。”main”線程開始運行后,Main.main方法執行完畢,主線程也隨之結束。”main”線程的主 要工作是調用Main.boot方法。

Main.boot方法的主要工作是處理命令行參數,然后創建並運行一個服務器實例。當服務器實例開始運行后,jboss的啟動過程也就成功結束了。下面的幾個階段都是boot方法的執行過程。

三、處理命令行參數

boot方法調用Main.processCommandLine方法,來處理命令行參數。這里的命令行參數其實就是main方法的args參數,它作為實參傳遞給processCommandLine方法。

processCommandLine方法使用了GNU-getopt程序包來解析命令行參數,對不同的命令行參數有不同的處理方式,簡單概括如下:

部分參數被簡單處理后,程序直接退出。

processCommandLine方法執行完畢后,boot方法將加載、創建並運行一個服務器實例。

四、加載並創建服務器實例

服務器實例是一個運行時對象,這個對象代表了運行着的JBoss應用服務器。啟動一個JBoss應用服務器,就會有一個服務器實例與

之對應。在JBoss中,服務器實例的實現是可以配置的,也就是說,服務器類不是固化的,而是可以替換的。這就帶來一個問題:

JBoss必須在啟動的過程中搜索並加載服務器類。

搜索並加載服務器實例類的工作由一個輔助類完成,它的全限定類名是org.jboss.system.server.ServerLoader。這個類會創建

一個特定的類加載器,並使用這個類加載器加載服務器類,然后利用反射機制,創建一個服務器實例。

boot方法首先創建一個ServerLoader實例,我們把它稱為loader,然后boot方法將一些url添加到loader中。我們把這些url稱為

服務器搜索路徑。loader就是在服務器搜索路徑中搜索服務器類。

loader自帶的url log4j-boot.jar、jboss-common.jar、jboss-system.jar、jboss-xml-binding.jar。

添加完服務器搜索路徑后,boot方法調用了loader的load方法。load方法以服務器搜索路徑作為參數,創建一個類加載器,並使用

它搜索和加載服務器類。如果成功加載,就利用放射機制,創建一個服務器實例,我們把它稱為server。

默認的服務器類是org.jboss.system.server.ServerImpl,它位於C:/JBoss/lib/jboss-system.jar中,並不在jboss的類路徑

中。因此,loader必須創建自己的類加載器,使用服務器搜索路徑作為類搜索路徑,才能夠找到ServerImpl。通過設置

jboss.server.type系統屬性,也可以使用自定義的服務器類。當然,前提是要保證自定義的服務器類的類文件要在服務器搜索路

徑中。

服務器實例創建完畢后,還需要對它進行配置,這就是下面的初始化工作。

五、初始化服務器實例

初始化服務器實例的主要工作就是將服務器配置信息封裝到一個對象中。這個對象是類

org.jboss.system.server.ServerConfigImpl的實例,如org.jboss.system.server.ServerConfigImpl@8b33e8。它包括了服務器實例的基本配置信息,例如JBoss的安裝路徑、服務器的根

目錄、服務器的日志目錄、服務器的臨時目錄、服務器的庫路徑等。

boot方法調用server的init方法,開始初始化工作。Init方法將初始化工作委派給server..doInit方法。doInit方法創建並配置ServerConfigImpl對象,並在最后在控制台和日志中打印出服務器的配置信息。

ServerConfigImpl對象是一個MBean,因此,用戶可以利用jmx控制台查看服務器實例的配置信息。

初始化完畢后,就要啟動服務器實例了。

六、啟動服務器實例

啟動服務器實例是一個復雜的過程,其中有很多的工作需要完成。前面已經提到,JBoss是基於JMX框架的,JBoss的主要功能都是

以MBean的形式作為服務提供的,服務之間利用JMX總線進行通信。直到目前為止,我們還沒有看到JMX相關的工作。因此,在服務

器實例的啟動過程中,首要的工作就是要搭建JMX框架。JMX框架搭建完畢后,JBoss需要創建幾個基本的服務,這些服務正是以

MBean的形式,掛在JMX框架上。之后,JBoss開始了部署過程。JBoss預配置的服務、用戶的部署單元都在這個階段被部署、啟動。

boot方法調用server.start方法,開始了啟動過程。start方法將啟動工作委派給了server.doStart方法。doStart方法依次完成以

下工作:

1.創建並啟動計時器

這個計時器是用來計算JBoss啟動的時間,JBoss啟動成功后,會在控制台輸出啟動過程所耗的時間,背后的秘密就在這里。(這個

無關緊要,為了完整性介紹一下)。

2.創建MBeanServer實例

MBeanServer是JMX框架的核心。JBoss需要創建一個MBeanServer實例。,MBeanServer的實現也是可以配置的。目前可以

使用兩種MBeanServer,一種是jvm platform MBeanServer,它是Java平台提供的;另一種是JBoss提供的,全限定類名為

org.jboss.mx.server.MBeanServerImpl。通過設置javax.management.builder.initial系統屬性,也可以使用自定義

MBeanServer。那么JBoss究竟使用的是哪種實現呢?如果Java版本達到或高於5.0,且jboss.platform.mbeanserver系統屬

為true,則使用jvm platform MBeanServer,否則都使用JBoss提供的MBeanServerImpl。(這一點說得並不准確,涉及

LazyMBeanServer,我還不太清除。大家可以認為,絕大部分情況下,都是用JBoss提供的MBeanServerImpl)。

3. 創建並注冊基礎服務

在創建MBeanServerImpl的過程中,會創建以下3個MBean:

第一個MBean是javax.management.MBeanServerDelegate, ObjectName=JMImplementation:type=MBeanServerDelegate

第二個MBean是一個動態MBean,org.jboss.mx.modelmbean.XMBean,ObjectName=JMImplementation:type=MBeanRegistry

第三個MBean是org.jboss.mx.loading.UnifiedLoaderRepository3,

ObjectName=JMImplementation:service=LoaderRepository, name=Default

第一個MBean是在調用MBeanServerImpl之前創建的,后面兩個MBean實在MBeanServerImpl的構造函數中創建的。 第二個MBean是用來MBeanServer的注冊表,所有掛在MBeanServer上的MBean都被注冊到注冊表中。第三個MBean與 JBoss的類加載架構有關,也是基礎服務之一。

服務器server和ServerConfigImpl也都是MBean,也都被注冊到MBeanServer,ObjectName分別為jboss.system:type=Server和jboss.system:type=ServerConfig。

然后,doStart方法創建並注冊以下3個MBean:

第一個MBean是org.jboss.system.server.ServerInfo,

ObjectName= jboss.system:type=ServerInfo

第二個MBean是org.jboss.system.ServiceController,

ObjectName= jboss.system:service=ServiceController

第三個MBean是org.jboss.deployment.MainDeployer,

ObjectName= jboss.system:service=MainDeployer

第一個MBean主要封裝了JBoss運行的軟硬件平台的信息,包括主機地址、J操作系統版本、Java版本等。

第二個MBean是用來控制MBean的生命周期。JMX規范沒有規定

引自博文:http://www.2cto.com/os/201404/293620.html

 

 

 

 

JBOSS5.0 配置詳解

 

JBoss5目錄結構

 

查看JBoss控制台JMX-Console 
//可以通過這個頁面進行對 JBOSS 的各服務的配置和管理。 
http://localhost:8080/jmx-console/

查看發布的WebService(進入 JbossWS 的查看界面)
http://localhost:8080/jbossws/

 

1.WAR文件的部署 
JBoss支持熱部署,也就是war文件部署到服務器上后不需要重新啟動JBoss(Tomcat不支這種特性)。war文件的部署很簡單,直接將war文件拷貝到JBoss/server/default/deploy目錄下即可。  


2.JBoss的目錄結構 
      bin:包含各種腳本文件以及相關文件,比如run.bat和shutdown.bat批處理文件。 
      client:存儲配置信息和可能被Java客戶端應用程序或外部Web容器用到的jar文件。 
      docs:保存在JBoss中引用到的XML文件和DTD文件(這里也提供了在JBoss中如何寫配置文件的例子)。該目錄下有針對不同的數據庫(如MySql、Oracle、SQL  Server、Postgres等)配置數據源的JCA配置文件。 
      lib:一些 JAR,JBoss 啟動時加載,且被所有 JBoss 配置共享。(不要把你的庫放在這里) 
      server: 這里的每一個子目錄對應着一個服務器配置。該配置由運行腳本文件時的參數"-c  <配置名稱>"來確定。在server目錄下有三個配置例子,即all、default和minimal,每一個配置安裝的服務都不一樣。 其中default下是缺省配置。


     minimal:僅加載啟動JBoss所需的最少服務,如日志服務、JNDI和URL部署掃描器(發現新的部署),不包含Web容器、EJB和JMS。 
     all:啟動所有的服務,包括RMI/IIOP、集群服務和Web服務部署器(默認配置不會被加載)。 
啟動JBoss時,如果run.bat不帶任何參數,則使用的配置是server/default目錄下的配置。如果要以其它目錄下的配置啟動JBoss,可以使用如下參數: 
run    -c    all 
上述命令將以all目錄下的配置信息啟動JBoss。也可以在server目錄下新建目錄,按自己的需要寫配置文件。

 

下面以default目錄為例,介紹服務器配置的目錄結構。 
     conf:該目錄下有指定核心服務的jboss-service.xml文件,也可以放其它服務配置的文件。 
     data:該目錄是JBoss內置的數據庫Hypersonic存儲數據的地方,也是JBossMQ(the  JBoss  implementation  of  JMS)存儲相關信息的地方。 
     deploy: 這是部署J2EE應用程序(jar、war和ear文件)的位置,只需將相應文件拷貝到該目錄下即可。該目錄也用來熱部署服務和JCA資源適配器。已經有 一些服務部署到這個目錄了,如jmx-console,你啟動JBoss后即可訪問。JBoss會周期性的掃描deploy目錄,當有任何組件改 變,JBoss會重新部署該程序。 
     lib:存放服務器配置所需的jar文件,比如,你可以將JDBC驅動程序放在該目錄下。 
     log:存放日志信息。JBoss使用Jakarta  log4j包存儲日志,在程序中你也可以直接使用該信息。 
    tmp:存儲在部署過程中解壓時產生的臨時文件。 
    work:Tomcat編譯JSP文件時的工作目錄。 
目錄data、log、tmp和work在JBoss安裝后並不存在,當JBoss運行時自動建立。 
另外,連接數據庫所用到的JDBC驅動程序要拷貝到JBoss_HOME /server /default /lib  目錄下。


3.  JBoss中的部署 
  JBoss中的部署過程非常的簡單、直接並且支持熱部署。在每一個配置中,JBoss不斷的掃描一個特殊的目錄的變化:$JBOSS_HOME/server/config-name/deploy。 
  你可以把下列文件拷貝到此目錄下: 
      *  任何jar庫(其中的類將被自動添加到JBoss的classpath中) 
      *  EJB  JAR 
      *  WAR  (Web  Appliction  aRrchive)  注意默認情況下context為war名稱. 
      *  EAR  (Enterprise  Application  aRchive) 
      *  包含JBoss  MBean定義的XML文件 
      *  一個包含EJB  JAR、WAR或者EAR的解壓縮內容,並以.jar、.war或者.ear結尾的目錄

 

二、實體 Bean發布前的准備工作
1、配置數據源XML並放置在[jboss安裝目錄]/server/default/deploy目錄,
數據庫驅動Jar包放置在[Jboss安裝目錄]\server\default\lib 目錄下,
放置后需要重啟Jboss服務器。如果數據源已經存在就不需要配置。
2、配置 persistence.xml文件,在文件中指定使用的源據源及各項參數。
3、把實體類和 persistence.xml文件打成 Jar,persistence.xml放在 jar文件的 META-INF目錄

各種數據庫的數據源配置模版你可以在[Jboss安裝目錄]\docs\examples\jca目錄中找到,默認名稱為:數據庫名+ -ds.xml 。

 

 

三、日志文件設置
若需要修改JBoss默認的log4j設置,可修改JBoss安裝目錄"server\default\conf下的jboss-log4j.xml文件,在該文件中可以看到,log4j的日志輸出在JBoss安裝目錄server\default\log下的server.log文件中。

不同應用生成到不同日志文件

Xml代碼   收藏代碼
  1. <!-- 應用日志輸出 -->  
  2.    <appender name="LIGHTESB" class="org.jboss.logging.appender.DailyRollingFileAppender">  
  3.       <errorHandler class="org.jboss.logging.util.OnlyOnceErrorHandler"/>  
  4.       <param name="File" value="${jboss.server.log.dir}/lightesb.log"/>  <!-- 就改了生成文件名稱 -->  
  5.       <param name="Append" value="true"/>  
  6.       <param name="DatePattern" value="'.'yyyy-MM-dd"/>  
  7.       <layout class="org.apache.log4j.PatternLayout">  
  8.          <param name="ConversionPattern" value="%d %-5p [%c] (%t) %m%n"/>  
  9.       </layout>  
  10.    </appender>  
  11.   
  12.    <appender name="WS" class="org.jboss.logging.appender.DailyRollingFileAppender">  
  13.       <errorHandler class="org.jboss.logging.util.OnlyOnceErrorHandler"/>  
  14.       <param name="File" value="${jboss.server.log.dir}/webservice.log"/>  
  15.       <param name="Append" value="true"/>  
  16.       <param name="DatePattern" value="'.'yyyy-MM-dd"/>  
  17.       <layout class="org.apache.log4j.PatternLayout">  
  18.          <param name="ConversionPattern" value="%d %-5p [%c] (%t) %m%n"/>  
  19.       </layout>  
  20.    </appender>  
  21.      
  22.     
  23.    <!-- 應用日志輸出 -->  
  24.    <category name="com.soa.lightesb">  
  25.       <priority value="DEBUG"/>  
  26.       <appender-ref ref="LIGHTESB"/>  
  27.    </category>  
  28.      
  29.    <!--服務日志輸出 -->  
  30.    <category name="com.soa.ws">  
  31.       <priority value="DEBUG"/>  
  32.       <appender-ref ref="WS"/>  
  33.    </category>  

 

修改jboss日志級別

由於JBOSS日志文件占用的空間太大,需要修改日志文件記錄信息的級別

JBOSS服務中的記錄日志文件:jboss-log4j.xml,修改<param name="Threshold" value="ERROR"/>

具體的value值有:DEBUG,INFO,WARN,ERROR.

 

 

JBOSS啟動時加載順序:

總結:

 

$JBOSS_HOME/common/lib  =》 deployer目錄下應用或者服務(包括配置的全局過濾器) =》 deploy下的數據源、隊列和應用等

 

JBOSS每次發布的時候都會生成一些臨時文件到\server\default\tmp\deploy下面去

JBOSS的機制就是,發布的時候將\server\default\deploy下面的一些基礎的應用一起發布,而這些基礎應用發布在temp的臨時目錄下,是作為所有應用的基礎包,也就是說這些包的優先級要高於每個普通應用的包的。 

 

需要注意的是:JBOSS在加載自帶的核心JAR之后,將會優先加載下面的兩個目錄 

1、D:\jboss\server\default\lib 

2、D:\jboss\server\default\tmp\deploy 

其中1會在2之前加載,而目錄2是發布某個WAR,EAR,EJB等應用之后生成的臨時的jar,這些應用的所有JAR會生成諸如temp*.jar的形式。本文開頭提到的錯誤也就是在目錄1中存在一個spring.jar的包,優先於各個應用的spring.jar包。

從JBOSS啟動的問題談及JBOSS中jar的加載順序

 

 

 Jboss 5啟動后只能從本機訪問,不能從遠程訪問的解決辦法

用netstat –na   查看,發現綁定到127.0.0.1上: 

tcp        0      0 127.0.0.1:8080

D:\jboss-5.1.0.GA\server\default\deploy\jbossweb.sar\server.xml中的:

Xml代碼   收藏代碼
  1. <Connector protocol="HTTP/1.1" port="8080" address="${jboss.bind.address}"   
  2.                connectionTimeout="20000" redirectPort="8443" />  

 

將${jboss.bind.address}修改為0.0.0.0即可

 

JBOSS配置數據源后的訪問

Java代碼   收藏代碼
  1. package com.test;  
  2.   
  3.   
  4. import java.sql.Connection;  
  5. import java.sql.PreparedStatement;  
  6. import java.sql.ResultSet;  
  7. import java.sql.SQLException;  
  8. import java.util.logging.Logger;  
  9.   
  10. import javax.naming.Context;  
  11. import javax.naming.InitialContext;  
  12. import javax.naming.NamingException;  
  13. import javax.sql.DataSource;  
  14.   
  15. public class JDBCUtil {  
  16.       
  17.     private final static Logger logger = Logger.getLogger(JDBCUtil.class.getName());  
  18.   
  19.     // 數據源  
  20.     private static DataSource ds;  
  21.       
  22.     private static String dsName = "java:/datasources/visesbdb";  
  23.   
  24.     static {  
  25.         try {  
  26.             Context ctx = new InitialContext();  
  27.             ds = (DataSource)ctx.lookup(dsName);  
  28.         } catch (NamingException e) {  
  29.             logger.warning("Can not lookup the data source which named : " + dsName);  
  30.             e.printStackTrace();  
  31.         }  
  32.     }  
  33.       
  34.     /** 
  35.      * 獲取數據庫連接 
  36.      *  
  37.      * @return 數據庫連接/null 
  38.      */  
  39.     public static Connection getConnection(){  
  40.         Connection conn = null;  
  41.         if(ds != null){  
  42.             try {  
  43.                 conn = ds.getConnection();  
  44.             } catch (SQLException e) {  
  45.                 logger.warning("Get Connection failed ...");  
  46.                 e.printStackTrace();  
  47.             }  
  48.         }  
  49.         return conn;  
  50.     }  
  51.       
  52.     /** 
  53.      * 關閉數據庫連接 
  54.      *  
  55.      * @param conn 
  56.      */  
  57.     public static void closeConnection(Connection conn){  
  58.         if(conn != null){  
  59.             try {  
  60.                 conn.close();  
  61.             } catch (SQLException e) {  
  62.                 e.printStackTrace();  
  63.             }  
  64.         }  
  65.     }  
  66.       
  67.     /** 
  68.      *  
  69.      * 通過查詢sql獲取結果集中第一行,第一列的值 
  70.      *  
  71.      * @param 查詢sql 
  72.      * @return 
  73.      */  
  74.     public static Object QueryUniqueResult(String query){  
  75.         Object result = null;   
  76.         Connection conn = getConnection();  
  77.         if(conn != null){  
  78.             try {  
  79.                 PreparedStatement ps = conn.prepareStatement(query);  
  80.                 ResultSet rs = ps.executeQuery();  
  81.                 if(rs.next()){  
  82.                     result = rs.getObject(1);  
  83.                 }  
  84.             } catch (SQLException e) {  
  85.                 logger.warning("execute query has error ...");  
  86.                 e.printStackTrace();  
  87.             }  
  88.         }  
  89.         closeConnection(conn);  
  90.         return result;  
  91.     }  
  92.   
  93. }  

 

Java代碼   收藏代碼
  1. package com.test;  
  2.   
  3. import javax.servlet.ServletContextEvent;  
  4. import javax.servlet.ServletContextListener;  
  5.   
  6.   
  7. public class TestContextListener implements ServletContextListener{  
  8.   
  9.     public void contextInitialized(ServletContextEvent sce) {  
  10.       
  11.         int access = 1;  
  12.         try {  
  13.             access = Integer.parseInt(JDBCUtil.QueryUniqueResult("SELECT T.CONFIG_VALUE FROM SYS_CONFIG T WHERE T.CONFIG_NAME = 'SRV_PARAMETER_CHECK_ACCESS'").toString());  
  14.         } catch (Exception e) {  
  15.         }  
  16.         System.out.println(access);  
  17.     }  
  18.   
  19.     public void contextDestroyed(ServletContextEvent sce) {  
  20.         // TODO Auto-generated method stub        
  21.     }     
  22. }  

 配置好數據源XML后可直接訪問。

jboss會自動查找server/default/deploy目錄下 **-ds.xml文件.並讀取其中內容.來得到相應DataSource

上例數據庫XML放在:server\default\deploy\datasources\visesbdb-ds.xml:

 

內部JNDI名字為:

<datasources>

    <local-tx-datasource>

        <jndi-name>datasources/visesbdb</jndi-name>

...

 

 

過濾器

WEB工程的FIiter需配到自己的web.xml中
JAVA工程無法定義Filter
EJB工程可以定義Filter,可以作為JBOSS的全局過濾器使用。

 

全局過濾器配置在server\default\deployers\jbossweb.deployer\web.xml中:

Xml代碼   收藏代碼
  1. <filter>  
  2.      <filter-name>mainFilter</filter-name>  
  3.      <filter-class>com.project.filter.MainFilter</filter-class>  
  4.   </filter>  
  5.   <filter-mapping>  
  6.      <filter-name>mainFilter</filter-name>  
  7.      <url-pattern>/*</url-pattern>  
  8.   </filter-mapping>  

 

Java代碼   收藏代碼
  1. /** 
  2.  * 該過濾器是一個全局的過濾器,過濾所有經過訪問J2EE服務器的請求 
  3.  */  
  4. public class MainFilter implements Filter {  
  5.       
  6.     private static final Logger logger = LoggerFactory.getLogger(MainFilter.class);  
  7.       
  8.     private ControlService cs = new ControlServiceImpl();  
  9.   
  10.     @Override  
  11.     public void destroy() {  
  12.         InstanceInfo.filterIsUp = false;  
  13.   
  14.     }  
  15.   
  16.     @Override  
  17.     public void doFilter(ServletRequest req, ServletResponse res,  
  18.             FilterChain chain) throws IOException, ServletException {  
  19.           
  20.         // 提取請求相關信息  
  21.         String requestURI = ((HttpServletRequest)req).getRequestURI();  
  22.         String ip = ServletUtils.getRequestIP((HttpServletRequest)req);  
  23.           
  24.         // 當前時間[yyyy-MM-dd hh:mm:ss.SSS] 請求IP[IP] 請求地址[requestURI]  
  25.         logger.debug("[" + ip + "][" + requestURI + "]");  
  26.           
  27.         // 只對SOAP請求做這些特殊操作  
  28.         // 判斷是否是SOAP請求  
  29.         // 判斷是否是Rest請求  
  30.         if(ServletUtils.isSoapRequest((HttpServletRequest)req) || ProxyServiceUtils.isRestRequest(((HttpServletRequest)req).getRequestURI())){  
  31.             // 記錄所有訪問的服務  
  32.             logger.info("[" + ip + "][" + requestURI + "]");  
  33.               
  34.             // 獲取服務英文名稱  
  35.             String serviceNameEn = ProxyServiceUtils.getServiceNameByRequestUri(requestURI);  
  36.             // 服務鑒權  
  37.             if(cs.accessAuth(serviceNameEn, ip)){  
  38.                   
  39.                 // 生成實例ID  
  40.                 String uuid = InstanceInfo.getInstanceUUID();  
  41.                   
  42.                 // 日志開關 1 為開啟,0為關閉  
  43.                 if("1".equals(Config.getConfigByName("log.switch"))){  
  44.                       
  45.                     logger.debug("log switch is on...");  
  46.                       
  47.                     // 封裝請求對象  
  48.                     RequestData rd = InstanceInfo.getRequestData();  
  49.                     rd.setInstanceUUID(uuid);  
  50.                     // 設置當前調用時間  
  51.                     rd.setDate(new Date(System.currentTimeMillis()));  
  52.                     rd.setServiceNameEn(serviceNameEn);  
  53.                     rd.setRequestURI(requestURI);  
  54.                     rd.setIp(ip);  
  55.                     // 設置測試標志  
  56.                     String testFlag = ((HttpServletRequest)req).getHeader("@test_flag");  
  57.                     if(testFlag != null && com.project.ws.constants.Constants.HTTPREQUEST_FOR_TEST_SERVICE.equals(testFlag.trim())){  
  58.                         rd.setIsTest(com.project.soa.ws.constants.Constants.HTTPREQUEST_FOR_TEST_SERVICE);  
  59.                     }  
  60.                       
  61.                     // 輸入輸出做封裝處理用來獲取輸入輸出  
  62.                     HttpServletRequestWrapper reqw = new HttpServletRequestWrapper((HttpServletRequest)req);  
  63.                     HttpServletResponseWrapper resw = new HttpServletResponseWrapper((HttpServletResponse)res);  
  64.                       
  65.                     chain.doFilter(reqw, resw);  
  66.                 }else{  
  67.                     chain.doFilter(req, res);  
  68.                 }  
  69.                   
  70.                 InstanceInfo.removeInstanceUUID();  
  71.                   
  72.             }else{  
  73.                 res.setContentType("text/xml;charset=UTF-8");  
  74.                 res.getWriter().write(SoapUtils.getAuthSoapMsg());  
  75.             }  
  76.               
  77.         }else{  
  78.             chain.doFilter(req, res);  
  79.         }  
  80.     }  
  81.   
  82.     @Override  
  83.     public void init(FilterConfig config) throws ServletException {  
  84.           
  85.         InstanceInfo.filterIsUp = true;  
  86.     }  
  87.   
  88. }  

 

..

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM