Ответ 1
Это стало возможным начиная с Spring Boot 1.3 с использованием winsw.
документация направляет вас к справочной реализации, которая показывает, как настроить службу.
Я пытаюсь завернуть загрузку spring "uber JAR" с прокруткой.
Выполнение следующих работ, как ожидалось:
java -jar my.jar
Мне нужна моя загрузочная банка spring для автоматического запуска при загрузке Windows. Самое приятное решение для этого было бы запустить банку как услугу (такую же, как автономный tomcat).
Когда я пытаюсь запустить это, я получаю "Прокрутка Commons Daemon с ошибкой с выходом: 3"
Глядя на источник spring -boot, он выглядит так, как будто он использует пользовательский загрузчик классов:
Я также получаю "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). В диспетчере задач нет упоминания о процессе (не очень хорошо, если я не слеп).
Это стало возможным начиная с Spring Boot 1.3 с использованием winsw.
документация направляет вас к справочной реализации, которая показывает, как настроить службу.
Я столкнулся с подобными проблемами, но нашел, что кто-то еще (Франческо Зануто) был достаточно любезен, чтобы написать сообщение в блоге об их усилиях. Их решение работало для меня. Я не беру на себя ответственность за время, которое они ввели в реализацию этого кода.
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);
}
}
}
}
Как и в Springboot v1.2.2, нет чистого способа закрыть приложение загрузки Spring, упакованное как банку uber, используя прокрутку. Обязательно следуйте этим вопросам, так как об этом также спрашивают другие:
Неясно, будут ли/ребята, которые будут с этим справляться. В то же время рассмотрите возможность распаковки uber jar и игнорирования Spring Boot JarLauncher.
Мой первоначальный ответ на этот вопрос (видимый в истории) предложил способ, который должен работать (и я думал, что сделал), но не из-за того, как обработчик класса обрабатывается в JarLauncher.
Просто наткнулся на это и хотел поделиться, я исправил эту проблему некоторое время назад и выдал запрос на перенос. https://github.com/spring-projects/spring-boot/pull/2520
Вы можете использовать мою разветвленную версию до тех пор, пока она не будет слита, чтобы начать/остановить использование прокрутки.
Держитесь подальше от 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\""