eclipse導出maven工程的可執行jar包


一、eclipse導出maven工程的可執行jar包

建立兩個maven工程 ZKServer 和ZKClient

注意:用maven進行開發管理的話,默認的打出來的jar包是不能運行的,需要在pom.xml文件中添加如下配置以生成可執行的jar包

<build>
    <plugins>
      <plugin>
        <artifactId> maven-assembly-plugin </artifactId>
        <configuration>
          <descriptorRefs>
            <descriptorRef>zkServer</descriptorRef>
          </descriptorRefs>
          <archive>
            <manifest>
              <mainClass>com.fanghao.AppServer</mainClass> 
            </manifest>
          </archive>
        </configuration>
        <executions>
          <execution>
            <id>make-assembly</id>
            <phase>package</phase>
            <goals>
              <goal>single</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>

而我們在eclipse中創建的工程默認的 JRE System Library 是 Java-SE-1.5 ,我們需要添加以下配置讓其變成1.7或1.8,並且無論我們對該maven工程update多少次,都不會回到1.5

<build>
    <plugins>

      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <configuration>
          <source>1.8</source>
          <target>1.8</target>
        </configuration>
      </plugin>

  </plugins>
</build>

 

ZKServer工程

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0       http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.fanghao</groupId>
  <artifactId>ZKServer</artifactId>
  <version>0.0.1-SNAPSHOT</version>

  <dependencies>
    <dependency>
      <groupId>org.apache.zookeeper</groupId>
      <artifactId>zookeeper</artifactId>
      <version>3.4.11</version>
    </dependency>
  </dependencies>
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <configuration>
          <source>1.8</source>
          <target>1.8</target>
        </configuration>
      </plugin>
      <plugin>
        <artifactId> maven-assembly-plugin </artifactId>
        <configuration>
          <descriptorRefs>
            <descriptorRef>zkServer</descriptorRef>
          </descriptorRefs>
          <archive>
            <manifest>
              <mainClass>com.fanghao.AppServer</mainClass>
            </manifest>
          </archive>
        </configuration>
        <executions>
          <execution>
            <id>make-assembly</id>
            <phase>package</phase>
            <goals>
              <goal>single</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
</project>

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

package com.fanghao;

import java.util.concurrent.CountDownLatch;

import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.Watcher.Event.KeeperState;
import org.apache.zookeeper.ZooDefs.Ids;

/**
* 某分布式系統中,主節點可以有多台,可以動態上下線;
* 任意一台客戶端都能實時感知到主節點服務器的上下線。
*/
public class AppServer {
  private String groupNode = "sgroup";
  private String subNode = "sub";
  private CountDownLatch latch = new CountDownLatch(1);

