【JavaService】使用Java编写部署windows服务

如果你玩windows系统,你对服务这个东西并不会陌生,服务可以帮我们做很多事情,在不影响用户正常工作的情况下,可以完成很多我们需要的需求。

众所周知,微软的visio studio内置的Service类可以编写windows服务,对于一个Java开发人员来说,想要编写一个windows服务部署到服务器里面,

还要在自己的开发环境装一个visio studio,那太麻烦了。

那么问题来了,我想用java编写一个windows服务,这个想法可行吗?答案是肯定的,可行!

开源的JavaService帮我们解决了这一个问题,使用java也可以编写一个windows服务部署到windows里面。

 

闲话不多说,来看看如何利用JavaService实现Java编写部署windows服务。

 

首先需要用到的一些开发工具:

 

JDK

Eclipse

JavaService

 

这里我安装的JDK是1.6版本的,

Eclipse用于编写一个JAVA工程,

JavaService可在官网下载,下载地址:http://javaservice.objectweb.org,下载之前官方需要确认你的一些个人信息,提交后可以进入资源下载页面,我这里下载的是2.0.10版本。解压后有很多文件,我们只需要用到其中的JavaService.exe。

 

做饭炒一个菜,我们需要准备一些菜品原料,以上我们的菜都买好了,接下来看看主要准备工作和主要步骤。

首先安装JDK,默认安装到C盘就可以了。

 

然后配置java环境变量,这里就不细说了,上一个链接给予大家参考,环境变量要配置正确,这个很重要。

配置JDK环境变量:http://jingyan.baidu.com/article/c85b7a6414f2ee003bac95d5.html

 

接着编写一个Java工程

这里我贴出我的代码示例出来,是工作的一个需求,大致看一些主要代码即可,我下面会提到的。

这里是工程结构:

 

代码:

 

