这里的SpringBoot项目就写一个最基础的SpringBoot就行了,本文的重点是演示如何将SpringBoot打包部署成jar包,然后部署成Windows服务的过程。
个人习惯先上POM,虽然这个demo没什么东西,但是我觉得上Java代码之前先上POM是对读者最起码的尊重,哈哈哈哈。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.7.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.demo</groupId>
<artifactId>springforwinservice</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springforwinservice</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
怎么创建SpringBoot项目网上的资料太多了,我就不在这里献丑了,直接上代码。项目的结构很简单就是三层:Controller、Service和Model,如下图:
package com.demo.springforwinservice.ctrl;
import com.demo.springforwinservice.impl.DemoService;
import com.demo.springforwinservice.model.Message;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class DemoControler {
@Autowired
private DemoService demoService;
@ResponseBody
@RequestMapping(value = "/message",produces = "application/json", method = RequestMethod.GET)
public Message getMessage() {
Message msg = demoService.getMsg();
return msg;
}
}
package com.demo.springforwinservice.impl;
import com.demo.springforwinservice.model.Message;
import org.springframework.stereotype.Service;
@Service
public class DemoService {
public Message getMsg(){
Message msg = new Message(0, "Success!");
return msg;
}
}
package com.demo.springforwinservice.model;
public class Message {
//0表示成功;-1表示失败
private int status;
//消息
private String message;
public int getStatus(){
return status;
}
public void setStatus(int status) {
this.status = status;
}
public String getMessage() {
return message;
}
public void setMessage(String message){
this.message = message;
}
public Message(int status, String massage) {
this.status = status;
this.message = massage;
}
}
写完上述代码后,给项目配置一个未被占用的端口号,就可以运行起来检查结果了。我这里使用接口开发的神器:Postman。如下图:
接口可以成功调用,证明项目没有问题。
我是直接使用Maven打的包,如下图:
打包完成后,会在项目路径下生成一个target文件夹,如下图:
红线里就是打出来的jar包。
打出来jar包后,先不要着急部署成Win服务,最好先验证下jar包是否可用。
下面在控制台中启动:
然后同样使用Postman进行接口调用:
没有问题。
验证jar包好用之后,就是本篇的重点了,配置Procrun。
Procrun是Apache推出的一套能让Java应用程序在Windows平台以服务的方式运行的插件。它主要包括两个程序:
当时我找这个下载地址还很费了一点劲儿哈哈。
地址为: http://www.apache.org/dist/commons/daemon/binaries/windows/
下载名为:commons-daemon-1.2.0-bin-windows.zip的压缩包,如下图:
下载并解压后,长这个样子:
首先我们创建一个目录,比如我这里叫做SpringForWinServiceDemo_Procrun,然后在其下创建三个文件夹,分别是JAR、Logs和Service,如下图:
JAR文件夹,用来放Spring打出来的jar包,如下图:
Logs文件夹用来保存Win Service的运行日志,目前是空的。
Service文件夹用来存放Procrun的exe。首先,将解压的commons-daemon-1.2.0-bin-windows\amd64文件夹下的prunsrv.exe,拷贝到Service文件夹中,如下图:
其次,将commons-daemon-1.2.0-bin-windows文件夹下的prunmgr.exe,拷贝到Service文件夹中,并重命名,我这里命名为SpringForWinServiceDemo.exe,如下图:
这样组织目录就设置好了。
在编写安装服务的脚本install.bat之前,有个非常重要,但是非常容易被忽视的问题(别的博客也没有提到过),这个问题会直接影响你的服务是否能够运行起来,那就是:
“确认你的jar包的Main-Class”。
对于我这个工程,我最开始想都不想,就觉得jar包里的Main-Class就是com.demo.springforwinservice.SpringforwinserviceApplication,然后配到脚本里,服务倒是装上了,但是怎么都启动不起来。。。蛋疼,最后搞了半天才得以解决,方法如下:
找到jar包,使用压缩软件打开,如下图:
进入这个META-INF文件夹,使用记事本打开MANIFEST.MF文件,如下图
看见了么,Main-Class是org.springframework.boot.loader.JarLauncher,而不是com.demo.springforwinservice.SpringforwinserviceApplication。
确定了这个后,开始写install.bat,如下:
@echo off
rem 设置程序名称
set SERVICE_EN_NAME=SpringForWinServiceDemo
set SERVICE_CH_NAME=Spring演示服务
rem 设置java路径
set JAVA_HOME=%JAVA_HOME%
rem 设置程序依赖及程序入口类
cd..
set BASEDIR=%CD%
set CLASSPATH=%BASEDIR%\JAR\springforwinservice-0.0.1-SNAPSHOT.jar
set MAIN_CLASS=org.springframework.boot.loader.JarLauncher
rem 设置prunsrv路径
set SRV=%BASEDIR%\Service\prunsrv.exe
rem 设置日志路径及日志文件前缀
set LOGPATH=%BASEDIR%\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 then install service
goto end
:foundJvm
echo 正在安装服务...
rem 安装
"%SRV%" //IS//%SERVICE_EN_NAME% --DisplayName="%SERVICE_CH_NAME%" "--Classpath=%CLASSPATH%" "--Install=%SRV%" "--JavaHome=%JAVA_HOME%" "--Jvm=%JVM%" --JvmMs=256 --JvmMx=1024 --Startup=auto --JvmOptions=-Djcifs.smb.client.dfs.disabled=false ++JvmOptions=-Djcifs.resolveOrder=DNS --StartMode=jvm --StartClass=%MAIN_CLASS% --StartMethod=main --StopMode=jvm --StopClass=%MAIN_CLASS% --StopMethod=main --StopParams= --LogPath=%LOGPATH% --StdOutput=auto --StdError=auto
echo 安装服务完成。
pause
卸载服务的uninstall.bat脚本比较简单,编写完成后同样放到Service文件夹下即可,如下:
@echo off
cd..
set basedir=%CD%
set SERVICE_NAME=SpringForWinServiceDemo
set SRV=%BASEDIR%\Service\prunsrv.exe
echo 正在卸载服务...
"%SRV%" //DS//%SERVICE_NAME%
echo 服务卸载完毕。
pause
执行install.bat,如下图:
提示“安装服务完成”后,在Windows任务栏的搜索框中直接输入“服务”或者“Service”,就可以打开Windows服务,如下图:
看,服务已经装好了。
装好的服务还没有启动,我们需要手动将其启动,回到Service文件夹,双击打开SpringForWinServiceDemo.exe,然后点击“开始”,如下:
如果一切正常的话,服务就可以成功启动了,如下图:
再次回到Windows服务列表页,可以看到服务的状态为“正在运行”,如下图:
注意,如果服务起不来的话,一定要去检查Procrun的log,在这里:
仍然使用Postman,来调用下这个Windows服务的接口,如下图:
Good, every good!
本地服务部署成功咯~~
如果想要卸载服务,运行uninstall.bat即可,如下图:
然后重启电脑即可看见对应的服务已经没有了~~~~
(怎么才能在不重启电脑的前提下,彻底卸载删除服务的方法我摸索了半天也没找到,所以欢迎大家交流以及批评指正~~~)