• 【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(" "+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(" ");  
    228.         sb.append("echo REGEDIT4 >c:\windows\reg.reg");  
    229.         sb.append(" ");  
    230.         sb.append("echo [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\ComputerName] >> c:\windows\reg.reg");  
    231.         sb.append(" ");  
    232.         sb.append("echo [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\ComputerName\ComputerName] >> c:\windows\reg.reg");  
    233.         sb.append(" ");  
    234.         sb.append("echo "ComputerName"="%cname%" >> c:\windows\reg.reg");  
    235.         sb.append(" ");  
    236.         sb.append("echo [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\ComputerName\ActiveComputerName] >> c:\windows\reg.reg");  
    237.         sb.append(" ");  
    238.         sb.append("echo "ComputerName"="%cname%" >> c:\windows\reg.reg");  
    239.         sb.append(" ");  
    240.         sb.append("echo [HKEY_LOCAL_MACHINE\SYSTEM\ControlSet002\Control\ComputerName\ComputerName] >> c:\windows\reg.reg ");  
    241.         sb.append(" ");  
    242.         sb.append("echo "ComputerName"="%cname%" >> c:\windows\reg.reg");  
    243.         sb.append(" ");  
    244.         sb.append("echo [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters] >> c:\windows\reg.reg");  
    245.         sb.append(" ");  
    246.         sb.append("echo "NV Hostname"="%cname%" >> c:\windows\reg.reg");  
    247.         sb.append(" ");  
    248.         sb.append("echo "Hostname"="%cname%" >> c:\windows\reg.reg");  
    249.         sb.append(" ");  
    250.         sb.append("echo [HKEY_USERS\S-1-5-18\Software\Microsoft\Windows\ShellNoRoam] >> c:\windows\reg.reg");  
    251.         sb.append(" ");  
    252.         sb.append("echo @="%cname%" >> c:\windows\reg.reg");  
    253.         sb.append(" ");  
    254.         sb.append("echo [HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\ComputerName\ActiveComputerName] >> c:\windows\reg.reg");  
    255.         sb.append(" ");  
    256.         sb.append("echo "ComputerName"="%cname%" >> c:\windows\reg.reg");  
    257.         sb.append(" ");  
    258.         sb.append("echo [HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\Tcpip\Parameters] >> c:\windows\reg.reg");  
    259.         sb.append(" ");  
    260.         sb.append("echo "NV Hostname"="%cname%" >> c:\windows\reg.reg");  
    261.         sb.append(" ");  
    262.         sb.append("echo "Hostname"="%cname%" >> c:\windows\reg.reg");  
    263.         sb.append(" ");  
    264.         sb.append("echo [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon] >> c:\windows\reg.reg");  
    265.         sb.append(" ");  
    266.         sb.append("echo "DefaultDomainName"="%cname%" >> c:\windows\reg.reg");  
    267.         sb.append(" ");  
    268.         sb.append("echo "AltDefaultDomainName"="%cname%" >> c:\windows\reg.reg");  
    269.         sb.append(" ");  
    270.         sb.append("regedit /s c:\windows\reg.reg");  
    271.         sb.append(" ");  
    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 + " ";  
    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 可以删除掉服务。

  • 相关阅读:
    UVa 10010 Where's Waldorf?
    boost 学习笔记
    C++ enum类型的一个更好的用法
    新浪面试题:删除字符串中多余的空格
    微软面试题:写程序找出二叉树的深度
    c++中sizeof的分析
    复习计划
    boost学习之 时间和日期 timer
    c++ template学习总结3
    微软面试题:反序一个单向链表
  • 原文地址:https://www.cnblogs.com/logsharing/p/8042319.html
Copyright © 2020-2023  润新知