[java] view plain copy
 
  1. <span style="font-family:Microsoft YaHei;font-size:14px;">package com.ecservice;  
  2.   
  3. import java.io.BufferedReader;  
  4. import java.io.File;  
  5. import java.io.FileNotFoundException;  
  6. import java.io.FileOutputStream;  
  7. import java.io.IOException;  
  8. import java.io.InputStreamReader;  
  9. import java.net.InetAddress;  
  10. import java.net.NetworkInterface;  
  11. import java.net.SocketException;  
  12. import java.net.UnknownHostException;  
  13. import java.text.SimpleDateFormat;  
  14. import java.util.Date;  
  15.   
  16. public class ECService {  
  17.     private static Thread thread = null;  
  18.     private static Service service = null;  
  19.   
  20.     /** 
  21.      * 退出服务方法(该方法必须有参数 String [] args) 
  22.      *  
  23.      * @param args 
  24.      */  
  25.     public static void StopService(String[] args) {  
  26.         System.out.println(service.getLocalTime()+"停止服务");  
  27.         service.setRunFlag(false);  
  28.     }  
  29.   
  30.     /** 
  31.      * 启动服务方法(该方法必须有参数 String [] args) 
  32.      *  
  33.      * @param args 
  34.      */  
  35.     public static void StartService(String[] args) {  
  36.         // 产生服务线程  
  37.         service = new Service();  
  38.         thread = new Thread(service);  
  39.         System.out.println("\r\n"+service.getLocalTime()+"-----------启动服务-----------");  
  40.           
  41.         try {  
  42.             // 将服务线程设定为用户线程,以避免StartService方法结束后线程退出  
  43.             thread.setDaemon(false);  
  44.             if (!thread.isDaemon()) {  
  45.                 System.out.println(service.getLocalTime()+"成功设定线程为用户线程!");  
  46.             }  
  47.             // 启动服务线程  
  48.             thread.start();  
  49.         } catch (SecurityException se) {  
  50.             System.out.println(service.getLocalTime()+"线程类型设定失败!");  
  51.         }  
  52.     }  
  53.   
  54.     public static void main(String[] args) {  
  55.         new Service().run();  
  56. //      ECService.StartService(null);  
  57.     }  
  58. }  
  59.   
  60. class Service implements Runnable {  
  61.     private boolean runFlag = true;  
  62.   
  63.     /** 
  64.      * 设定服务线程运行标志值 
  65.      *  
  66.      * @param runFlag 
  67.      */  
  68.     public synchronized void setRunFlag(boolean runFlag) {  
  69.         this.runFlag = runFlag;  
  70.     }  
  71.   
  72.     /** 
  73.      * 取得服务线程运行标志值 
  74.      *  
  75.      * @param void 
  76.      */  
  77.     @SuppressWarnings("unused")  
  78.     private synchronized boolean getRunFlag() {  
  79.         return runFlag;  
  80.     }  
  81.   
  82.     @Override  
  83.     public void run() {  
  84.         System.out.println(getLocalTime()+"服务线程开始运行");  
  85.         // while (getRunFlag()) {  
  86.         // 获取当前计算机名和MAC  
  87.         String hostName = getHostName();  
  88.         if (hostName != null) {  
  89.             System.out.println(getLocalTime()+"计算机名获取成功!");  
  90.             // 获取本机mac地址  
  91.             String localMac = getMac();  
  92.             if (localMac != null) {  
  93.                 System.out.println(getLocalTime()+"mac获取成功!");    
  94.                 String mac = subMac(localMac);  
  95.                 // 匹配本机计算机名与mac地址  
  96.                 if (!hostName.equals(mac)) {  
  97.                     System.out.println(getLocalTime()+"开始执行修改计算机名称。");  
  98.                     // 执行修改计算机名  
  99.                     // 生成一个bat批处理文件  
  100.                     boolean isMakeBatSuccess = makeBat(mac);  
  101.                     if(isMakeBatSuccess == true){  
  102.                         System.out.println(getLocalTime()+"生成bat成功!");  
  103.                         // 执行bat  
  104.                         runCMD("C:\\ECService\\modify_hostname.bat");  
  105.                         System.out.println(getLocalTime()+"执行bat完毕!");  
  106.                         // 删除bat  
  107.                         removeBat("C:\\ECService\\modify_hostname.bat");  
  108.                         System.out.println(getLocalTime()+"执行删除bat完毕!");  
  109.                         // 重启机器  
  110.                         runCMD("shutdown -r -t 0");  
  111.                         System.out.println(getLocalTime()+"执行修改计算机名操作完毕,系统正在重启。");  
  112.                     }else{  
  113.                         System.out.println(getLocalTime()+"生成bat失败!");  
  114.                     }                     
  115.                 } else {  
  116.                     System.out.println(getLocalTime()+"本机计算机名与mac地址一致,不需要修改计算机名。");  
  117.                 }  
  118.             } else {  
  119.                 System.out.println(getLocalTime()+"获取本机mac地址失败!");  
  120.             }  
  121.         } else {  
  122.             System.out.println(getLocalTime()+"获取本机计算机名失败!");  
  123.         }  
  124.   
  125.         // }  
  126.         System.out.println(getLocalTime()+"服务线程结束运行");  
  127.     }  
  128.   
  129.     /** 
  130.      * 获取计算机名称 
  131.      *  
  132.      * @return 
  133.      */  
  134.     public String getHostName() {         
  135.         try {  
  136.             InetAddress inetAddress = InetAddress.getLocalHost();  
  137.             String hostName = "";  
  138.             hostName = inetAddress.getHostName();  
  139.             return hostName;  
  140.         } catch (Exception e) {  
  141.             // TODO Auto-generated catch block  
  142.             e.printStackTrace();  
  143.             System.out.println(getLocalTime()+"获取计算机名称失败:" + e.getMessage());  
  144.         }  
  145.         return null;  
  146.     }  
  147.   
  148.     /** 
  149.      * 获取MAC地址 
  150.      *  
  151.      * @return 
  152.      */  
  153.     public String getMac() {  
  154.         NetworkInterface byInetAddress;  
  155.         try {  
  156.             InetAddress localHost = InetAddress.getLocalHost();  
  157.             byInetAddress = NetworkInterface.getByInetAddress(localHost);  
  158.             byte[] hardwareAddress = byInetAddress.getHardwareAddress();  
  159.             return getMacFromBytes(hardwareAddress);  
  160.         } catch (SocketException e) {  
  161.             // TODO Auto-generated catch block  
  162.             e.printStackTrace();  
  163.             System.out.println(getLocalTime()+"获取mac地址失败:" + e.getMessage());  
  164.         } catch (UnknownHostException e) {  
  165.             // TODO Auto-generated catch block  
  166.             e.printStackTrace();  
  167.             System.out.println(getLocalTime()+"获取mac地址失败:" + e.getMessage());  
  168.         } catch (Exception e) {  
  169.             // TODO Auto-generated catch block  
  170.             e.printStackTrace();  
  171.             System.out.println(getLocalTime()+"获取mac地址失败:" + e.getMessage());  
  172.         }  
  173.         return null;  
  174.     }  
  175.   
  176.     public String subMac(String mac) {  
  177.         String r = mac.substring(9, mac.length());  
  178.         return r;  
  179.     }  
  180.   
  181.     public String getMacFromBytes(byte[] bytes) {  
  182.         StringBuffer mac = new StringBuffer();  
  183.         byte currentByte;  
  184.         boolean first = false;  
  185.         for (byte b : bytes) {  
  186.             if (first) {  
  187.                 mac.append("-");  
  188.             }  
  189.             currentByte = (byte) ((b & 240) >> 4);  
  190.             mac.append(Integer.toHexString(currentByte));  
  191.             currentByte = (byte) (b & 15);  
  192.             mac.append(Integer.toHexString(currentByte));  
  193.             first = true;  
  194.         }  
  195.         return mac.toString().toLowerCase();  
  196.     }  
  197.   
  198.     public boolean makeBat(String hostname) {  
  199.         boolean isSuccess = false;  
  200.         File file = new File("C:\\ECService\\modify_hostname.bat");  
  201.         try {  
  202.             file.createNewFile();  
  203.             StringBuilder sb = appendBat(hostname);  
  204.             String str = sb.toString();  
  205.             byte bt[] = new byte[1024];  
  206.             bt = str.getBytes();  
  207.             FileOutputStream in;  
  208.             in = new FileOutputStream(file);  
  209.             in.write(bt, 0, bt.length);  
  210.             in.close();  
  211.             isSuccess = true;  
  212.         } catch (FileNotFoundException e) {  
  213.             // TODO Auto-generated catch block  
  214.             e.printStackTrace();  
  215.         } catch (IOException e) {  
  216.             // TODO Auto-generated catch block  
  217.             e.printStackTrace();  
  218.         } catch (Exception e) {  
  219.             e.printStackTrace();  
  220.         }  
  221.         return isSuccess;  
  222.     }  
  223.   
  224.     public StringBuilder appendBat(String hostname) {  
  225.         StringBuilder sb = new StringBuilder();  
  226.         sb.append("set cname=" + hostname);  
  227.         sb.append("\r\n");  
  228.         sb.append("echo REGEDIT4 >c:\\windows\\reg.reg");  
  229.         sb.append("\r\n");  
  230.         sb.append("echo [HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\ComputerName] >> c:\\windows\\reg.reg");  
  231.         sb.append("\r\n");  
  232.         sb.append("echo [HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\ComputerName\\ComputerName] >> c:\\windows\\reg.reg");  
  233.         sb.append("\r\n");  
  234.         sb.append("echo \"ComputerName\"=\"%cname%\" >> c:\\windows\\reg.reg");  
  235.         sb.append("\r\n");  
  236.         sb.append("echo [HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\ComputerName\\ActiveComputerName] >> c:\\windows\\reg.reg");  
  237.         sb.append("\r\n");  
  238.         sb.append("echo \"ComputerName\"=\"%cname%\" >> c:\\windows\\reg.reg");  
  239.         sb.append("\r\n");  
  240.         sb.append("echo [HKEY_LOCAL_MACHINE\\SYSTEM\\ControlSet002\\Control\\ComputerName\\ComputerName] >> c:\\windows\\reg.reg ");  
  241.         sb.append("\r\n");  
  242.         sb.append("echo \"ComputerName\"=\"%cname%\" >> c:\\windows\\reg.reg");  
  243.         sb.append("\r\n");  
  244.         sb.append("echo [HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters] >> c:\\windows\\reg.reg");  
  245.         sb.append("\r\n");  
  246.         sb.append("echo \"NV Hostname\"=\"%cname%\" >> c:\\windows\\reg.reg");  
  247.         sb.append("\r\n");  
  248.         sb.append("echo \"Hostname\"=\"%cname%\" >> c:\\windows\\reg.reg");  
  249.         sb.append("\r\n");  
  250.         sb.append("echo [HKEY_USERS\\S-1-5-18\\Software\\Microsoft\\Windows\\ShellNoRoam] >> c:\\windows\\reg.reg");  
  251.         sb.append("\r\n");  
  252.         sb.append("echo @=\"%cname%\" >> c:\\windows\\reg.reg");  
  253.         sb.append("\r\n");  
  254.         sb.append("echo [HKEY_LOCAL_MACHINE\\SYSTEM\\ControlSet001\\Control\\ComputerName\\ActiveComputerName] >> c:\\windows\\reg.reg");  
  255.         sb.append("\r\n");  
  256.         sb.append("echo \"ComputerName\"=\"%cname%\" >> c:\\windows\\reg.reg");  
  257.         sb.append("\r\n");  
  258.         sb.append("echo [HKEY_LOCAL_MACHINE\\SYSTEM\\ControlSet001\\Services\\Tcpip\\Parameters] >> c:\\windows\\reg.reg");  
  259.         sb.append("\r\n");  
  260.         sb.append("echo \"NV Hostname\"=\"%cname%\" >> c:\\windows\\reg.reg");  
  261.         sb.append("\r\n");  
  262.         sb.append("echo \"Hostname\"=\"%cname%\" >> c:\\windows\\reg.reg");  
  263.         sb.append("\r\n");  
  264.         sb.append("echo [HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon] >> c:\\windows\\reg.reg");  
  265.         sb.append("\r\n");  
  266.         sb.append("echo \"DefaultDomainName\"=\"%cname%\" >> c:\\windows\\reg.reg");  
  267.         sb.append("\r\n");  
  268.         sb.append("echo \"AltDefaultDomainName\"=\"%cname%\" >> c:\\windows\\reg.reg");  
  269.         sb.append("\r\n");  
  270.         sb.append("regedit /s c:\\windows\\reg.reg");  
  271.         sb.append("\r\n");  
  272.         sb.append("exit");  
  273.         return sb;  
  274.     }  
  275.   
  276.     public String runCMD(String commands) {  
  277.         String result = "";  
  278.         try {  
  279.             Process process = Runtime.getRuntime().exec(commands);  
  280.             BufferedReader errorReader = new BufferedReader(  
  281.                     new InputStreamReader(process.getInputStream()));  
  282.             String line = null;  
  283.             while ((line = errorReader.readLine()) != null) {  
  284.                 result += line + "\n";  
  285.             }  
  286.             errorReader.close();  
  287.         } catch (Exception e) {  
  288.             e.printStackTrace();  
  289.         }  
  290.         return result;  
  291.     }  
  292.   
  293.     public void removeBat(String path) {  
  294.         File file = new File(path);  
  295.         if (file.exists()) {  
  296.             boolean isflag = file.delete();  
  297.             if (isflag == true){  
  298.                 System.out.println(getLocalTime()+"删除bat成功!");  
  299.             }  
  300.             else {  
  301.                 System.out.println(getLocalTime()+"删除bat失败!");  
  302.             }  
  303.         } else {  
  304.             System.out.println(getLocalTime()+"删除bat失败,批处理文件不存在!");  
  305.         }  
  306.     }  
  307.       
  308.     public String getLocalTime(){  
  309.         String time ="[";  
  310.         SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
  311.         time += df.format(new Date()).toString();  
  312.         time+="]";  
  313.         return time;  
  314.     }  
  315.   
  316. }  
  317. </span>  


