1. 程式人生 > >maven打造可執行war包(超詳細)

maven打造可執行war包(超詳細)

在開發java Web時,有時我們會使用嵌入式jetty來執行,專案完成後,如果能夠直接執行war包從而啟動jetty來執行war包那就非常完美了,本文將講解如何在專案中整合jetty 9,並構造可執行的war包(打包前和打包後都能隨時啟動)。

1.首先新增jetty 9的依賴(本文暫時只用到了jetty的以下依賴,讀者根據自己的專案需要增加)

<dependency>
    <groupId>org.eclipse.jetty</groupId>
	<artifactId>jetty-server</artifactId>
	<version
>
9.2.7.v20150116</version> </dependency> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-webapp</artifactId> <version>9.2.7.v20150116</version> </dependency>

2.專案中使用jetty 9。

首先我封裝了自己的JettyServer

public class EmbeddedServer
{ //public static final Logger logger = LoggerFactory.getLogger(EmbeddedServer.class); // private static final int DEFAULT_BUFFER_SIZE = 16192; protected final Server server = new Server(); public EmbeddedServer(int port,String path) throws IOException{ this(port,path,false,null
); } /** * use war to start * @param port * @param isWar * @param warPath * @throws IOException */ public EmbeddedServer(int port,boolean isWar,String warPath) throws IOException{ this(port,null,isWar,warPath); } private EmbeddedServer(int port, String path,boolean isWar,String warPath) throws IOException { Connector connector = getConnector(port); server.addConnector(connector); WebAppContext application = getWebAppContext(path,isWar,warPath); server.setHandler(application); server.setStopAtShutdown(true); } protected WebAppContext getWebAppContext(String path,boolean isWar,String warPath) { WebAppContext application; if(isWar){ application=new WebAppContext(); application.setWar(warPath); return application; }else{ application = new WebAppContext(path, "/"); application.setConfigurationDiscovered(true); application.setParentLoaderPriority(true); application.setClassLoader(Thread.currentThread().getContextClassLoader()); return application; } } protected Connector getConnector(int port) throws IOException { HttpConfiguration http_config = new HttpConfiguration(); // this is to enable large header sizes when Kerberos is enabled with AD //final int bufferSize = getBufferSize(); //http_config.setResponseHeaderSize(bufferSize); //http_config.setRequestHeaderSize(bufferSize); ServerConnector connector = new ServerConnector(server, new HttpConnectionFactory(http_config)); connector.setPort(port); connector.setHost("0.0.0.0"); server.addConnector(connector); return connector; } /*protected Integer getBufferSize() { try { Configuration configuration = ApplicationProperties.get(); return configuration.getInt("sysimple.jetty.request.buffer.size", DEFAULT_BUFFER_SIZE); } catch (Exception e) { // do nothing } return DEFAULT_BUFFER_SIZE; }*/ public void start() throws Exception { server.start(); //logger.info("********************************************************"); //logger.info("The SySimple Has Started !!!"); server.join(); } public void stop() { try { server.stop(); } catch (Exception e) { //logger.warn("Error during shutdown", e); } } }

接著可以使用封裝好的EmbeddedServer來啟動war

public class StartWeb{
	private static EmbeddedServer embeddedServer;
	public static void main(String[] args){
	//Start web server
	int port=3000try{
        	if(args.length==0){
        	    //該方式能夠在開發時快速啟動
            	embeddedServer=new EmbeddedServer(port, "src/main/webapp");
            }else{
                //傳入war包的路徑,該方法能夠在打包完成後啟動該war包
            	embeddedServer=new EmbeddedServer(port, true, args[0]);
            }
        	embeddedServer.start();
        }catch(Exception e){
        	System.exit(0);
        }
    }
}

注意:打包後如果需要啟動war包,需要使用如下的這種批處理命令來啟動:

以批處理命令(start.bat)和server.war在同級目錄下為例:(以下是start.bat的內容)

@echo off
set bat_dir=%~dp0
java -jar  %bat_dir%/web.war %bat_dir%/web.war

讀者可以考慮在程式碼中得到war包的路徑,這樣可以在啟動時省去傳參。

  1. 下面是最重要的:使用Maven構建可執行war包

總的來說可執行war包是將war包的結構仿照jar包的結構進行改變,第一個是需要在manifest中標記出主方法,第二個是編譯後的程式碼(包,而非.class)必須放在war包的最外層,最後要能夠找到專案的依賴。

①標記主方法

通過maven-war-plugin在manifest中標記主方法入口

<plugin>  
            <groupId>org.apache.maven.plugins</groupId>  
            <artifactId>maven-war-plugin</artifactId>  
            <configuration>
                <archive>
                    <manifest>
                        <mainClass>org.bit.linc.web.commons.StartWeb</mainClass>
                    </manifest>
                </archive>
            </configuration>
         </plugin>

②拷貝(也可以移動)web的所有的程式碼到war包最外層(使用maven-antrun-plugin)

<plugin>
                <groupId>org.apache.maven.plugins</groupId>  
                <artifactId>maven-antrun-plugin</artifactId>  
                <executions>
                    <execution>  
                        <id>main-class-placement</id>  
                        <phase>prepare-package</phase>  
                        <configuration>  
                            <target>
                                <copy todir="${project.build.directory}/${project.artifactId}/">  
                                    <fileset dir="${project.build.directory}/classes/">  
                                        <include name="**/*.*" />
                                    </fileset>  
                                </copy>
                            </target>  
                        </configuration>  
                        <goals>
                            <goal>run</goal>  
                        </goals>
                    </execution>  
                </executions>  
            </plugin>

③ 標記所有依賴的位置(將程式碼拷貝到war最外層後,會出現依賴的類都找不到的情況,因此需要讓war包能夠查詢到這些依賴)

將maven-war-plugin更改為如下內容:

<plugin>  
            <groupId>org.apache.maven.plugins</groupId>  
            <artifactId>maven-war-plugin</artifactId>  
            <configuration>
                <archive>
                    <manifest>
                        <mainClass>org.bit.linc.web.commons.StartWeb</mainClass>
                        <addClasspath>true</addClasspath>
                        <classpathPrefix>WEB-INF/lib</classpathPrefix>
                    </manifest>
                </archive>
            </configuration>
         </plugin>

現在可以構建可執行war包了。

以筆者的專案為例: 構建的war包中META-INF/MANIFEST.MF會變成如下內容:

Manifest-Version: 1.0
Built-By: wubo
Build-Jdk: 1.7.0_17
Class-Path: WEB-INF/lib/commons-0.0.2.jar WEB-INF/lib/commons-configur
 ation-1.8.jar WEB-INF/lib/commons-lang-2.6.jar WEB-INF/lib/commons-lo
 gging-1.1.1.jar WEB-INF/lib/slf4j-api-1.7.7.jar WEB-INF/lib/slf4j-log
 4j12-1.7.7.jar WEB-INF/lib/log4j-1.2.17.jar WEB-INF/lib/plugins-0.0.2
 .jar WEB-INF/lib/clusters-0.0.2.jar WEB-INF/lib/monitors-0.0.2.jar WE
 B-INF/lib/jetty-server-9.2.7.v20150116.jar WEB-INF/lib/javax.servlet-
 api-3.1.0.jar WEB-INF/lib/jetty-http-9.2.7.v20150116.jar WEB-INF/lib/
 jetty-util-9.2.7.v20150116.jar WEB-INF/lib/jetty-io-9.2.7.v20150116.j
 ar WEB-INF/lib/jetty-webapp-9.2.7.v20150116.jar WEB-INF/lib/jetty-xml
 -9.2.7.v20150116.jar WEB-INF/lib/jetty-servlet-9.2.7.v20150116.jar WE
 B-INF/lib/jetty-security-9.2.7.v20150116.jar WEB-INF/lib/gson-2.3.1.j
 ar
Created-By: Apache Maven 3.3.9
Main-Class: org.bit.linc.web.commons.StartWeb
Archiver-Version: Plexus Archiver

其中的Class-Path和Main-Class均已經改變。