使用Java Service Wrapper 将Java程序注册成系统服务

     你是不是在找将Java程序注册成系统服务的方法?试试Java Service Wrapper这个工具吧,你可以从这个网站上面下载你喜欢的版本:http://wrapper.tanukisoftware.org/ ,Java Service Wrapper提供了适合市面上流行的操作系统的版本。

    使用WrapperJava程序注册成系统服务有三种方式可供选择:

    第一种是使用WrapperSimpleApp 这个帮助类来运行你的程序,这个是最简单的方法,也是官方推荐使用的方式,但是这样可能会对你的程序有改动,如果你在项目初期就开始考虑的话,这个方法还是不错的。像JBoss也是使用这种方式。

    第二种方式是使用WraperStartStopApp这个类来实现功能,这个方法适合那些通过ClassA类来负责启动服务,ClassB类来负责停止服务的应用场景。

    我使用的是第三种方式,这种方式好处是对程序改动比较小,只要让你的启动类实现WrapperListener接口,并实现接口中的start(String[] args) 和 stop(String [] args)方法,然后通过WrapperManager来启动。其他的一些配置比如要运行的主类全名、Java类路径、依赖Java库的路径、还有服务显示的名称,都可以通过配置文件conf/wrapper.conf来配置,相对来说比较灵活,像我目前在做的RCP项目有自动更新功能,更新下来的插件要比那些原来的插件的版本号要更新,虽然说会定期删除那些过期的插件,但有时还是会产生延迟,那么配置文件里面配置的Java类路径必须也要链接到最新的插件的地址,我是通过一个Java类来管理这个wrapper.confg文件,如果有更新的插件,通过Java类来得到最新插件的路径,将这些信息写入到wrapper.confg文件中,这样就能保证配置文件中的类路径是最新的了。
   下面是程序的结构:

https://i-blog.csdnimg.cn/blog_migrate/d1f45cb5b4db0b8676509cca73601f35.jpeg

 

    这里主页介绍一下wrapper.conf的配置,这个配置文件是Java常用的属性文件格式,

   wrapper.java.command=java: 指定要运行的Java,如果你不想设置环境变量的话,你也可以指定JDKbin文件路径

   wrapper.java.mainclass=test.Main: 指定要运行的类,这个类必须实现WrapperListener接口和接口中的startstop方法,通过WrapperManager类来初始化服务。如果启动服务过程中出现与不能取得JVM信息的情况,可能是接口实现的问题。

   wrapper.java.classpath.1=../lib/wrapper.jar:配置Java的类路径,这里的将wrapper.jar也包含在内,这里可以设置参数的位置,而且这个位置必须得从开始,不能跳过,必须顺序指定,指定类路径的时候还有根据依赖关系来排列,被依赖的排在前面,否则会出现ClassNotFoundException的错误,这里支持觉得路径和相对路径,也支持通配符"*",比如wrapper.java.classpath.1=../lib/wrapper*,不过这个通配符只能用于匹配文件名,不能用于匹配文件夹名称。

   wrapper.java.library.path.1=../lib:指定Wrapper自带的类库文件存放文件夹,比如Wrapper.DLL文件等,只要指定到对应的上级目录名称就行,支持通配符。

   wrapper.java.library.path.1=../lib:指定Wrapper自带的类库文件存放文件夹,比如Wrapper.DLL文件等,只要指定到对应的上级目录名称就行,支持通配符。

   wrapper.app.parameter.1= :指定运行类的main方法参数。

   wrapper.console.loglevel=INFO:配置控制台的显示信息的级别,NONE不显示任何输出信息,FATAL只显示致命的错误消息,ERROR显示所有的错误消息,STATUS显示服务状态的改变,包括服务启动和停止等信息,INFO显示所有程序输出的信息和JVM显示的信息,如果程序无法正常启动,可以使用DEBUG显示详细的调试信息。

   wrapper.logfile.loglevel=INFO:配置日志记录文件要记录的输出信息的级别,参数值和wrapper.console.loglevel功能一致

   wrapper.logfile.maxsize=0:配置日志文件的最大大小,如果为0表示不限制日志文件的大小,支持标记符,“k”代表KB,“m”代表MB,如果要设置最大大小为100KB的话可以这样:wrapper.logfile.maxsize=100k

   wrapper.console.title=Wrapper Demo :控制台窗口显示标题,

   wrapper.ntservice.name=testwrapper: 系统服务的名称

   wrapper.ntservice.displayname=Wrapper Demo:在服务管理中显示的名称

   wrapper.ntservice.description=Wrapper Demo的介绍信息: 在服务管理器显示服务的描述信息

   wrapper.ntservice.starttype=AUTO_START: 配置服务启动方式,可以选择AUTO_START(自动)DEMAND_START(手动)两种方式。默认为自动。


   下面是Wrapper自带的例子源代码,可以参考一下,

 

 1  package  org.tanukisoftware.wrapper.test;
 2 
 3  import  java.awt.List;
 4  import  java.awt.TextField;
 5  import  java.io.IOException;
 6  import  java.io.PrintStream;
 7  import  org.tanukisoftware.wrapper.WrapperActionServer;
 8  import  org.tanukisoftware.wrapper.WrapperListener;
 9  import  org.tanukisoftware.wrapper.WrapperManager;