  /**
  * 連接zookeeper
  * @param address server的地址
  */
  public void connectZookeeper(String address) throws Exception {
    ZooKeeper zk = new ZooKeeper("192.168.1.100:2181", 5000, new Watcher() {
      public void process(WatchedEvent event) {
        // 不做處理
        if(event.getState()==KeeperState.SyncConnected){
          latch.countDown();
        }
      }
    });
    // 在"/sgroup"下創建子節點
    // 子節點的類型設置為EPHEMERAL_SEQUENTIAL, 表明這是一個臨時節點, 且在子節點的名稱后面加上一串數字后綴
    // 將server的地址數據關聯到新創建的子節點上
    latch.await();
    String createdPath = zk.create("/" + groupNode + "/" + subNode, address.getBytes("utf-8"),
        Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
    System.out.println("create: " + createdPath);
  }

  /**
  * server的工作邏輯寫在這個方法中
  * 此處不做任何處理, 只讓server sleep
  */
  public void handle() throws InterruptedException {
    Thread.sleep(Long.MAX_VALUE);
  }

  public static void main(String[] args) {
    // 在參數中指定server的地址
    if (args.length == 0) {
      System.err.println("The first argument must be server address");
      System.exit(1);
    }

    AppServer as = new AppServer();
    try {
      as.connectZookeeper(args[0]);

      as.handle();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}

 

ZKClient工程

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0     http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.fanghao</groupId>
  <artifactId>ZKClient</artifactId>
  <version>0.0.1-SNAPSHOT</version>

  <dependencies>
    <dependency>
      <groupId>org.apache.zookeeper</groupId>
      <artifactId>zookeeper</artifactId>
      <version>3.4.11</version>
    </dependency>
  </dependencies>
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <configuration>
          <source>1.8</source>
          <target>1.8</target>
        </configuration>
      </plugin>
      <plugin>
        <artifactId> maven-assembly-plugin </artifactId>
        <configuration>
          <descriptorRefs>
            <descriptorRef>zkClient</descriptorRef>
          </descriptorRefs>
          <archive>
            <manifest>
              <mainClass>com.fanghao.AppClient</mainClass>
            </manifest>
          </archive>
        </configuration>
        <executions>
          <execution>
            <id>make-assembly</id>
            <phase>package</phase>
            <goals>
              <goal>single</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
</project>

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

package com.fanghao;

import java.util.ArrayList;
import java.util.List;

import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.Watcher.Event.EventType;
import org.apache.zookeeper.data.Stat;

/**
* 某分布式系統中,主節點可以有多台,可以動態上下線;
* 任意一台客戶端都能實時感知到主節點服務器的上下線。
* Created by tianjun on 2016/12/19 0019.
*/
public class AppClient {
  private String groupNode = "sgroup";
  private ZooKeeper zk;
  private Stat stat = new Stat();
  private volatile List<String> serverList;

  /**
  * 連接zookeeper
  */
  public void connectZookeeper() throws Exception {
    zk = new ZooKeeper("127.0.0.1:2181", 5000, new Watcher() {
        public void process(WatchedEvent event) {
          // 如果發生了"/sgroup"節點下的子節點變化事件, 更新server列表, 並重新注冊監聽
          if (event.getType() == EventType.NodeChildrenChanged
              && ("/" + groupNode).equals(event.getPath())) {
            try {
              updateServerList();
            } catch (Exception e) {
              e.printStackTrace();
            }
          }
        }
    });

    updateServerList();
  }

  /**
  * 更新server列表
  */
  private void updateServerList() throws Exception {
    List<String> newServerList = new ArrayList<String>();

    // 獲取並監聽groupNode的子節點變化
    // watch參數為true, 表示監聽子節點變化事件.
    // 每次都需要重新注冊監聽, 因為一次注冊, 只能監聽一次事件, 如果還想繼續保持監聽, 必須重新注冊
    List<String> subList = zk.getChildren("/" + groupNode, true);
    for (String subNode : subList) {
      // 獲取每個子節點下關聯的server地址
      byte[] data = zk.getData("/" + groupNode + "/" + subNode, false, stat);
      newServerList.add(new String(data, "utf-8"));
    }

    // 替換server列表
    serverList = newServerList;

    System.out.println("server list updated: " + serverList);
  }

  /**
  * client的工作邏輯寫在這個方法中
  * 此處不做任何處理, 只讓client sleep
  */
  public void handle() throws InterruptedException {
    Thread.sleep(Long.MAX_VALUE);
  }

  public static void main(String[] args) throws Exception {
    AppClient ac = new AppClient();
    ac.connectZookeeper();

    ac.handle();
  }

}

右鍵待導出的maven工程-> Export -> Java -> Runnable JAR file,單擊next

注意:如果 Launch Configuration:下面沒有工程對應的main方法所在的類或者什么都沒有,說明該類沒有在eclipse中執行過,只需要將該類執行一次即可;

          如果 Launch Configuration:下面的類太多了,可以將其清空,方法為刪除當前workspace對應的目錄下的 .metadata\.plugins\org.eclipse.debug.core\.launches 目錄下的內             容,注意是刪除workspace對應的目錄下的 .metadata\.plugins\org.eclipse.debug.core\.launches 目錄下的內容,不是刪除該目錄

二、在Windows系統下執行可執行jar包

打開cmd命令行窗口,切換到導出的可執行jar包所在的目錄,執行命令  java -jar xxx.jar [arg0] [arg1] [...]

其中 xxx.jar 是可執行jar包的名字,后面可傳入零或多個參數

三、在Linux系統下執行可執行jar包(亦可叫做啟動或停止java應用程序)

 1、檢查jdk是否已經安裝在Ubuntu上

打開終端,使用下面的命令:java -versio

如果你看到像下面的輸出,這就意味着你並沒有安裝過Jdk:

The program ‘java’ can be found in the following packages:
*default-jre * gcj-4.6-jre-headless * openjdk-6-jre-headless * gcj-4.5-jre-headless * openjdk-7-jre-headless Try: sudo apt-get install

2、在Ubuntu上安裝jdk

(1)下載jdk-8u161-linux-x64.tar.gz,直接用鼠標拖放到Ubuntu的桌面文件夾里,然后復制到在/usr/soft(如果沒有請新建)目錄下,解壓后刪除jdk-8u161-linux-x64.tar.gz

(2)配置java環境變量,配置在/etc/environment文件中

執行命令 gedit /etc/environment 打開/etc/environment文件的編輯窗口,配置JAVA_HOME,CLASSPATH和PATH,如下

JAVA_HOME="/usr/soft/jdk1.8.0_161"
CLASSPATH=".:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar"
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:$JAVA_HOME/bin:$HADOOP_INSTALL/bin"

(3)保存后執行 source  /etc/environment 使其立即生效,執行 java -version 命令檢查配置是否成功

3、執行可執行jar包

將可執行jar包拖放到某個目錄,然后切換到該目錄,直接執行命令  java -jar xxx.jar [arg0] [arg1] [...]

其中 xxx.jar 是可執行jar包的名字,后面可傳入零或多個參數,也可編寫啟動停止的shell腳本,如下是一個通用shell腳本

#!/bin/sh

#JDK所在目錄
JAVA_HOME="/usr/soft/jdk1.8.0_161"


#執行程序啟動所使用的系統用戶,考慮到安全,不推薦使用root用戶
RUNNING_USER=root


#Java程序所在的目錄(classes的上一級目錄)
APP_HOME=/opt/xxx/WEB-INF


#需要啟動的Java主程序(main方法所在類)
APP_MAINCLASS=com.fanghao.Main


#拼湊完整的classpath參數,包括制定lib目錄下所有的jar
CLASSPATH=$APP_HOME/classes
for i in "$APP_HOME"/lib/*.jar; do
  CLASSPATH="$CLASSPATH":"$i"
done


#java虛擬機啟動參數
JAVA_OPTS="-ms512m -mx512m -Xmn256m -Djava.awt.headless=true -XX:MaxPermSize=128m"

 

########################################
#(函數)判斷程序是否已啟動
#說明:使用JDK自帶的JPS命令及grep命令組合,准確查找pid
# jps加l參數,表示顯示java的完整包路徑
# 使用awk,分割出pid($1部分),及java程序名稱($2部分)
########################################
#初始化psid變量(全局)
psid=0

checkpid() {
  javaps=`$JAVA_HOME/bin/jps -l | grep $APP_MAINCLASS`
  if [ -n "$javaps" ]; then
    psid=`echo $javaps | awk '{print $1}'`
  else
    psid=0
  fi
}

########################################
#(函數)啟動程序
#說明:
#1、首先調用checkpid函數,刷新$psid全局變量
#2、如果程序已經啟動($psid不等於0),則提示程序已啟動
#3、如果程序沒有被啟動,則執行啟動命令行
#4、啟動命令執行后,再次調用checkpid函數
#5、如果步驟4的結果能夠確認程序的pid,則打印[OK],否則打印[Failed]
#注意:echo -n 表示打印字符后,不換行
#注意:"nohup 某命令 >/dev/null 2>&1 &" 的用法
########################################
start() {
  checkpid

  if [ $psid -ne 0 ]; then
    echo "==============================="
    echo "warn: $APP_MAINCLASS already started! (pid=$psid)"
    echo "==============================="
  else
    echo -n "Starting $APP_MAINCLASS ..."
    JAVA_CMD="nohup $JAVA_HOME/bin/java $JAVA_OPTS -classpath $CLASSPATH $APP_MAINCLASS >/dev/null 2>&1 &"
    su - $RUNNING_USER -c "$JAVA_CMD"
    checkpid
    if [ $psid -ne 0 ]; then
      echo "(pid=$psid) [Successfully started]"
    else
      echo "[Failed to start]"
    fi
  fi
}

########################################
#(函數)停止程序
#說明:
#1、首先調用checkpid函數,刷新$psid全局變量
#2、如果程序已經啟動($psid不等於0),則開始執行停止,否則提示程序未運行
#3、使用kill -9 pid命令強制殺死進程
#4、執行kill命令后,馬上查看上一句命令的返回值:$?
#5、如果步驟4的結果$?等於0,則打印[Successfully stopped],否則打印[Failed to stop]
#6、為了防止java程序被啟動多次,這里增加反復檢查進程,反復殺死的處理(遞歸調用stop)
#注意:echo -n 表示打印字符后,不換行
#注意:在shell編程中,"$?" 表示上一句命令或者一個函數的返回值
########################################
stop() {
  checkpid

  if [ $psid -ne 0 ]; then
    echo -n "Stopping $APP_MAINCLASS ...(pid=$psid)"
    su - $RUNNING_USER -c "kill -9 $psid"
    if [ $? -eq 0 ]; then
      echo "[Successfully stopped]"
    else
      echo "[Failed to stop]"
    fi

    checkpid
    if [ $psid -ne 0 ]; then
      stop
    fi
  else
    echo "==============================="
    echo "warn: $APP_MAINCLASS is not running"
    echo "==============================="
  fi
}

########################################
#(函數)檢查程序運行狀態
#說明:
#1、首先調用checkpid函數,刷新$psid全局變量
#2、如果程序已經啟動($psid不等於0),則提示正在運行並打印出pid,否則提示程序未運行
########################################
status() {
  checkpid

  if [ $psid -ne 0 ]; then
    echo "$APP_MAINCLASS is running!(pid=$psid)"
  else
    echo "$APP_MAINCLASS is not running!"
  fi
}

########################################
#(函數)打印系統環境參數
########################################
info() {
  echo "System Information:"
  echo "***************************************"
  echo `head -n 1 /etc/issue`
  echo `uname -a`
  echo
  echo "JAVA_HOME=$JAVA_HOME"
  echo `$JAVA_HOME/bin/java -version`
  echo
  echo "APP_HOME=$APP_HOME"
  echo "APP_MAINCLASS=$APP_MAINCLASS"
  echo "***************************************"
}

########################################
#讀取腳本的第一個參數($1),進行判斷
#參數取值范圍:{start|stop|restart|status|info}
#如果參數不在指定范圍之內,則打印幫助信息
########################################
case "$1" in
  'start')
    start
    ;;
  'stop')
    stop
    ;;
  'restart')
    stop
    start
    ;;
  'status')
    status
    ;;
  'info')
    info
    ;;
  *)
    echo "Usage: $0 {start|stop|restart|status|info}"
    exit 1
esac
exit 0


免責聲明!

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



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