如何讓jboss eap 6.2+ 的多個war應用共享 jar 包?


weblogic有一個很貼心的功能,允許把多個war應用共同依賴的jar包,打包一個單獨的war,以libary方式部署,然后各應用在weblogic.xml里聲明引用該libary即可,這樣可大大減少打包后的war文件尺寸,可以加快部署的上傳進度,對web server而言,這類共用jar包只加載一次,也節省資源。

但是jboss下想達到類似的功能就要復雜很多了,先來一個簡單的示例:

一、基礎篇

1.1 假如我們先開發了一個工具庫,打包后生成的mylib.jar ,為了減少各種依賴項的干擾,這個工程不依賴任何其它第三方庫,只有一個測試方法:

package yjmyzz.test;

public class TestUtils {

    public String sayHello(String msg) {
        return "Hello ," + msg + " !";
    }
}

1.2 再建一個spring mvc的web項目,為了簡單起見,也只有一個空頁面,啥功能也沒有,pom.xml里引用剛才的mylib工程

1 <dependency>
2     <groupId>yjmyzz</groupId>
3     <artifactId>mylib</artifactId>
4     <version>1.0</version>
5     <scope>compile</scope>
6 </dependency>

Controller里,調用mylib中的sayHello方法

@RequestMapping("/index")
public String index() {
	TestUtils utils = new TestUtils();
	System.out.println(utils.sayHello("hello"));
	return "index";
}

然后打包,默認情況下mylib.jar會打進myweb項目的WEB-INF/lib下  

前面這些都是准備工作而已,不用太在意具體細節,下面才是正經開始.

現在我們要把這個mylib-1.0.jar給弄到jboss里,讓它成為jboss的默認模塊,最終目的是myweb.war的WEB-INF/lib目錄下,不再需要這個jar。

 

1.3 折騰 jboss EAP

a. $JBOSS_HOME/modules 目錄下,創建 mylib/main 目錄,即要保證$JBOSS_HOME/modules/mylib/main目錄存在

b. 把mylib-1.0.jar復制到$JBOSS_HOME/modules/mylib/main中

c. 在$JBOSS_HOME/modules/mylib/main中創建一個名為module.xml的文件,內容如下:

1 <?xml version="1.0" encoding="UTF-8"?>
2 <module xmlns="urn:jboss:module:1.1" name="mylib">
3     <resources>
4         <resource-root path="mylib-1.0.jar" />        
5     </resources>
6 </module>

注意:第2行中的name="xxx"這里的name一定要跟/modules/下的子目錄名一致,如果子目錄是多層結構,比如 /modules/mycompany/mylib/main,則這里的name應該是"mycompany.mylib"

 

1.4 應用新增加的module

module加好以后,myweb在啟動時並不知道jboss新增了這個module,有3種方法可以處理:

a) 修改myweb.war中META-INF/MANIFEST.MF清單文件

Manifest-Version: 1.0
Dependencies: mylib
Built-By: jimmy
Build-Jdk: 1.7.0_79
Created-By: Apache Maven 3.3.3
Archiver-Version: Plexus Archiver

注意第2行, Dependencies: mylib 把這行加上后,就表示myweb.war在啟動時,要依賴mylib這個module,如果我們自己開發的module不止一個,多個module之間要英文逗號隔開,比如:module1,module2

當然,這一行如果要人工手動添加,未免太不講究,有maven-plugin可以幫我們搞定:

 1 <plugin>
 2     <groupId>org.apache.maven.plugins</groupId>
 3     <artifactId>maven-war-plugin</artifactId>
 4     <configuration>
 5         <archive>
 6             <manifestEntries>
 7                 <Dependencies>mylib</Dependencies>
 8             </manifestEntries>
 9         </archive>
10     </configuration>
11 </plugin>

b) 還有第2種方式,在WEB-INF下添加文件jboss-deployment-structure.xml,內容如下:

1 <jboss-deployment-structure>
2     <deployment>
3         <dependencies>
4             <module name="mylib"/>
5         </dependencies>
6     </deployment>
7 </jboss-deployment-structure>

c) 上面二種方式,都是由應用本身來控制加載哪些模塊,也是我個人推薦的方式,還有一種一勞永逸的暴力方法,直接修改$JBOSS_HOME/standalone/configuration/standalone.xml文件(注:如果是domain模式,則相應修改domain.xml文件),內容如下:

1 <subsystem xmlns="urn:jboss:domain:ee:1.1">
2     <global-modules>
3         <module name="mylib" slot="main"/>
4     </global-modules>
5     <spec-descriptor-property-replacement>false</spec-descriptor-property-replacement>
6     <jboss-descriptor-property-replacement>true</jboss-descriptor-property-replacement>
7 </subsystem>

根據關鍵字":ee:1.1"找到這段, 添加第2-4行即可,這樣jboss在啟動時,會把這個當成全局module,默認加載。

注:這種方式雖然簡單,但是不推薦,原因是如果jboss部署了多個應用,其它應用不知道有這個全局module,在自己的項目中再重復打包這些jar包,極容易在啟動時造成沖突,最終啟動失敗,各種報錯。

