tags: java jsw maven ziphtml
使用java開發程序,在windows平臺下,通常有web應用,後臺服務應用,桌面應用:java
- web應用多數打成war包在web容器(如tomcat,jetty等)中運行
- 桌面應用通常打成jar包或exe文件運行
- 後臺服務應用通常打成jar包,而後使用命令行(如java -jar xxx.jar)運行
前面兩種運行方式在本文不做討論,主要描述java開發的後臺服務程序(如定時任務程序,文件處理,數據備份等)。linux
若使用命令行方式運行java程序,把命令寫成腳本(如bat腳本)運行便可,但命令行方式有其不方便之處,如命令行窗口不能關閉,關閉即中止,所以維護人員容易誤操做(關閉窗口使程序中止);若服務器宕機或其它緣由,程序每每沒法在服務器重啓時自動啓動。在windows下,不少程序都是以服務的形式運行,這也符合windows的管理。所以,建議使用服務形式運行,操做方便。web
有幾種方法可讓java程序以服務形式運行:apache
- Java Service Wrapper目前業界最知名、最成熟的解決方案,添加任何額外的代碼便可使用,不足之處是收費、64位版本須要購買Licence,不過在64位使用32位的也關係不大(除非你的程序須要很大的運算量)。
- Yet Another Java Service Wrapper相似JSW的開源實現版本,不過官方支持不怎麼好。
- Apache Commons Daemon著名的Apache Commons工具包的成員,按規則添加啓動程序,再編寫腳本實現。
- 其它的(如WinRun4J,Launch4j)未使用過,更多可參考java開源打包工具
本文主要講解使用java service wrapper把java程序做爲windows的服務運行,它不須要添加任何代碼,配置便可。windows
java程序打包通常打成jar包,若是是供其它調用打包成一個jar包上傳到倉庫,其它人能夠引用,這種方式可行,若是它是獨立的程序,有其它的額外文件(如配置文件,本文中說的wrapper文件),打成jar包就比較難處理了,所以,更多的狀況是把程序把成zip包以便傳輸,並規定好程序包目錄結構,打包時打成一個zip包,解壓即用。以下是我常常用到的一種包結構:tomcat
說明:服務器
- classes目錄:存放全部java編譯文件及資源配置文件
- lib目錄:存放全部程序使用到全部依賴jar
- wrapper:全部存放wrapper相關的文件,包括運行腳本bin,wrapper的配置文件conf,wrapper使用的依賴lib,及日誌存放目錄
所以,須要使用maven把程序打成zip包,解壓出來後就是上述的目錄結構,可直接運行。app
按前面所說的要求,本文如下面的一個示例進行講解,示例使用標準maven archetype結構,只實現了一個簡單的文件寫入內容的功能,使用jsw對程序進行包裝,並把它使用maven打包成zip,解壓後直接使用jsw的bin下的腳本安裝或卸載服務。jsp
從圖中可見,程序很簡單,僅一個java類FileLogger用於寫日誌到文件,使用log4j(1.2.16版本,如今流行slf4j和logback了)輸出日誌內容。日誌路徑是當前的classpath下的logs目錄。log4j使用參考它的官網,當前咱們主要關注如下兩點:
maven-assembly-plugin是maven中用於構建發佈包的插件,「assembly」是把一組文件、目錄、依賴元素組裝成一個歸檔文件,不只支持建立二進制歸檔文件,也支持建立源碼歸檔文件。目前Assembly插件支持以下格式的歸檔文件:
使用方法也比較簡單,可參考maven官網的assembly,通常是三個步驟
以下所示,在pom.xml文件中的build>plugins元素下配置assembly插件,請看註釋說明:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<!-- assembly版本 -->
<version>2.2.1</version>
<executions>
<!-- 若要同時打多個包(如windows和linux不一樣系統的包),可配置多個execution,此處只打zip,所以配置一個 -->
<execution>
<!-- id標識,惟一便可 -->
<id>make-wrapper-win-zip</id>
<!-- 設置package階段進行 -->
<phase>package</phase>
<goals>
<!-- 只運行一次 -->
<goal>single</goal>
</goals>
<configuration>
<!-- 輸出的最終名稱,自動添加格式後綴(如zip),當前示例爲jsw-test.zip -->
<finalName>jsw-test</finalName>
<!-- 配置是否添加id到名稱中,若爲true,當前示例中,則爲jsw-test-zip.zip,false即不添加,只是jsw-test.zip; 若同時打多個包,則可設爲true,分別添加id以做區分-->
<appendAssemblyId>true</appendAssemblyId>
<!-- 打包的輸出目錄,可自定義,${project.build.directory}爲編譯輸出目錄,即target目錄 -->
<outputDirectory>${project.build.directory}</outputDirectory>
<descriptors>
<!-- 使用的描述符,按此描述進行打包,此處配置一個zip.xml表示打zip包 -->
<descriptor>src/main/assembly/wrapper-win-zip.xml</descriptor>
</descriptors>
</configuration>
</execution>
</executions>
</plugin>
複製代碼
assembly插件在pom.xml的配置比較簡單,回答幾個問題便可:
前面講到要使用一個描述符進行打包操做,即wrapper-win-zip.xml,此類文件可統一存放在目錄src/main/assembly中,以便統一管理。wrapper-win-zip.xml的格式以下所示:
<assembly>
<!-- id標識,惟一便可,若pom中的appendAssemblyId設置爲true,則會添加此id做爲後綴 -->
<id>wrapper-win</id>
<formats>
<!-- 打包的格式 -->
<format>zip</format>
</formats>
<!-- 打包的文件不包含項目目錄,壓縮包下直接是文件 -->
<includeBaseDirectory>false</includeBaseDirectory>
<!-- 配置依賴的輸出 -->
<dependencySets>
<dependencySet>
<!-- 是否把當前項目的輸出jar包並使用,true則會把當前項目輸出爲jar包到輸出目錄,false不輸出 -->
<useProjectArtifact>false</useProjectArtifact>
<!-- 依賴輸出目錄,相對輸出目錄的根目錄,當前示例把依賴輸出到lib目錄 -->
<outputDirectory>/lib</outputDirectory>
</dependencySet>
</dependencySets>
<!-- 文件輸出 -->
<fileSets>
<fileSet>
<!-- 源目錄,此處是把編譯出來的class文件都輸出到根目錄下的classes目錄-->
<directory>${project.build.directory}/classes</directory>
<!-- 輸出目錄 -->
<outputDirectory>/classes</outputDirectory>
</fileSet>
<fileSet>
<!-- 此處是把wrapper文件所有輸出到根目錄下的wrapper目錄-->
<directory>install/wrapper/windows</directory>
<outputDirectory>/wrapper</outputDirectory>
</fileSet>
</fileSets>
</assembly>
複製代碼
詳細參考官網assembly的配置說明 說明一下,按上述的配置,使用maven命令進行打包(mvn package
),在target目錄會輸出的是一個jsw-test-wrapper-win包,當前此包名稱不影響程序運行,讀者可自行個性,包下面直接是三個文件夾(classes,lib,wrapper)。至此,便可以使用maven打出自定義的zip包。
jsw在不添加任何代碼的狀況下能夠直接使用,把java程序安裝爲windows服務,這樣就能夠隨着系統的運行而自動運行。
到java service wrapper官網下載,它支持各類操做系統,按系統下載便可,這裏講解windows的,下載32位(64位的收費)。
下載解壓後,內容以下:
java程序中添加jsw的步驟很簡單,主要如下兩步:
rem 程序目錄位置
set.APP_HOME=../..
rem java目錄位置
set.JAVA_HOME=E:/Program Files/Java/jdk1.8.0_51
rem 服務英文名稱
set.SERVICE_EN_NAME=jsw-test
rem 服務中文名稱
set.SERVICE_CH_NAME=jsw測試
rem 服務描述
set.SERVICE_DESCRIPTION=jsw測試
rem 你的Java應用程序的運行類(主類)
set.USER_MAIN_CLASS=service.FileLogger
複製代碼
而後主要設置如下配置(%var%
爲變量引用),其它配置按默認便可。若有個性化需求,可看官方文檔
- JVM位置:
wrapper.java.command=%JAVA_HOME%/bin/java
- 你的Java應用程序的運行類(主類)
wrapper.app.parameter.1=%USER_MAIN_CLASS%
- 你的Java程序所需的類路徑:
wrapper.java.classpath.1=../lib/wrapper.jar
wrapper.java.classpath.2=%APP_HOME%/classes
wrapper.java.classpath.3=%APP_HOME%/lib/*
- 你的Wrapper.DLL或wrapper.jar所在的目錄
wrapper.java.library.path.1=../lib
- 註冊爲服務的名稱和顯示名,你能夠隨意進行設置
wrapper.name=%SERVICE_EN_NAME%
wrapper.displayname=%SERVICE_CH_NAME%
wrapper.description=%SERVICE_DESCRIPTION%
- 日誌文件位置
wrapper.logfile=../logs/wrapper.log
配置完以後,使用bin下的腳本可進行相應的安裝,卸載操做。
使用maven打包,mvn package
,按前面的配置,便可輸出zip包,見前面的程序示例,把zip包放到服務,解壓,便可使用wrapper安裝服務。
3hs5