这里看主要代码:

 

 

[javascript] view plain copy
 
  1. public static void StartService(String[] args) {  
  2.   //启动服务的方法  
  3. }</span>  

 

[java] view plain copy
 
  1. public static void StopService(String[] args) {  
  2.   //停止服务的方法  
  3. }</span>  


编写完工程代码后,将工程打包为jar包。

 

右键项目-Export,选择打包为JAR包

Finish

 

JAR包打包完毕,接下来开始做注册服务的工作。

将之前下载的JavaService解压得到JavaService.exe后,将它和jar包,统一放到文件夹C:\ECService内(注意,不要有中文路径,否则服务启动会失败)。

其中err.log和out.log是运行服务后JavaService生成的日志文件。

 

以管理员身份运行cmd,CD到JavaService.exe和jar包所在的目录

 

然后执行命令

JavaService.exe -install ECService "%JAVA_HOME%/jre/bin/server/jvm.dll" -Xmx128m -Djava.class.path="%JAVA_HOME%/lib/tools.jar;c:/ECService/ec.jar" -start com.ecservice.ECService -method StartService -stop com.ecservice.ECService -method StopService -out "%CD%/out.log" -err "%CD%/err.log" -current "%CD%" -auto

 

 

说明:

1. -install SE : 是你要发布服务的名称;


