示例代码:https://github.com/blvyoucan/SpringBootWinSW
请使用maven命令打包 [mvn clean package]

暴露JMX接口

@ManagedResource@ManagedOperation声明JMX操作
使程序能够通过JMX接口关闭

@SpringBootApplication
@ManagedResource(objectName=ApplicationShutdown.DEFAULT_OBJECT_NAME)
public class Application {
    private static ConfigurableApplicationContext context;

    public static void main(String[] args) {
        context = SpringApplication.run(Application.class, args);
    }
    
    @ManagedOperation
    public void shutdown() {
	    //关闭SpringBoot
        int exitCode = SpringApplication.exit(context);
        //退出java虚拟机
        System.exit(exitCode);
    }
}

访问shutdown操作

DEFAULT_OBJECT_NAME必须与前面@ManagedResource中的objectName一致
这里代码就是访问前面Application类中声明的JMX操作
这个类在关闭服务时起作用

public class ApplicationShutdown {
    public static final String DEFAULT_OBJECT_NAME = "sample:type=Application,name=application";

    public static void main(String[] args) {
        if( args.length == 0 ) {
            System.out.println("请传入JMX端口号");
        }
        String url = "service:jmx:rmi:///jndi/rmi://127.0.0.1:" + args[0] + "/jmxrmi";
        JMXServiceURL serviceUrl;
        try {
            serviceUrl = new JMXServiceURL(url);
            JMXConnector connection = JMXConnectorFactory.connect(serviceUrl, null);
            ObjectName objectName = new ObjectName(DEFAULT_OBJECT_NAME);
            connection.getMBeanServerConnection().invoke(objectName, "shutdown", null, null);
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (MalformedObjectNameException e) {
            e.printStackTrace();
        } catch (InstanceNotFoundException e) {
            e.printStackTrace();
        } catch (MBeanException e) {
            e.printStackTrace();
        } catch (ReflectionException e) {
            e.printStackTrace();
        }
    }
}

winsw配置文件

<service>
	<id>SpringBootWinSW</id>
	<name>SpringBootWinSW</name>
	<description>SpringBootWinSW</description>
	<workingdirectory>%BASE%\</workingdirectory>
	<logpath>%BASE%\logs</logpath>
	<logmode>rotate</logmode>
	
    <!--加上onfailure后,本人使用tskill java /A /V命令后,程序能自动启动-->
    <onfailure action="restart" delay="120 sec"/>
    <!--下面就是一条java -cp命令(也可以用java -jar),作用是启动SpringBoot程序,注意JMX端口-->
    <executable>java</executable>
    <startargument>-Dfile.encoding=UTF-8</startargument>
    <startargument>-Dspring.application.admin.enabled=true</startargument>
    <startargument>-Dcom.sun.management.jmxremote.port=50201</startargument>
    <startargument>-Dcom.sun.management.jmxremote.authenticate=false</startargument>
    <startargument>-Dcom.sun.management.jmxremote.ssl=false </startargument>
    <startargument>-cp</startargument>
    <startargument>SpringBootWinSW.jar</startargument>
    <startargument>sample.Application</startargument>
    <!--下面的java命令在关闭服务的时候调用,加载ApplicationShutdown类访问JMX暴露出来的shutdown方法
    注意最后的参数JMX端口要与启动时的一致-->
    <!--2020-05-27,今天发现如果不写stopexecutable,也能停止服务,也就是说不用暴露JMX的shutdown方法了
    <stopexecutable>java</stopexecutable>
    <stopargument>-cp</stopargument>
    <stopargument>SpringBootWinSW.jar</stopargument>
    <stopargument>sample.ApplicationShutdown</stopargument>
    <stopargument>50201</stopargument>
    -->
</service>

打包配置

打包不使用spring-boot-maven-plugin插件
主要是因为使用此插件打包后的jar包和普通的jar包结构不一样,java -cp命令无法识别sample.ApplicationShutdown这个类
pom.xml主要配置

    <properties>
        <start-class>sample.Application</start-class>
        <stop-class>sample.ApplicationShutdown</stop-class>
        
        <dist.finalname>${project.artifactId}</dist.finalname>
        <dist.dir>${project.build.directory}/dist</dist.dir>
        <dist.project.id>${dist.finalname}</dist.project.id>
        <dist.project.name>${dist.finalname}</dist.project.name>
        <dist.project.description>${dist.finalname}</dist.project.description>
        <dist.jmx.port>50201</dist.jmx.port>
        
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>1.8</java.version>
        
        <skipTests>true</skipTests>
    </properties>
    <build>
	    <!--指定打包后的jar文件名-->
        <finalName>${dist.finalname}</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <configuration>
                    <archive>
	                    <!--在jar文件中写入jar包的运行信息,主要就是classpath,
	                    包含运行时需要加载的jar包信息-->
                        <manifest>
                            <mainClass>${start-class}</mainClass>
                            <addClasspath>true</addClasspath>
                            <classpathPrefix>lib/</classpathPrefix>
                        </manifest>
                        <manifestEntries>
                            <Class-Path>./</Class-Path>
                        </manifestEntries>
                    </archive>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-resources-plugin</artifactId>
                <executions>
                    <execution>
                        <id>copy-resources</id>
                        <phase>process-resources</phase>
                        <goals>
                            <goal>copy-resources</goal>
                        </goals>
                        <configuration>
                            <outputDirectory>${dist.dir}</outputDirectory>
                            <resources>
	                            <!--读取src/main/dist目录下的server.xml等文件,将文件中的占位符替换掉,
	                            生成最终的server.xml-->
                                <resource>
                                    <directory>src/main/dist</directory>
                                    <filtering>true</filtering>
                                </resource>
                            </resources>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <!--下面是最终打包操作,具体配置在windows.xml中-->
            <plugin>  
                <artifactId>maven-assembly-plugin</artifactId>  
                <configuration>  
                    <!-- not append assembly id in release file name -->  
                    <appendAssemblyId>false</appendAssemblyId>  
                    <descriptors>  
                        <descriptor>src/main/assembly/windows.xml</descriptor>
                    </descriptors>  
                </configuration>  
                <executions>
                    <execution>  
                        <id>make-assembly</id>
                        <phase>package</phase>  
                        <goals>  
                            <goal>single</goal>  
                        </goals>  
                    </execution>  
                </executions>  
            </plugin>
        </plugins>
    </build>

window.xml

<?xml version="1.0"?>
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 http://maven.apache.org/xsd/assembly-1.1.3.xsd">
    <id>windows</id>

    <formats>
        <format>zip</format>
    </formats>
    
    <includeBaseDirectory>true</includeBaseDirectory> 
     
    <dependencySets>
        <dependencySet>  
            <outputDirectory>lib</outputDirectory>
            <excludes>
                <exclude>${groupId}:${artifactId}</exclude>
            </excludes>
        </dependencySet>
    </dependencySets>
    
    <fileSets>
        <fileSet>
            <outputDirectory />
            <directory>${project.build.directory}</directory>
            <includes>
                <include>*.jar</include>
            </includes>
        </fileSet>
    </fileSets>  
   
    <files>
        <file>
            <outputDirectory />
            <source>src/main/winsw/WinSW.NET2.exe</source>
            <destName>${dist.finalname}.exe</destName>
        </file>
        <file>
            <outputDirectory />
            <source>${dist.dir}/service.xml</source>
            <destName>${dist.finalname}.xml</destName>
        </file>
        <file>
            <outputDirectory />
            <source>${dist.dir}/service.exe.config</source>
            <destName>${dist.finalname}.exe.config</destName>
        </file>
        <file>
            <outputDirectory />
            <source>${dist.dir}/安装说明.txt</source>
            <destName>安装说明.txt</destName>
        </file>
    </files>
</assembly>

安装服务

1.命令cd /d [发布目录]
2.命令SpringBootWinSW.exe install

卸载服务

1.命令cd /d [发布目录]
2.命令SpringBootWinSW.exe uninstall

启动服务

两种方式

  1. services.msc右键启动SpringBootWinSW
  2. 使用命令net start SpringBootWinSW

停止服务

两种方式

  1. services.msc右键停止SpringBootWinSW
  2. 使用命令net stop SpringBootWinSW
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