jar文件打包瘦身与部署为Windows服务

需求: 由于spring boot 结合cloud 可以有多个微服务,可以打很多jar包,其中有很多maven库是重复的,package生成的jar中由于重复会占用大量的体积。造成在操作系统上部署时占用磁盘空间,安装过程也较慢。 同时,为了便于在操作系统上一键化部署jar服务,可以编写install.exe或install.sh来实现。在云平台上由于有install文件,也可以方便以组件的形式安装部署和卸载。


目前我了解的将Java程序部署为Windows服务的方式有java service wrapper和Apache Commons Daemon两种。

1.概述

1.1  为什么使用Apache Commons Daemon

      java service wrapper使用简单,集成方法简单,不修改任何代码,一般情况下已满足需求。但是,java service wrapper只对java程序的开启及关闭进行操作,若需要对程序启动前及关闭前进行一些自定义的操作(如启动时初始化工作,关闭时释放某些资源或进行特殊操作),此时就可以使用apache commons daemon了。

1.2  Apache Commons Daemon介绍

      Apache common deamon是用来提供java服务的安装,实现将一个普通的 Java 应用变成系统的一个后台服务,在linux下部署为后台运行程序,在windows部署为windows服务(著名的tomcat就是使用它实现启动及停止的。提供启动、停止、卸载等操作)。详细介绍可见commons-daemon官网(http://commons.apache.org/proper/commons-daemon/index.html)。相对java service wrapper,commons daemon需要自己写少许代码,即按规定要求编写程序启动及关闭的入口类,仅此而已。

2.下载安装

下载commons-daemon主程序commons-daemon-1.1.0-bin.zip,解压出commons-daemon-1.1.0.jar

下载procrun,官网的procrun页面只对它的使用进行讲解,在哪里下载即没有提及,这里特别提醒一下,需要在这里(http://www.apache.org/dist/commons/daemon/binaries/windows/)下载procrun,下载commons-daemon-1.1.0-bin-windows.zip。解压出文件如下:

jar文件打包瘦身与部署为Windows服务_第1张图片

将你的Java程序打成jar包,commons-daemon-1.1.0.jar和prunsrv.exe,prunmgr.exe,install.bat,uninstall.bat放到同一个文件夹下(注意64位的机器要用amd64文件夹下的prunsrv.exe)

3.spring boot 程序启动类实现

 pom.xml文件里新增loader包支持

      
        
            org.springframework.boot
            spring-boot-loader
        
        
            commons-daemon
            commons-daemon
            1.1.0
        

 

 

在***Aplication.class 相同目录下,新增一个启动类。

package com.mboot.wheelbase;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.loader.PropertiesLauncher;

/**
 * Daemon jsvc方式注册部署jar服务时的启动类
 */
public class DaemonMainLauncher  extends PropertiesLauncher {
    private static Logger LOGGER = LoggerFactory.getLogger(DaemonMainLauncher.class);

    private static DaemonMainLauncher daemonMainLauncher = null;

    public static void init(String[] args) {
    }

    public static void start(String[] args) {
        if (daemonMainLauncher == null)
            daemonMainLauncher = new DaemonMainLauncher();
        try
        {
            args = daemonMainLauncher.getArgs(args);
            daemonMainLauncher.launch(args);
        } catch (Exception ex) {
            System.exit(1);
        }
    }

    public static void destroy() {
    }

    public static void start() {
        String[] args = { "start" };
        start(args);
    }

    public static void stop(String[] args) {
        try {
            System.exit(0);
        } catch (Exception ex) {
            System.exit(1);
        }
    }

    public static void stop() {
        String[] args = { "stop" };
        stop(args);
    }

    public static void main(String[] args)
    {
        try {
            String mode = (args != null) && (args.length > 0) ? args[0] : null;
            if ("start".equals(mode)) {
                start(args);
            }
            else if ("stop".equals(mode)) {
                stop(args);
            }
            else
                start(args);
        }
        catch (Exception e) {
            System.exit(1);
        }
    }
}

 

pom.xml文件里配置bulid 插件。


    

        
            
            
                org.springframework.boot
                spring-boot-maven-plugin
                
                    true
                    ZIP
                    
                        
                            com.mboot
                            wheel-base
                        
                    
                
            

            
            
                org.apache.maven.plugins
                maven-jar-plugin
                
                    
                        
                            true
                            lib/
                            com.mboot.wheelbase.WheelBaseApplication
                        
                    
                
            

            
            
                org.apache.maven.plugins
                maven-dependency-plugin
                
                    
                        copy-dependencies
                        prepare-package
                        
                            copy-dependencies
                        
                        
                            ${project.build.directory}/lib
                            false
                            false
                            true
                        
                    
                
            

        

    

       编译打包生成wheel-base-0.0.1.jar 包,这个包即为瘦身后的包,大概只有几十KB,非常小。它不包含maven中引入的软件依赖库,而生成的依赖库则在pom.xml中配置的lib路径里面。将包含依赖库的lib文件复制出来作为接下来的公共依赖库使用。

下面来写服务安装脚本  install.bat

@echo off

rem 设置程序名称
set SERVICE_EN_NAME=WheelBase
set SERVICE_CH_NAME=WheelBase工作流引擎
set DESCRIPTION=wheel-base工作组件

rem 设置java路径
set _JAVA_HOME=%JAVA_HOME%


rem 设置程序依赖及程序入口类
set BASEDIR=%CD%
set BPM_LIBS=%BASEDIR%\server\lib
set BPM_MAIN_LIBS=%BASEDIR%\server\main_lib
set BPM_EXT_LIBS=%BASEDIR%\server\ext_lib
set BPM_LOG=%BASEDIR%\config\log
set _main=com.mboot.wheelbase.WheelBaseApplication
set _LauncherClass=com.mboot.wheelbase.DaemonMainLauncher
set CLASSPATH=%BPM_LIBS%\*;%BPM_MAIN_LIBS%\*;%BPM_EXT_LIBS%\*;%BPM_LOG%;%_JAVA_HOME%\lib\dt.jar;%_JAVA_HOME%\lib\tools.jar;%BPM_MAIN_LIBS%\wheel-base-0.0.1.jar;


rem 设置prunsrv路径 
set SRV=%CD%\prunsrv.exe

rem 设置日志路径及日志文件前缀
set LOGPATH=%BASEDIR%\tmp\logs

rem 输出信息
echo SERVICE_NAME: %SERVICE_EN_NAME%
echo JAVA_HOME: %JAVA_HOME%
echo MAIN_CLASS: %MAIN_CLASS%
echo prunsrv path: %SRV%

rem 设置jvm
if "%JVM%" == "" goto findJvm
if exist "%JVM%" goto foundJvm
:findJvm
set "JVM=%_JAVA_HOME%\jre\bin\server\jvm.dll"
if exist "%JVM%" goto foundJvm
echo can not find jvm.dll automatically,
echo please use COMMAND to localation it
echo for example : set "JVM=%_JAVA_HOME%\jre\bin\server\jvm.dll"
echo then install service
goto end
:foundJvm

rem 安装
"%SRV%" //IS//"%SERVICE_EN_NAME%" --DisplayName="%SERVICE_EN_NAME%" --Classpath="%CLASSPATH%"  --Description="%DESCRIPTION%" --Install="%SRV%" --JavaHome="%_JAVA_HOME%" --Jvm="%JVM%" --JvmMs=256 --JvmMx=1024 --Startup=auto --JvmOptions=-Djcifs.smb.client.dfs.disabled=false ++JvmOptions=-Djava.io.tmpdir="%CD%"/tmp ++JvmOptions=-Dloader.main=%_main% ++JvmOptions=-DBPM_HOME=%BASEDIR% ++JvmOptions=-Djcifs.resolveOrder=DNS --StartPath="%BASEDIR%" --StartMode=jvm  --StartClass=%_LauncherClass% --StartMethod=start --StopPath="%BASEDIR%" --StopMode=jvm --StopClass=%_LauncherClass% --StopMethod=stop --LogPath="%LOGPATH%" --StdOutput=auto --StdError=auto 

:end

    要注意的是classpath中的路径应有你Java程序的所有依赖包以及你自己打包程序的那个jar包,上述解压出的commons-daemon-1.1.0.jar也应该在这个路径中。
%SRV%  为prunsrv.exe所在路径

%LOGPATH%  为日志路径

--StartMethod   为程序入口开始方法(对应部署服务之后的启动)   必须要在自己打包的Java程序中写这个方法,根据自己的业务逻辑编写即可。(在某些博客中看到这个方法必须命名为start,实践证明并不需要,但你一定要有这个开始方法)。

--StopMethod   为程序入口结束方法(对应部署服务后的停止)   必须要在自己打包的Java程序中写这个方法,根据自己的业务逻辑编写即可。(在某些博客中看到这个方法必须命名为start,实践证明并不需要,但你一定要有这个结束方法)。

要格外注意的是以上两个方法一定要声明为public static void,并且一定要带参数(如string[] args),不然Apache Commons Daemon会报错,详情请见Apache Commons Daemon的官方说明文档。建议你所打包的Java入口程序中不写main方法,只写开始和结束方法。
 

再来写服务卸载脚本  uninstall.bat

@echo off
set BASEDIR=%CD%
set SERVICE_NAME=WheelBase
set "SRV=%BASEDIR%\prunsrv.exe"

%SRV% //DS//%SERVICE_NAME%

:end

简言之,到这一步为止,你的目录结构下应该有你自己打的jar包,commons-daemon-1.1.0.jar,prunsrv.exe,prunmgr.exe,install.bat,uninstall.bat

其目录结构如下,其中conf,server,tmp的子目录按照install.bat 文件中配置的文件路径创建即可:

jar文件打包瘦身与部署为Windows服务_第2张图片


此时运行install.bat脚本即可,运行之后会发现操作系统的服务中多了一个WheelBase服务,可以正常的启动和停止。tmp目录下中的log目录会记录启动日志,如下:

jar文件打包瘦身与部署为Windows服务_第3张图片

jar文件打包瘦身与部署为Windows服务_第4张图片

该日志记录了服务注册的成功与失败,以及停止卸载等。

 

jar文件打包瘦身与部署为Windows服务_第5张图片

在操作系统的服务中,点击“启动”后,spring boot 启动成功,表示服务注册部署成功。

如果要卸载该服务,运行uninstal.exe即可。

以上就是jar包瘦身与服务部署注册的完整过程,其中不涉及到业务代码的修改。只需要嵌入启动类即可。

 

 

 


 

你可能感兴趣的:(部署运维)