只有一種情況,比較適合這種方式:數據庫驅動jar,比如:ojdbc6.jar這類,不過對於數據庫驅動jar包而言,有一種更簡單的方式,直接將驅動jar包當成普通應用來部署就行了,所以這種改standalone.xml的方式,仍然體現不出優越性。

 

1.5 修改pom.xml ,不打包公用jar包

既然mylib這個公用jar已經移動jboss中了,那么myweb這個項目打包里就不必再打包它了,修改pom.xml中的相關部分:

1 <dependency>
2     <groupId>yjmyzz</groupId>
3     <artifactId>mylib</artifactId>
4     <version>1.0</version>
5     <scope>provided</scope>
6 </dependency>

注意:第5行,改成provided表示該依賴項,運行時由jboss容器提供,因此打包時該項被忽略。

 

二、進階篇

根據前面的步驟,好象並不難弄,但是實際應用中,如果想把一些知名的開源jar包,比如:spring, mybatis, hibernate , jackson這些全都以module的形式弄到jboss里,卻並不容易,原因在於:這些開源項目本身又依賴其它開源項目,而其它開源項目,還有依賴,一層一層分析下來,關系十分復雜。更要命的的jboss本身也默認集成了一些知名的開源項目,比如:commons-logging之類,所以相互之間極容易沖突。就拿spring來說,最低層的是spring-core,它是依賴項最少的,如果要放到jboss的module中,module.xml內容為:

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 
 3 <module xmlns="urn:jboss:module:1.1" name="mylib.spring-core">
 4 
 5     <resources>
 6         <resource-root path="spring-core-4.1.1.RELEASE.jar" />        
 7     </resources>
 8 
 9     <dependencies>
10         <module name="org.apache.commons.logging"/>
11         <module name="javax.api" export="true"/>
12         <module name="org.jboss.vfs"/>
13     </dependencies>
14 
15 </module>

注意:9-13行,這里表示spring-core依賴了哪些更底層次的module,一個也都不能少,否則啟動時就會有一堆其名其妙的錯誤。所以,分析眾多開源項目和jboss內置module的依賴關系,將是一個極大的挑戰。

spring 4.1.1-RELEASE整套jar包,全部以module方式融合進jboss的話,步驟如下:
a) modules目錄下先創建子目錄org/springframework/spring/main

b) 將spring的一堆jar包復制進來,文件列表如下:
spring-aop-4.1.1.RELEASE.jar               

spring-aspects-4.1.1.RELEASE.jar          

spring-beans-4.1.1.RELEASE.jar
spring-context-4.1.1.RELEASE.jar           

spring-context-support-4.1.1.RELEASE.jar   

spring-core-4.1.1.RELEASE.jar              

spring-expression-4.1.1.RELEASE.jar        

spring-instrument-4.1.1.RELEASE.jar        

spring-instrument-tomcat-4.1.1.RELEASE.jar
spring-jdbc-4.1.1.RELEASE.jar
spring-jms-4.1.1.RELEASE.jar
spring-messaging-4.1.1.RELEASE.jar
spring-orm-4.1.1.RELEASE.jar
spring-oxm-4.1.1.RELEASE.jar
spring-test-4.1.1.RELEASE.jar
spring-tx-4.1.1.RELEASE.jar
spring-web-4.1.1.RELEASE.jar
spring-webmvc-4.1.1.RELEASE.jar
spring-webmvc-portlet-4.1.1.RELEASE.jar
spring-websocket-4.1.1.RELEASE.jar

c) module.xml內容如下:

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <module xmlns="urn:jboss:module:1.1" name="org.springframework.spring">
 3     <resources>
 4         <resource-root path="spring-aop-4.1.1.RELEASE.jar"/>
 5         <resource-root path="spring-aspects-4.1.1.RELEASE.jar"/>
 6         <resource-root path="spring-beans-4.1.1.RELEASE.jar"/>
 7         <resource-root path="spring-context-4.1.1.RELEASE.jar"/>
 8         <resource-root path="spring-context-support-4.1.1.RELEASE.jar"/>
 9         <resource-root path="spring-core-4.1.1.RELEASE.jar"/>
10         <resource-root path="spring-expression-4.1.1.RELEASE.jar"/>
11         <resource-root path="spring-instrument-4.1.1.RELEASE.jar"/>
12         <resource-root path="spring-instrument-tomcat-4.1.1.RELEASE.jar"/>
13         <resource-root path="spring-jdbc-4.1.1.RELEASE.jar"/>
14         <resource-root path="spring-jms-4.1.1.RELEASE.jar"/>
15         <resource-root path="spring-messaging-4.1.1.RELEASE.jar"/>
16         <resource-root path="spring-orm-4.1.1.RELEASE.jar"/>
17         <resource-root path="spring-oxm-4.1.1.RELEASE.jar"/>
18         <resource-root path="spring-test-4.1.1.RELEASE.jar"/>
19         <resource-root path="spring-tx-4.1.1.RELEASE.jar"/>
20         <resource-root path="spring-web-4.1.1.RELEASE.jar"/>
21         <resource-root path="spring-webmvc-4.1.1.RELEASE.jar"/>
22         <resource-root path="spring-webmvc-portlet-4.1.1.RELEASE.jar"/>
23         <resource-root path="spring-websocket-4.1.1.RELEASE.jar"/>
24     </resources>
25     <dependencies>
26         <module name="org.apache.commons.logging"/>
27         <module name="javax.api" export="true"/>
28         <module name="javaee.api" export="true"/>
29         <module name="org.jboss.vfs"/>
30     </dependencies>
31 </module>%

 d) 應用中jboss-deployment-structure.xml的內容如下:

1 <?xml version="1.0" encoding="UTF-8"?>
2 <jboss-deployment-structure>
3     <deployment>
4         <dependencies>
5             <module name="org.springframework.spring" export="true" meta-inf="export"/>
6         </dependencies>
7     </deployment>
8 </jboss-deployment-structure> 

 

三、實戰篇

下面就以一個Spring MVC 4.1.1 RELEASE + mybatis 3.2.8 + mysql + druid 的實例來說明,如何定制共享jar包:
這是打包后WEB-INF/lib下的所有依賴jar包:

aopalliance-1.0.jar
commons-dbcp-1.4.jar
commons-logging-1.1.3.jar
commons-pool-1.5.4.jar
mybatis-3.2.8.jar
mybatis-spring-1.2.2.jar
mysql-connector-java-5.1.25.jar
spring-aop-4.1.1.RELEASE.jar
spring-beans-4.1.1.RELEASE.jar
spring-context-4.1.1.RELEASE.jar
spring-core-4.1.1.RELEASE.jar
spring-expression-4.1.1.RELEASE.jar
spring-jdbc-4.1.1.RELEASE.jar
spring-tx-4.1.1.RELEASE.jar
spring-web-4.1.1.RELEASE.jar
spring-webmvc-4.1.1.RELEASE.jar

整個應用打包后,war包的尺寸約為6.7M(注:druid數據源是用在jboss創建jndi datasource的,所以不需要打包在war中)。根據前面的介紹,一步一步來精減發布包:

1. %JBOSS_HOME/modules/mylib/main 先創建該目錄,把lib下的這些jar文件,全復制進去

2. 然后創建module.xml

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <module xmlns="urn:jboss:module:1.1" name="mylib">
 3     <resources>
 4         <resource-root path="standard-1.1.2.jar"/>
 5         <resource-root path="jstl-1.2.jar"/>
 6         <resource-root path="aopalliance-1.0.jar"/>
 7         <resource-root path="mybatis-3.2.8.jar"/>
 8         <resource-root path="mybatis-spring-1.2.2.jar"/>
 9         <resource-root path="mysql-connector-java-5.1.25.jar"/>
10         <resource-root path="spring-aop-4.1.1.RELEASE.jar"/>
11         <resource-root path="spring-beans-4.1.1.RELEASE.jar"/>
12         <resource-root path="spring-context-4.1.1.RELEASE.jar"/>
13         <resource-root path="spring-core-4.1.1.RELEASE.jar"/>
14         <resource-root path="spring-expression-4.1.1.RELEASE.jar"/>
15         <resource-root path="spring-jdbc-4.1.1.RELEASE.jar"/>
16         <resource-root path="spring-tx-4.1.1.RELEASE.jar"/>
17         <resource-root path="spring-web-4.1.1.RELEASE.jar"/>
18         <resource-root path="spring-webmvc-4.1.1.RELEASE.jar"/>
19         <resource-root path="druid-1.0.15.jar"/>
20     </resources>
21     <dependencies>
22         <module name="org.apache.commons.logging"/>
23         <module name="javax.api" export="true"/>
24         <module name="javaee.api" export="true"/>
25         <module name="javax.transaction.api" export="true"/>
26         <module name="javax.servlet.api" optional="true"/>
27         <module name="org.jboss.vfs"/>
28     </dependencies>
29 </module>

3. 應用中的jboss-deployment-structure.xml

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <jboss-deployment-structure>
 3     <deployment>
 4         <exclusions>
 5            
 6         </exclusions>
 7         <dependencies>
 8             <module name="mylib"/>
 9         </dependencies>
10     </deployment>
11 </jboss-deployment-structure>

4. META-INF的特殊處理

因為spring的相關jar全放到jboss中了,這樣會給應用本身運行帶來問題,spring程序在啟動時,會解析bean.xml配置文件,這個過程會加載spring.handers等文件,原來spring打包在應用本身中時,這些文件內嵌在sping的jar中,所以不會有問題,現在這些文件沒有了,解析過程就會報錯,因此需要手動把這些文件放到META-INF下,如圖:

圖中的這些文件,在spring里都可以找到,如果你的應用還使用了struts2,jstl,standard這些jar包,這些jar包里META-INF下的tld等文件也要復制到自己項目的META-INF下,根據我實際測試的結果,如果出現問題

spring-webmvc-xxx.jar

struts2-core-xxx.jar

這二個jar最好還是打包到應用中

 

最后別忘記了修改pom.xml文件,把所有依賴項的scope改成provided。

這樣處理后,war包的尺寸從6.7M直接降到19K。


免責聲明!

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



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