我刚刚继承了一个java应用程序,需要在XP和vista上作为服务安装。我已经8年没有使用任何形式的windows了,我从来没有创建过服务,更不用说从java应用程序(我已经为应用程序准备了一个jar和一个依赖jar - log4j)。使其作为服务运行所必需的魔力是什么?我已经得到了源代码,所以代码修改(尽管最好避免)是可能的。
当前回答
另一个不错的选择是FireDaemon。它被一些大公司使用,比如NASA、IBM等;他们的网站上有完整的列表。
其他回答
通过结合使用外部内存和连接器API(从JDK16开始预览)与OpenJDK jextract项目来处理Windows服务的回调,然后使用jpackage来生成一个Windows EXE,然后可以注册为Windows服务,这是可能在100% Java代码中实现Windows服务。
请看这个例子,它概述了实现Windows服务所需的工作。所有Windows服务EXE必须为主入口点ServiceMain和服务控制处理程序提供回调,并在Advapi.DLL中使用API调用StartServiceCtrlDispatcherW, RegisterServiceCtrlHandlerExW和SetServiceStatus。
在具有外部内存结构的Java中,上述回调的流程是:
main()
Must register ServiceMain using StartServiceCtrlDispatcherW
Above call blocks until ServiceMain exits
void ServiceMain(int dwNumServicesArgs, MemoryAddress lpServiceArgVectors)
Must register SvcCtrlHandler using RegisterServiceCtrlHandlerExW
Use SetServiceStatus(SERVICE_START_PENDING)
Initialise app
Use SetServiceStatus(SERVICE_RUNNING)
wait for app shutdown notification
Use SetServiceStatus(SERVICE_STOPPED)
int SvcCtrlHandler(int dwControl, int dwEventType, MemoryAddress lpEventData, MemoryAddress lpContext)
Must respond to service control events and report back using SetServiceStatus
On receiving SERVICE_CONTROL_STOP reports SetServiceStatus(SERVICE_STOP_PENDING)
then set app shutdown notification
一旦完成Java应用程序,jpackage可以创建运行时+EXE,然后可以安装和注册为Windows服务。以管理员身份运行(=后面的空格很重要):
sc create YourJavaServiceName type= own binpath= "c:\Program Files\Your Release Dir\yourjavaservice.exe"
我认为Java服务包装器工作得很好。请注意,集成应用程序有三种方法。如果您不想更改代码,那么听起来选项1最适合您。配置文件可能有点疯狂,但只要记住(对于选项1)您正在启动并将为其指定参数的程序是它们的辅助程序,然后它将启动您的程序。他们对此有一个示例配置文件。
使用Java 8,我们可以在没有任何外部工具的情况下处理这种情况。Java 8附带的Javapackager工具提供了一个创建自包含应用程序包的选项:
原生类型 生成自包含的应用程序包(如果可能的话)。使用-B选项为正在使用的绑定器提供参数。如果指定了type,则只创建该类型的bundle。如果没有指定类型,则使用all。
以下值对type有效:
-native type
Generate self-contained application bundles (if possible). Use the -B option to provide arguments to the bundlers being used. If type is specified, then only a bundle of this type is created. If no type is specified, all is used.
The following values are valid for type:
all: Runs all of the installers for the platform on which it is running, and creates a disk image for the application. This value is used if type is not specified.
installer: Runs all of the installers for the platform on which it is running.
image: Creates a disk image for the application. On OS X, the image is the .app file. On Linux, the image is the directory that gets installed.
dmg: Generates a DMG file for OS X.
pkg: Generates a .pkg package for OS X.
mac.appStore: Generates a package for the Mac App Store.
rpm: Generates an RPM package for Linux.
deb: Generates a Debian package for Linux.
在windows的情况下,参考以下文档,我们可以根据需要创建msi或exe。
exe: Generates a Windows .exe package.
msi: Generates a Windows Installer package.
使用Apache Commons Daemon,您现在可以拥有自定义的可执行名称和图标!您还可以获得一个自定义的Windows托盘显示器与您自己的名称和图标!
我现在有我的服务运行与我自己的名称和图标(prunsrv.exe),和系统托盘监视器(prunmgr.exe)也有我自己的自定义名称和图标!
Download the Apache Commons Daemon binaries (you will need prunsrv.exe and prunmgr.exe). Rename them to be MyServiceName.exe and MyServiceNamew.exe respectively. Download WinRun4J and use the RCEDIT.exe program that comes with it to modify the Apache executable to embed your own custom icon like this: > RCEDIT.exe /I MyServiceName.exe customIcon.ico > RCEDIT.exe /I MyServiceNamew.exe customTrayIcon.ico Now install your Windows service like this (see documentation for more details and options): > MyServiceName.exe //IS//MyServiceName \ --Install="C:\path-to\MyServiceName.exe" \ --Jvm=auto --Startup=auto --StartMode=jvm \ --Classpath="C:\path-to\MyJarWithClassWithMainMethod.jar" \ --StartClass=com.mydomain.MyClassWithMainMethod Now you have a Windows service of your Jar that will run with your own icon and name! You can also launch the monitor file and it will run in the system tray with your own icon and name. > MyServiceNamew.exe //MS//MyServiceName
另一种选择是WinRun4J。这是一个可配置的java启动器,可作为windows服务主机(32位和64位版本)。它是开源的,使用上没有限制。
(完全披露:我参与了这个项目)。
推荐文章
- 在maven中安装mvn到底做什么
- 不可变与不可修改的集合
- 如何在JSON中使用杰克逊更改字段名
- GSON -日期格式
- 如何从线程捕获异常
- 无法解析主机"<URL here>"没有与主机名关联的地址
- 如何在Java中打印二叉树图?
- String.format()在Java中格式化双重格式
- com.jcraft.jsch.JSchException: UnknownHostKey
- Java中的操作符重载
- 如何加速gwt编译器?
- 在Hibernate中重新连接分离对象的正确方法是什么?
- 应该……接住环内还是环外?
- 如何格式化Joda-Time DateTime仅为mm/dd/yyyy?
- 如何在POM.xml中引用环境变量?