本项目已经通过git进行版本管理,checkout:http://github.com/lettoo/orion
项目要实现一个java后台程序,提供start(),stop()和status()的方法。
主要的原理是:有一个Server类运行在localhost:xxxx上,当成一个RMI service,这个Server类里有一个Service List,通过Spring注入的方式,向其中注入Service,当然,也可以通过编程方式动态往里面加Service,因为项目比较简单,直接通过Spring配置已经满足要求。RMI 客户端通过调用Server.start(),遍历Service List中的service,一个个启动起来。客户端调用stop(),则遍历Service List中的server,一个个关闭,最终再关闭服务端。status()方法只是简单的提供Server是否在运行状态。
1. Server接口
public interface IServer {
void start() throws Exception;
void stop() throws Exception;
boolean isStarted();
}
2. Server实现类
import java.util.LinkedList;
import java.util.List;
public class ServerImpl implements IServer {
private volatile boolean isStarted = false;
private List<IService> serviceList = new LinkedList<IService>();
public void setServiceList(List<IService> serviceList) {
this.serviceList = serviceList;
}
@Override
public void start() throws Exception {
if (isStarted) {
return;
}
for (IService service : serviceList) {
service.start();
}
isStarted = true;
}
@Override
public void stop() throws Exception{
for (IService service : serviceList) {
service.stop();
}
isStarted = false;
System.exit(0);
}
@Override
public boolean isStarted() {
return isStarted;
}
}
3. 通过Spring RMI,分别创建两个xml,一个是server.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING/DTD BEAN/EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean id="server" class="cn.lettoo.server.ServerImpl"> <property name="serviceList"> <list> <!-- Add your service here, all service implements IService interface. --> <ref bean="jmsService" /> <ref bean="jobService" /> <ref bean="dataReaderService" /> </list> </property> </bean> <bean id="orionMonitorServer" class="org.springframework.remoting.rmi.RmiServiceExporter"> <property name="serviceInterface" value="cn.lettoo.server.IServer" /> <property name="service" ref="server" /> <property name="serviceName" value="OrionMonitorServer" /> <property name="registryPort" value="1199" /> <property name="alwaysCreateRegistry" value="true" /> </bean> </beans>
再创建一个client.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING/DTD BEAN/EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean id="serviceProxy" class="org.springframework.remoting.rmi.RmiProxyFactoryBean"> <property name="serviceUrl" value="rmi://localhost:1199/OrionMonitorServer" /> <property name="serviceInterface" value="cn.lettoo.server.IServer" /> </bean> </beans>
4. 写一个Luncher类,通过RMI来调用Server的方法
import org.apache.commons.cli.BasicParser;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Options;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Launcher {
/** The Constant USAGE. */
private static final String USAGE = "[options]";
/** The Constant HEADER. */
private static final String HEADER = "Options:";
/** The Constant FOOTER. */
private static final String FOOTER = "For more instructions, please contact golettoo@gmail.com";
private IServer server;
private static Log logger = LogFactory.getLog(Launcher.class);
public static void main(String args[]) {
Launcher launcher = new Launcher();
try {
launcher.execute(args);
} catch (Exception e) {
launcher.printUsage(launcher.createOptions());
logger.error("launch error: ", e);
System.exit(1);
}
}
private void execute(String[] args) throws Exception {
CommandLineParser parser = new BasicParser();
Options options = createOptions();
CommandLine commandLine = parser.parse(options, args);
if (commandLine.hasOption('h')) {
printUsage(options);
return;
}
if (commandLine.hasOption('v')) {
System.out.println("Version: 1.0");
return;
}
if (args.length == 0) {
start();
} else if (commandLine.hasOption("start")) {
start();
} else if (commandLine.hasOption("stop")) {
stop();
} else if (commandLine.hasOption("status")) {
System.out.println("Status: " + getStatus());
} else {
printUsage(options);
}
}
private void initServer() throws Exception {
ApplicationContext context =
new ClassPathXmlApplicationContext(new String[] { "server.xml" });
}
private void initClient() throws Exception {
ApplicationContext context =
new ClassPathXmlApplicationContext(new String[] { "client.xml" });
this.server = (IServer) context.getBean("serviceProxy");
}
private void start() throws Exception {
initServer();
initClient();
server.start();
}
private void stop() {
try {
initClient();
server.stop();
} catch (Exception e) {
logger.error("Stop server error: " + e.toString());
}
}
private String getStatus() {
try {
initClient();
return server.isStarted() ? "started" : "stopped";
} catch (Exception e) {
logger.error("Get server status error: " + e.toString());
}
return "stopped";
}
private void printUsage(Options options) {
HelpFormatter helpFormatter = new HelpFormatter();
helpFormatter.printHelp(USAGE, HEADER, options, FOOTER);
}
private Options createOptions() {
Options options = new Options();
options.addOption("h", "help", false, "print this usage information");
options.addOption("o", "option", true, "set option");
options.addOption("v", "version", false, "print version");
options.addOption("start", false, "start the application");
options.addOption("stop", false, "stop the application");
options.addOption("status", false, "print the status information");
return options;
}
}
Luncher类通过运行时的参数来决定是start还是stop,另外,还提供了一个帮助和版本信息的查看
现在可以通过运行Luncher -start来启动这个server了
再通过Luncher -status来看状态
通过Luncher -stop来关闭server