SpringBoot项⽬在window系统下以系统服务的⽅式部署jar包1.部署背景:
作者的Java框架是以Spring cloud体系为基础构建的。基于Spring Boot⼀般有两种打包⽅式,⼀种是War包,⼀种是Jar包,抛开War包部署不讲,以jar包的形式部署是基于以下的考虑:
A:SpringBoot本⾝的优势之⼀是内置tomcat,如果我们以war包的形式打包并部署在tomcat下,那么这个优势还有没有必要?
B:官⽅建议使⽤velocity模板⽽不是jsp,是因为jar包形式运⾏对jsp⽀持不⾜,如果以war包部署,最初⼜何必纠结⽤jsp还是velecity
这些只是作者的⼀点想法,写这篇⽂章的根本原因是,我们公司的服务器采⽤的是windows操作系统,并且是window server 2012版本,这跟最后决定采不采⽤docker有关。
Docker for window对windows系统有要求,server版本最低要求是2016,低版本的windows系统要上docker只能使⽤docker toolbox,是linux容器。
这样的话,把服务器装成linux系统不就可以了吗?何况,上docker解决的并⾮是根本的部署问题。
题外话不说,这⾥主要解决的问题是,在windows操作系统下,如何以系统服务的⽅式运⾏jar包,令其后台运⾏,并且宕机时,开机⾃启。
2.采⽤技术:
通常情况下,我们在windows操作系统上部署java web程序,是以tomcat为主要web应⽤服务器,将项⽬war包放置于tomcat webapps⽬录下,并在bin⽬录下安装service.bat脚本注册window服务,运⾏进⾏管理,这种针对的是web项⽬。
SpringBoot内置tomcat,可以打包成jar包,通过主⽅法运⾏,本质上是独⽴的Java application,这种情况再放置于tomcat下运⾏,显然已不合适,当然,重新配置代码,并打成war包后仍可适⽤,这⾥我们只讲打成jar包的情况。在jar包的情况下,为此我查阅了⽹上资料。
3.个⼈说明:
⽹上有⼀些资料,但算不上许多,虽然我也是通过这些资料最终才实践成功的,但还是要写这篇⽂章,主要是因为那些⽂章的描述并不是很全,导致我在实践的过程中⾛了许多弯路,在这⾥,我可以负责任的说,如果你跟我有同样的需求,那么按照我的⽅案⾛,是可以解决你的问题的。
4.项⽬改造:
在实现window后台服务化的功能上,代码是有变动的,但这些变动并不影响项⽬本⾝以其他形式部署或运⾏。变动主要有以下⼏点。
A:实现window服务需要实现服务的标准,需要实现启动和停⽌这两个基本的接⼝。
B:SpringBoot打包和普通的jar包打包是不同的,class⽂件会包装在BOOT-INF下,导致正常的打包,你会class not found。so,需要使⽤ant辅助,只需要将主⽅法提取出来即可,这并不影响jar包的完整性。如此改造即可,也就是说,你需要额外建多⼀个类,提供下项⽬启动的⽅法,还有项⽬停⽌的⽅法,以及将该类可读,可以正常访问。
5.核⼼插件:
6.Jar包⽀持:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-loader</artifactId>
</dependency>
7.新增⼀个启动类
名字⾃取,我这⾥叫Bootstrap,放哪都可以,后⾯配置procrun会⽤到。
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 {
Thread.currentThread().setContextClassLoader(classLoader);
Thread runnerThread = new Thread(() -> {
try {
createMainMethodRunner(mainClass, args, classLoader).run();
}
catch(Exception ex) {}
});
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 {
classLoader = ClassPathArchives());
bootstrap.launch(args, MainClass(), classLoader, true);
}
catch (Exception ex) {
ex.printStackTrace();
}
}
public static void stop (String []args) {
try {
if (bootstrap != null) {
bootstrap.launch(args, MainClass(), classLoader, true);
bootstrap项目bootstrap = null;
classLoader = null;
}
}
catch (Exception ex) {
ex.printStackTrace();
}
}
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);
}
}
}
8.修改SpringBoot的application类
即SpringBoot的⼊⼝类。我的为ZooBusinessServiceApplication,修改main函数,启动时,是调⽤的springApplication.run,关闭时调⽤的是it,判断参数为stop字符串,这是重点。
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.ExitCodeGenerator;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import t.ApplicationContext;
import org.springframework.fig.EnableJpaAuditing;
import org.figuration.EnableGlobalMethodSecurity;
import java.lang.management.ManagementFactory;
@EnableDiscoveryClient
@SpringBootApplication
@EnableGlobalMethodSecurity(prePostEnabled = true)
@EnableJpaAuditing
public class ZooBusinessServiceApplication {
private static final Logger logger = Logger(ZooBusinessServiceApplication.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:" + RuntimeMXBean().getName() + " Application mode:" + mode + " context:" + applicationContext);
}
if (applicationContext != null && mode != null && "stop".equals(mode)) {
@Override
public int getExitCode() {
return 0;
}
}));
}
else {
SpringApplication app = new SpringApplication(ZooBusinessServiceApplication.class);
applicationContext = app.run(args);
if (logger.isDebugEnabled()) {
logger.debug("PID:" + RuntimeMXBean().getName() + " Application started context:" + applicationContext);
}
}
}
}
9.配置打包⽅式
因为SpringBoot默认的打包⽅式⽐正常jar包多了BOOT-INF⽬录,因此使⽤ant将此类按照正常jar包的⽅式开放出来。在l⾥的build⽂件⾥配置,我们的主类为Bootstrap
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
<executions>
<execution>
<phase>package</phase>
<configuration>
<target>
<zip destfile="${project.build.directory}/${project.build.finalName}.jar" update="true" compress="store">
<fileset dir="${project.build.directory}/classes" includes="com/ycsys/business/Bootstrap.class" />
</zip>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
10.配置procrun
java程序上做的修改已经完毕。接下来就是配置procrun的步骤。⾸先我们创建⼀个⽬录,名字叫procrun,并在此⽬录下创建⼀个source⽬录,把下载的procrun全部丢进去。再另起⼀个procrun下另起⼀个⽬录,我的项⽬叫zoo-business-service,所以这个⽬录也叫zoo-business-service。另外再建⼀个⽬录,专门存放jar包,例如at-deploys-jars,加个at前缀主要是跟起名⼀样a开头可以保证显⽰在最前⾯,如下图,其他的是我其他项⽬,这是我⾃⼰的组织⽅式,不喜可按⾃⼰的⽅式来。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。