【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。

【JavaService】使用Java编写部署windows服务_第1张图片


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

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


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

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


接着编写一个Java工程

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

这里是工程结构:



代码:

package com.ecservice;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class ECService {
	private static Thread thread = null;
	private static Service service = null;

	/**
	 * 退出服务方法(该方法必须有参数 String [] args)
	 * 
	 * @param args
	 */
	public static void StopService(String[] args) {
		System.out.println(service.getLocalTime()+"停止服务");
		service.setRunFlag(false);
	}

	/**
	 * 启动服务方法(该方法必须有参数 String [] args)
	 * 
	 * @param args
	 */
	public static void StartService(String[] args) {
		// 产生服务线程
		service = new Service();
		thread = new Thread(service);
		System.out.println("\r\n"+service.getLocalTime()+"-----------启动服务-----------");
		
		try {
			// 将服务线程设定为用户线程,以避免StartService方法结束后线程退出
			thread.setDaemon(false);
			if (!thread.isDaemon()) {
				System.out.println(service.getLocalTime()+"成功设定线程为用户线程!");
			}
			// 启动服务线程
			thread.start();
		} catch (SecurityException se) {
			System.out.println(service.getLocalTime()+"线程类型设定失败!");
		}
	}

	public static void main(String[] args) {
		new Service().run();
//		ECService.StartService(null);
	}
}

class Service implements Runnable {
	private boolean runFlag = true;

	/**
	 * 设定服务线程运行标志值
	 * 
	 * @param runFlag
	 */
	public synchronized void setRunFlag(boolean runFlag) {
		this.runFlag = runFlag;
	}

	/**
	 * 取得服务线程运行标志值
	 * 
	 * @param void
	 */
	@SuppressWarnings("unused")
	private synchronized boolean getRunFlag() {
		return runFlag;
	}

	@Override
	public void run() {
		System.out.println(getLocalTime()+"服务线程开始运行");
		// while (getRunFlag()) {
		// 获取当前计算机名和MAC
		String hostName = getHostName();
		if (hostName != null) {
			System.out.println(getLocalTime()+"计算机名获取成功!");
			// 获取本机mac地址
			String localMac = getMac();
			if (localMac != null) {
				System.out.println(getLocalTime()+"mac获取成功!");	
				String mac = subMac(localMac);
				// 匹配本机计算机名与mac地址
				if (!hostName.equals(mac)) {
					System.out.println(getLocalTime()+"开始执行修改计算机名称。");
					// 执行修改计算机名
					// 生成一个bat批处理文件
					boolean isMakeBatSuccess = makeBat(mac);
					if(isMakeBatSuccess == true){
						System.out.println(getLocalTime()+"生成bat成功!");
						// 执行bat
						runCMD("C:\\ECService\\modify_hostname.bat");
						System.out.println(getLocalTime()+"执行bat完毕!");
						// 删除bat
						removeBat("C:\\ECService\\modify_hostname.bat");
						System.out.println(getLocalTime()+"执行删除bat完毕!");
						// 重启机器
						runCMD("shutdown -r -t 0");
						System.out.println(getLocalTime()+"执行修改计算机名操作完毕,系统正在重启。");
					}else{
						System.out.println(getLocalTime()+"生成bat失败!");
					}					
				} else {
					System.out.println(getLocalTime()+"本机计算机名与mac地址一致,不需要修改计算机名。");
				}
			} else {
				System.out.println(getLocalTime()+"获取本机mac地址失败!");
			}
		} else {
			System.out.println(getLocalTime()+"获取本机计算机名失败!");
		}

		// }
		System.out.println(getLocalTime()+"服务线程结束运行");
	}

	/**
	 * 获取计算机名称
	 * 
	 * @return
	 */
	public String getHostName() {		
		try {
			InetAddress inetAddress = InetAddress.getLocalHost();
			String hostName = "";
			hostName = inetAddress.getHostName();
			return hostName;
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			System.out.println(getLocalTime()+"获取计算机名称失败:" + e.getMessage());
		}
		return null;
	}

	/**
	 * 获取MAC地址
	 * 
	 * @return
	 */
	public String getMac() {
		NetworkInterface byInetAddress;
		try {
			InetAddress localHost = InetAddress.getLocalHost();
			byInetAddress = NetworkInterface.getByInetAddress(localHost);
			byte[] hardwareAddress = byInetAddress.getHardwareAddress();
			return getMacFromBytes(hardwareAddress);
		} catch (SocketException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			System.out.println(getLocalTime()+"获取mac地址失败:" + e.getMessage());
		} catch (UnknownHostException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			System.out.println(getLocalTime()+"获取mac地址失败:" + e.getMessage());
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			System.out.println(getLocalTime()+"获取mac地址失败:" + e.getMessage());
		}
		return null;
	}

	public String subMac(String mac) {
		String r = mac.substring(9, mac.length());
		return r;
	}

	public String getMacFromBytes(byte[] bytes) {
		StringBuffer mac = new StringBuffer();
		byte currentByte;
		boolean first = false;
		for (byte b : bytes) {
			if (first) {
				mac.append("-");
			}
			currentByte = (byte) ((b & 240) >> 4);
			mac.append(Integer.toHexString(currentByte));
			currentByte = (byte) (b & 15);
			mac.append(Integer.toHexString(currentByte));
			first = true;
		}
		return mac.toString().toLowerCase();
	}

	public boolean makeBat(String hostname) {
		boolean isSuccess = false;
		File file = new File("C:\\ECService\\modify_hostname.bat");
		try {
			file.createNewFile();
			StringBuilder sb = appendBat(hostname);
			String str = sb.toString();
			byte bt[] = new byte[1024];
			bt = str.getBytes();
			FileOutputStream in;
			in = new FileOutputStream(file);
			in.write(bt, 0, bt.length);
			in.close();
			isSuccess = true;
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return isSuccess;
	}

	public StringBuilder appendBat(String hostname) {
		StringBuilder sb = new StringBuilder();
		sb.append("set cname=" + hostname);
		sb.append("\r\n");
		sb.append("echo REGEDIT4 >c:\\windows\\reg.reg");
		sb.append("\r\n");
		sb.append("echo [HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\ComputerName] >> c:\\windows\\reg.reg");
		sb.append("\r\n");
		sb.append("echo [HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\ComputerName\\ComputerName] >> c:\\windows\\reg.reg");
		sb.append("\r\n");
		sb.append("echo \"ComputerName\"=\"%cname%\" >> c:\\windows\\reg.reg");
		sb.append("\r\n");
		sb.append("echo [HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\ComputerName\\ActiveComputerName] >> c:\\windows\\reg.reg");
		sb.append("\r\n");
		sb.append("echo \"ComputerName\"=\"%cname%\" >> c:\\windows\\reg.reg");
		sb.append("\r\n");
		sb.append("echo [HKEY_LOCAL_MACHINE\\SYSTEM\\ControlSet002\\Control\\ComputerName\\ComputerName] >> c:\\windows\\reg.reg ");
		sb.append("\r\n");
		sb.append("echo \"ComputerName\"=\"%cname%\" >> c:\\windows\\reg.reg");
		sb.append("\r\n");
		sb.append("echo [HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters] >> c:\\windows\\reg.reg");
		sb.append("\r\n");
		sb.append("echo \"NV Hostname\"=\"%cname%\" >> c:\\windows\\reg.reg");
		sb.append("\r\n");
		sb.append("echo \"Hostname\"=\"%cname%\" >> c:\\windows\\reg.reg");
		sb.append("\r\n");
		sb.append("echo [HKEY_USERS\\S-1-5-18\\Software\\Microsoft\\Windows\\ShellNoRoam] >> c:\\windows\\reg.reg");
		sb.append("\r\n");
		sb.append("echo @=\"%cname%\" >> c:\\windows\\reg.reg");
		sb.append("\r\n");
		sb.append("echo [HKEY_LOCAL_MACHINE\\SYSTEM\\ControlSet001\\Control\\ComputerName\\ActiveComputerName] >> c:\\windows\\reg.reg");
		sb.append("\r\n");
		sb.append("echo \"ComputerName\"=\"%cname%\" >> c:\\windows\\reg.reg");
		sb.append("\r\n");
		sb.append("echo [HKEY_LOCAL_MACHINE\\SYSTEM\\ControlSet001\\Services\\Tcpip\\Parameters] >> c:\\windows\\reg.reg");
		sb.append("\r\n");
		sb.append("echo \"NV Hostname\"=\"%cname%\" >> c:\\windows\\reg.reg");
		sb.append("\r\n");
		sb.append("echo \"Hostname\"=\"%cname%\" >> c:\\windows\\reg.reg");
		sb.append("\r\n");
		sb.append("echo [HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon] >> c:\\windows\\reg.reg");
		sb.append("\r\n");
		sb.append("echo \"DefaultDomainName\"=\"%cname%\" >> c:\\windows\\reg.reg");
		sb.append("\r\n");
		sb.append("echo \"AltDefaultDomainName\"=\"%cname%\" >> c:\\windows\\reg.reg");
		sb.append("\r\n");
		sb.append("regedit /s c:\\windows\\reg.reg");
		sb.append("\r\n");
		sb.append("exit");
		return sb;
	}

	public String runCMD(String commands) {
		String result = "";
		try {
			Process process = Runtime.getRuntime().exec(commands);
			BufferedReader errorReader = new BufferedReader(
					new InputStreamReader(process.getInputStream()));
			String line = null;
			while ((line = errorReader.readLine()) != null) {
				result += line + "\n";
			}
			errorReader.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}

	public void removeBat(String path) {
		File file = new File(path);
		if (file.exists()) {
			boolean isflag = file.delete();
			if (isflag == true){
				System.out.println(getLocalTime()+"删除bat成功!");
			}
			else {
				System.out.println(getLocalTime()+"删除bat失败!");
			}
		} else {
			System.out.println(getLocalTime()+"删除bat失败,批处理文件不存在!");
		}
	}
	
	public String getLocalTime(){
		String time ="[";
		SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		time += df.format(new Date()).toString();
		time+="]";
		return time;
	}

}

这里看主要代码:

public static void StartService(String[] args) {
  //启动服务的方法
}

public static void StopService(String[] args) {
  //停止服务的方法
}

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

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

【JavaService】使用Java编写部署windows服务_第2张图片

Finish

【JavaService】使用Java编写部署windows服务_第3张图片


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

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

【JavaService】使用Java编写部署windows服务_第4张图片

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


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

【JavaService】使用Java编写部署windows服务_第5张图片


然后执行命令

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

【JavaService】使用Java编写部署windows服务_第6张图片

说明:

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

【JavaService】使用Java编写部署windows服务_第7张图片


停止服务

net stop ECService

【JavaService】使用Java编写部署windows服务_第8张图片


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

【JavaService】使用Java编写部署windows服务_第9张图片

你可能感兴趣的:(Java)