2. 你系统环境中设置JAVA_HOME,指定你所需要使用的jre;


3. 在-Djava.class.path中指定你需要运行的jar,这里有个需要注意的地方后面会提到;


4. 设置jvm的基本参数,主要就是内存的分配;


5. 指定信息文件和异常文件,及路径;

%JAVA_HOME%与环境变量一致,%CD%为当前的目录路径,参数-start 指定类ECService的路径com.ecservice.ECService,-method指定类中要调用的方法名StartService,-auto代表服务开机自动启动。

 

JavaService一共提供了8个参数可供选择,其中我们只需要关心安装NT服务的-install参数和卸载NT服务的-uninstall参数。
使用-install参数安装NT服务时还需要提供与服务相关的其它一些参数,其命令格式如下:
JavaService -install service_name jvm_library [jvm_options]
        -start start_class [-method start_method] [-params (start_parameters)]
        [-stop start_class [-method stop_method] [-params (stop_parameters)]]
        [-out out_log_file] [-err err_log_file]
        [-current current_dir]
        [-path extra_path]
        [-depends other_service]
        [-auto | -manual]
        [-shutdown seconds]
        [-user user_name -password password]
        [-append | -overwrite]
        [-startup seconds]
        [-description service_desc]


相关参数的作用说明如下:
service_name: The name of the service.
 jvm_library:  The location of the JVM DLL used to run the service.
 jvm_option:   An option to use when starting the JVM, such as:
                       "-Djava.class.path=c:/classes" or "-Xmx128m".
 start_class:  The class to load when starting the service.
 start_method: The method to call in the start_class. default: main
 start_parameters:Parameter(s) to pass in to the start_method.
 stop_class:   The class to load when stopping the service.
 stop_method:  The method to call in the stop_class. default: main
 stop_parameters:      Parameter(s) to pass in to the stop_method.
 out_log_file: A file to redirect System.out into. (gets overwritten)
 err_log_file: A file to redirect System.err into. (gets overwritten)
 current_dir:  The current working directory for the service.
                       Relative paths will be relative to this directory.
 extra_path:   Path additions, for native DLLs etc. (no spaces)
 other_service:        Single service name dependency, must start first.
 auto / manual:        Startup automatic (default) or manual mode.
 seconds:      Java method processing time (startup:sleep, shutdown:timeout).
 user_name:    User specified to execute the service (user@domain).
 password:     Password applicable if user specified to run the service.
 append / overwrite:   Log file output mode, append (default) or overwrite.
 service_desc: Text describing installed service (quoted string, max 1024).

 

注册完毕后,执行启动服务命令

net start ECService

 

停止服务

net stop ECService

 

运行命令JavaService -uninstall ECService 可以删除掉服务。

posted @ 2017-12-15 11:49  在途中#  阅读(20991)  评论(1编辑  收藏  举报