您的位置:首页 > 运维架构 > Linux

Linux DNS服务搭建1

2013-10-29 14:18 295 查看
最近工作中碰到这个问题,用Java写的一个系统托盘,要求只能有一个实例,当再次启动程序的时候,需要激活并显示已经启动的实例。

网上搜了一下,一个实例的问题网上已经有解决办法(使用文件锁),激活前一个实例的问题却没有头绪,有人说用Win32 API,但搜了好多,搜到的都是VB,VC++等来实现的,没有用Java的;还有一个方法是使用Socket,这个尝试了下,确实可行,但缺点是需要占用一个端口。

这里我把两个问题写到一个例子里,供有需要的朋友参考:

其中:有一个系统托盘实例:SystemTray tray;一个窗体对象:JFrame frame;

在启动系统托盘的main()方法里,代码如下:

public class AppTest {
private JFrame frame;               //窗体
private SystemTray tray;            //系统托盘
private MyServer server;    //服务端socket
public AppTest() {
init();
}
private void init(){
//如果当前操作系统不支持系统托盘,则退出
if(!SystemTray.isSupported()){
JOptionPane.showMessageDialog(null, "对不起,当前操作系统不支持系统托盘!");
System.exit(0);
}
tray = SystemTray.getSystemTray();
Image image = null;
try {
image = ImageIO.read(this.getClass().getClassLoader().getResourceAsStream("com/blog/icons.png"));
} catch (IOException e) {
JOptionPane.showMessageDialog(null, e.getMessage());
System.exit(0);
}
final TrayIcon trayIcon = new TrayIcon(image);
try {
tray.add(trayIcon);
} catch (AWTException e) {
JOptionPane.showMessageDialog(null, e.getMessage());
System.exit(0);
}
PopupMenu menu = new PopupMenu();
MenuItem mi = new MenuItem("Exit");
mi.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
frame.setVisible(false);
frame.dispose();
frame = null;
tray.remove(trayIcon);
tray = null;
server.closeServer();
System.exit(0);
}
});
menu.add(mi);
trayIcon.setPopupMenu(menu);

frame = new JFrame("AppTest");
frame.setSize(new Dimension(200, 200));
frame.setVisible(true);
}
/**
* 显示/隐藏 主窗体
* */
public void showHideFrame(boolean isVisible){
frame.setVisible(isVisible);
frame.setExtendedState(JFrame.NORMAL);
}

/**
* 注入server对象,关闭server时使用
* @param server
*/
public void setServerSocket(MyServer server){
this.server = server;
}
//检查是否获得锁,true:获得锁,说明是第一次执行;false:没有取得锁,说明已经有一个程序在执行
public static boolean checkLock() {
FileLock lock = null;
RandomAccessFile r = null;
FileChannel fc = null;
try {
// 在临时文件夹创建一个临时文件,锁住这个文件用来保证应用程序只有一个实例被创建.
File sf = new File(System.getProperty("java.io.tmpdir") + "lock.single");
sf.deleteOnExit();
sf.createNewFile();
r = new RandomAccessFile(sf, "rw");
fc = r.getChannel();
lock = fc.tryLock();
if (lock == null||!lock.isValid()) {
// 如果没有得到锁,则程序退出.
// 没有必要手动释放锁和关闭流,当程序退出时,他们会被关闭的.
return false;
}
} catch (Exception e) {
e.printStackTrace();
}
return true;
}
public static void main(String[] args) {
//检查文件锁,确保只有一个实例运行
if(!checkLock()){
//告知上一个程序激活主窗口
try {
new Socket(InetAddress.getLocalHost(),60098);
} catch (Exception e) {
e.printStackTrace();
}
//退出当前程序
System.exit(0);
}

AppTest app = new AppTest();
new MyServer(app);
}

static class MyServer{
private ServerSocket server;//当前的socket
private AppTest tray;       //保存的前一个托盘实例
public MyServer(AppTest tray) {
this.tray = tray;
tray.setServerSocket(this);
initServerSocket();
}
private void initServerSocket(){
try {
server = new ServerSocket(60098);
while(true){
if(server.isClosed()){
break;
}
//如果监听到一个socket连接,说明程序启图再次打开一个实例,此时显示前一个窗体
Socket socket = server.accept();
tray.showHideFrame(true);
socket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
public void closeServer(){
try {
server.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
本文出自 “Crazy_Programmer” 博客,请务必保留此出处http://handd.blog.51cto.com/2796632/1144569
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: