Подтвердить что ты не робот

Spring boot JAR как служба Windows

Я пытаюсь завернуть загрузку spring "uber JAR" с прокруткой.

Выполнение следующих работ, как ожидалось:

java -jar my.jar

Мне нужна моя загрузочная банка spring для автоматического запуска при загрузке Windows. Самое приятное решение для этого было бы запустить банку как услугу (такую ​​же, как автономный tomcat).

Когда я пытаюсь запустить это, я получаю "Прокрутка Commons Daemon с ошибкой с выходом: 3"

Глядя на источник spring -boot, он выглядит так, как будто он использует пользовательский загрузчик классов:

https://github.com/spring-projects/spring-boot/blob/master/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/JarLauncher.java

Я также получаю "ClassNotFoundException" при попытке запустить мой основной метод напрямую.

java -cp my.jar my.MainClass

Есть ли способ, который я могу использовать для запуска моего основного метода в загрузочном банке spring (не через JarLauncher)?

Кто-нибудь успешно интегрировал spring -boot с прокруткой?

Я знаю http://wrapper.tanukisoftware.com/. Однако из-за их лицензии я не могу ее использовать.

UPDATE

Теперь мне удалось запустить службу с помощью прокрутки.

set SERVICE_NAME=MyService
set BASE_DIR=C:\MyService\Path
set PR_INSTALL=%BASE_DIR%prunsrv.exe

REM Service log configuration
set PR_LOGPREFIX=%SERVICE_NAME%
set PR_LOGPATH=%BASE_DIR%
set PR_STDOUTPUT=%BASE_DIR%stdout.txt
set PR_STDERROR=%BASE_DIR%stderr.txt
set PR_LOGLEVEL=Error

REM Path to java installation
set PR_JVM=auto
set PR_CLASSPATH=%BASE_DIR%%SERVICE_NAME%.jar

REM Startup configuration
set PR_STARTUP=auto
set PR_STARTIMAGE=c:\Program Files\Java\jre7\bin\java.exe 
set PR_STARTMODE=exe
set PR_STARTPARAMS=-jar#%PR_CLASSPATH%

REM Shutdown configuration
set PR_STOPMODE=java
set PR_STOPCLASS=TODO
set PR_STOPMETHOD=stop

REM JVM configuration
set PR_JVMMS=64
set PR_JVMMX=256

REM Install service
%PR_INSTALL% //IS//%SERVICE_NAME%

Теперь мне просто нужно тренироваться, как остановить службу. Я подумываю о том, чтобы сделать что-то с помощью spring-shutdown shutdown JTX Bean.

Что происходит, когда я останавливаю службу на данный момент; Windows не может остановить службу (но отмечает, что она остановлена), служба все еще работает (я могу перейти на localhost). В диспетчере задач нет упоминания о процессе (не очень хорошо, если я не слеп).

4b9b3361

Ответ 2

Я столкнулся с подобными проблемами, но нашел, что кто-то еще (Франческо Зануто) был достаточно любезен, чтобы написать сообщение в блоге об их усилиях. Их решение работало для меня. Я не беру на себя ответственность за время, которое они ввели в реализацию этого кода.

http://zazos79.blogspot.com/2015/02/spring-boot-12-run-as-windows-service.html

Он использует режим запуска и остановки jvm по сравнению с exe-режимом, который я вижу в вашем примере. Благодаря этому он может расширить Spring Boot JarLauncher для обработки команд "start" и "stop" из служб Windows, которые, я считаю, вы хотите сделать для изящного завершения работы.

Как и в его примерах, вы будете добавлять несколько основных методов, в зависимости от вашей реализации, вам нужно будет указать, к чему теперь следует запускать пусковую установку. Я использую Gradle и просто должен был добавить следующее в свой файл build.gradle:

springBoot{
    mainClass = 'mydomain.app.MyApplication'
}

Моя установка Procrun script:

D:\app\prunsrv.exe //IS//MyServiceName ^
--DisplayName="MyServiceDisplayName" ^
--Description="A Java app" ^
--Startup=auto ^
--Install=%CD%\prunsrv.exe ^
--Jvm=%JAVA_HOME%\jre\bin\server\jvm.dll ^
--Classpath=%CD%\SpringBootApp-1.1.0-SNAPSHOT.jar; ^
--StartMode=jvm ^
--StartClass=mydomain.app.Bootstrap ^
--StartMethod=start ^
--StartParams=start ^
--StopMode=jvm ^
--StopClass=mydomain.app.Bootstrap ^
--StopMethod=stop ^
--StopParams=stop ^
--StdOutput=auto ^
--StdError=auto ^
--LogPath=%CD% ^
--LogLevel=Debug

Класс расширения JarLauncher:

package mydomain.app;


import org.springframework.boot.loader.JarLauncher;
import org.springframework.boot.loader.jar.JarFile;

public class Bootstrap extends JarLauncher {

    private static ClassLoader classLoader = null;
    private static Bootstrap bootstrap = null;

    protected void launch(String[] args, String mainClass, ClassLoader classLoader, boolean wait)
            throws Exception {
        Runnable runner = createMainMethodRunner(mainClass, args, classLoader);
        Thread runnerThread = new Thread(runner);
        runnerThread.setContextClassLoader(classLoader);
        runnerThread.setName(Thread.currentThread().getName());
        runnerThread.start();
        if (wait == true) {
            runnerThread.join();
        }
    }

    public static void start (String []args) {
        bootstrap = new Bootstrap ();
        try {
            JarFile.registerUrlProtocolHandler();
            classLoader = bootstrap.createClassLoader(bootstrap.getClassPathArchives());
            bootstrap.launch(args, bootstrap.getMainClass(), classLoader, true);
        }
        catch (Exception ex) {
            ex.printStackTrace();
            System.exit(1);
        }
    }

    public static void stop (String []args) {
        try {
            if (bootstrap != null) {
                bootstrap.launch(args, bootstrap.getMainClass(), classLoader, true);
                bootstrap = null;
                classLoader = null;
            }
        }
        catch (Exception ex) {
            ex.printStackTrace();
            System.exit(1);
        }
    }

    public static void main(String[] args) {
        String mode = args != null && args.length > 0 ? args[0] : null;
        if ("start".equals(mode)) {
            Bootstrap.start(args);
        }
        else if ("stop".equals(mode)) {
            Bootstrap.stop(args);
        }
    }

}

Мой основной класс Spring:

package mydomain.app;

import java.lang.management.ManagementFactory;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.ExitCodeGenerator;
import org.springframework.boot.SpringApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.ComponentScan;

@SpringBootApplication
@ComponentScan
@EnableAutoConfiguration
public class MyApplication {

    private static final Logger logger = LoggerFactory.getLogger(MyApplication.class);
    private static ApplicationContext applicationContext = null;

    public static void main(String[] args) {
        String mode = args != null && args.length > 0 ? args[0] : null;

        if (logger.isDebugEnabled()) {
            logger.debug("PID:" + ManagementFactory.getRuntimeMXBean().getName() + " Application mode:" + mode + " context:" + applicationContext);
        }
        if (applicationContext != null && mode != null && "stop".equals(mode)) {
            System.exit(SpringApplication.exit(applicationContext, new ExitCodeGenerator() {
                @Override
                public int getExitCode() {
                    return 0;
                }
            }));
        }
        else {
            SpringApplication app = new SpringApplication(MyApplication.class);
            applicationContext = app.run(args);
            if (logger.isDebugEnabled()) {
                logger.debug("PID:" + ManagementFactory.getRuntimeMXBean().getName() + " Application started context:" + applicationContext);
            }
        }
    }
}

Ответ 3

Как и в Springboot v1.2.2, нет чистого способа закрыть приложение загрузки Spring, упакованное как банку uber, используя прокрутку. Обязательно следуйте этим вопросам, так как об этом также спрашивают другие:

Неясно, будут ли/ребята, которые будут с этим справляться. В то же время рассмотрите возможность распаковки uber jar и игнорирования Spring Boot JarLauncher.

Мой первоначальный ответ на этот вопрос (видимый в истории) предложил способ, который должен работать (и я думал, что сделал), но не из-за того, как обработчик класса обрабатывается в JarLauncher.

Ответ 4

Просто наткнулся на это и хотел поделиться, я исправил эту проблему некоторое время назад и выдал запрос на перенос. https://github.com/spring-projects/spring-boot/pull/2520

Вы можете использовать мою разветвленную версию до тех пор, пока она не будет слита, чтобы начать/остановить использование прокрутки.

Ответ 5

Держитесь подальше от winsw, он создан с помощью .NET, и у меня возникает много проблем в среде моих клиентов, Windows.

Я рекомендую NSSM, он создан с использованием чистого C, и я использовал его на всех моих устаревших Windows без проблем, Он имеет те же функции и многое другое...

Вот пример batch script (.bat), как его использовать:

rem Register the service
nssm install my-java-service "C:\Program Files\Java\jre1.8.0_152\bin\java.exe" "-jar" "snapshot.jar"
rem Set the service working dir
nssm set my-java-service AppDirectory "c:\path\to\jar-diretory"
rem Redirect sysout to file
nssm set my-java-service AppStdout "c:\path\to\jar-diretory\my-java-service.out"
rem Redirect syserr to file
nssm set my-java-service AppStderr "c:\path\to\jar-diretory\my-java-service.err"
rem Enable redirection files rotation
nssm set my-java-service AppRotateFiles 1
rem Rotate files while service is running
nssm set my-java-service AppRotateOnline 1
rem Rotate files when they reach 10MB
nssm set my-java-service AppRotateBytes 10485760
rem Stop service when my-java-service exits/stop
nssm set my-java-service AppExit Default Exit
rem Restart service when my-java-service exits with code 2 (self-update)
nssm set my-java-service AppExit 2 Restart
rem Set the display name for the service
nssm set my-java-service DisplayName "My JAVA Service"
rem Set the description for the service
nssm set my-java-service Description "Your Corp"
rem Remove old rotated files (older than 30 days)
nssm set my-java-service AppEvents Rotate/Pre "cmd /c forfiles /p \"c:\path\to\jar-diretory\" /s /m \"my-java-service-*.*\" /d -30 /c \"cmd /c del /q /f @path\""
rem Make a copy of my-java-service.jar to snapshot.jar to leave the original JAR unlocked (for self-update purposes)
nssm set my-java-service AppEvents Start/Pre "cmd /c copy /y \"c:\path\to\jar-diretory\my-java-service.jar\" \"c:\path\to\jar-diretory\snapshot.jar\""