10 
11  public   class  Main  extends  AbstractActionApp  implements  WrapperListener {
12     private  MainFrame m_frame;
13     private  DeadlockPrintStream m_out;
14     private  DeadlockPrintStream m_err;
15     private  Thread m_userRunner;
16     private  List m_listenerFlags;
17     private  TextField m_serviceName;
18 
19     public  Integer start(String[] args) {
20      System.out.println( " start() " );
21 
22      prepareSystemOutErr();
23       try  {
24         this .m_frame  =   new  MainFrame( this );
25         this .m_frame.setVisible( true );
26      }  catch  (InternalError e) {
27        System.out.println();
28        System.out.println( " ERROR - Unable to display the Swing GUI: " );
29        System.out.println( "            "   +  e.toString());
30        System.out.println( " Exiting " );
31        System.out.println();
32         return   new  Integer( 1 );
33      }
34 
35       try  {
36         int  port  =   9999 ;
37        WrapperActionServer server  =   new  WrapperActionServer(port);
38        server.enableShutdownAction( true );
39        server.enableHaltExpectedAction( true );
40        server.enableRestartAction( true );
41        server.enableThreadDumpAction( true );
42        server.enableHaltUnexpectedAction( true );
43        server.enableAccessViolationAction( true );
44        server.enableAppearHungAction( true );
45        server.start();
46 
47        System.out.println( " ActionServer Enabled.  " );
48        System.out.println( "   Telnet localhost 9999 " );
49        System.out.println( "   Commands:  " );
50        System.out.println( "     S: Shutdown " );
51        System.out.println( "     H: Expected Halt " );
52        System.out.println( "     R: Restart " );
53        System.out.println( "     D: Thread Dump " );
54        System.out.println( "     U: Unexpected Halt (Simulate crash) " );
55        System.out.println( "     V: Access Violation (Actual crash) " );
56        System.out.println( "     G: Make the JVM appear to be hung. " );
57      }  catch  (IOException e) {
58        System.out.println( " Unable to open the action server socket:  "   +  e.getMessage());
59      }
60       return   null ;
61    }
62 
63     public   int  stop( int  exitCode) {
64      System.out.println( " stop( "   +  exitCode  +   " ) " );
65 
66       if  ( this .m_frame  !=   null ) {
67         if  ( ! (WrapperManager.hasShutdownHookBeenTriggered())) {
68           this .m_frame.setVisible( false );
69           this .m_frame.dispose();
70        }
71         this .m_frame  =   null ;
72      }
73 
74       if  (isNestedExit()) {
75        System.out.println( " calling System.exit( "   +  exitCode  +   " ) within stop. " );
76        System.exit(exitCode);
77      }
78       return  exitCode;
79    }
80 
81     public   void  controlEvent( int  event) {
82      System.out.println( " controlEvent( "   +  event  +   " ) " );
83 
84       if  ((event  ==   202 &&  (WrapperManager.isLaunchedAsService()))  {
85        System.out.println( "   Ignoring logoff event " );
86      }  else {
87        WrapperManager.stop( 0 );
88      }
89    }
90 
91     public   static   void  main(String[] args) {
92      System.out.println( " Initializing " );
93 
94      WrapperManager.start( new  Main(), args);
95    }
96  }

 

   这个类实现了WrapperWrapperListener 并实现了它的startstop方法,start方法在服务器启动的时候调用,不过这里要注意,如果在30秒内你不能执行完start方法,系统会自动放弃这个服务的启动,解决办法可以在start方法使用线程,将比较耗时的操作放在这个线程执行,比如加载Spring文件等。而且如果在start方法执行出现异常,会终止服务的运行。这点要注意。

  Stop方法在服务停止启动,startstop方法的参数可以在wrapper.conf文件里面配置。一般按照这样配置的话你的程序应该可以通过执行StartApp-NT.bat正常启动了,

<!--endfragment-->
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值