文章目录
P1 服务器监视器 ChatRoomServerMonitor
在完成CSFramework后,现在基于CSFramework来完成一个聊天室,这个聊天室分为两部分,Server和Client,这里的Server和Client与CSFramework内的不同,这里的Server和Client是APP,是真正提供给用户使用的应用程序,一个良好的应用程序,应该有友善的界面且能够侦听用户的操作并作出反馈,程序要足够健壮,设计时,要考虑周全
最终效果:
1 监视窗口的初始化
现在先完成服务器监视窗口的初始化:
/**
* 服务器监视窗口窗口初始化
*/
@Override
public void init() {
this.jfrmView = new JFrame("雫-聊天室-服务器-监视器");
this.jfrmView.setMinimumSize(new Dimension(viewWidth, viewHeight));
//设置主窗口可以被最大化
this.jfrmView.setExtendedState(JFrame.MAXIMIZED_BOTH);
this.jfrmView.setLayout(new BorderLayout());
//设置默认居中
this.jfrmView.setLocationRelativeTo(null);
//设置点击右上关闭键无操作
this.jfrmView.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
//设置主标签
JLabel jlblTopic = new JLabel("雫-聊天室-服务器-监视器");
jlblTopic.setFont(topicFont);
jlblTopic.setForeground(topicColor);
this.jfrmView.add(jlblTopic, BorderLayout.NORTH);
//设置系统信息滑动框
this.jtatSystemMessage = new JTextArea();
this.jtatSystemMessage.setFont(normalFont);
JScrollPane jscpSystemMessage = new JScrollPane(this.jtatSystemMessage);
this.jfrmView.add(jscpSystemMessage, BorderLayout.CENTER);
//设置系统信息滑动框标题
TitledBorder ttbdSystemMessage = new TitledBorder("系统消息");
ttbdSystemMessage.setTitleFont(normalFont);
ttbdSystemMessage.setTitleColor(topicColor);
ttbdSystemMessage.setTitleJustification(TitledBorder.CENTER);
ttbdSystemMessage.setTitlePosition(TitledBorder.TOP);
jscpSystemMessage.setBorder(ttbdSystemMessage);
//设置命令输入框
JPanel jpnlFooter = new JPanel(new FlowLayout());
this.jfrmView.add(jpnlFooter, BorderLayout.SOUTH);
JLabel jlblCommand = new JLabel("命令");
jlblCommand.setFont(normalFont);
jpnlFooter.add(jlblCommand);
this.jtxtCommand = new JTextField(30);
this.jtxtCommand.setFont(normalFont);
jpnlFooter.add(this.jtxtCommand);
}
2 提供给用户选择的配置文件
在APP中,一些数据应该可以被用户修改,如连接的端口号,最大连接数量等,这些数据应该写到properties文件中,在服务器启动前先解析properties文件后,才能启动服务器,用户可以修改properties文件来更改服务器的一些属性,或者为用户提供合适的setter和getter方法:
properties文件:
解析properties文件:
/**
* 打开界面时解析配置文件
* 获取端口号和是否要自动打开服务器的信息
* 以及最大连接数
*/
public void initChatServer(String configPath) throws IOException, PropertiesNotFound {
PropertiesParser.loadProperties(configPath);
String strPort = PropertiesParser.getValue("port");
if(strPort != null && strPort.length() > 0) {
int port = Integer.valueOf(strPort);
setPort(port);
}
String strAutoStartUp = PropertiesParser.getValue("auto_startup");
if(strAutoStartUp != null && strAutoStartUp.length() > 0) {
boolean autoStartUp = Boolean.valueOf(strAutoStartUp);
this.autoStartUp = autoStartUp;
}
String strMaxClientCount = PropertiesParser.getValue("max_client_count");
if(strMaxClientCount != null && strMaxClientCount.length() > 0) {
this.setMaxChatCount(Integer.valueOf(strMaxClientCount));
}
}
3 侦听用户的操作
接下来需要完成对用户操作的侦听,完成交互式程序设计,服务器的管理员可以通过输入各种命令来进行对服务器的开机,关机等操作:
/**
* 侦听交互操作
*/
@Override
public void dealAction() {
//添加窗口侦听器,实现关闭主窗口操作
this.jfrmView.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
server.shutDown();
closeMonitor();
}
});
//添加命令文本框侦听器,实现命令的处理,回车后处理
this.jtxtCommand.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
//获取文本框中的命令
String command = jtxtCommand.getText().trim();
if(command.length() <= 0) {
ViewTool.showWarnning(jfrmView, "命令不能为空");
} else {
dealCommand(command);
}
jtxtCommand.setText("");
}
});
}
/**
* 处理输入的命令
*/
private void dealCommand(String command) {
if(command.equalsIgnoreCase("startup")
|| command.equalsIgnoreCase("s")) {
this.server.startUp();
} else if(command.equalsIgnoreCase("shutdown")
|| command.equalsIgnoreCase("d")) {
this.server.shutDown();
} else if(command.equalsIgnoreCase("forcedown")
|| command.equalsIgnoreCase("f")) {
this.server.forceDown();;
} else if(command.equalsIgnoreCase("exit")
|| command.equalsIgnoreCase("x")) {
closeMonitor();
}
}
4 将服务器监视器作为Listener接收CSFramework传来的信息
在CSFramework会话层内提到了Speaker和Listener,即将框架内需要输出信息的Server作为Speaker,将服务器APP作为Listener,框架向APP传递消息,实现了ISpeaker接口的就是Speaker,实现了IListener接口的就是Listener,且需要实现接口中的方法,这里需要让服务器监视器实现IListener,将框架传来的系统信息显示在服务器监视器上:
/**
* 初始化server,将本类加入听众列表
* 设置打开窗口自动启动为false
*/
public ChatRoomServerMonitor() {
this.server = new Server();
setPort(DEFAULT_PORT);
//将本类作为server的听众
this.server.addListener(this);
this.autoStartUp = false;
}
/**
* 本类作为Server的听众应该处理来自Server的消息
* 将server传来的消息显示到系统信息滑动框
*/
@Override
public void readMessage(String message) {
this.jtatSystemMessage.append(message + "\n");
this.jtatSystemMessage.setCaretPosition(this.jtatSystemMessage.getText().length());
}
5 弹窗提示 ViewTool
对于APP还应该对用户一些操作做出提示,如在服务器APP上,当服务器管理员需要对服务器关机时,但此时有客户端在线,此时就应该弹出窗口提示:
package com.my.util;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
public class ViewTool {
public static String TITLE_MESSAGE = "来自雫的提示";
public ViewTool() {
}
public static void showWarnning(JFrame parentView, String message) {
JOptionPane.showMessageDialog(parentView, message, TITLE_MESSAGE, JOptionPane.WARNING_MESSAGE);
}
public static void showError(JFrame parentView, String message) {
JOptionPane.showMessageDialog(parentView, message, TITLE_MESSAGE, JOptionPane.ERROR_MESSAGE);
}
public static void showInformation(JFrame parentView, String message) {
JOptionPane.showMessageDialog(parentView, message, TITLE_MESSAGE, JOptionPane.INFORMATION_MESSAGE);
}
public static int getUserChoice(JFrame parentView, String message) {
return JOptionPane.showConfirmDialog(parentView, message, TITLE_MESSAGE, JOptionPane.YES_NO_OPTION);
}
}
P2 启动服务器
1 启动类 ChatRoomServerMain
至此就完成了基于CSFramework的服务器监视器ChatRoomServerMonitor,接下来只需一个启动服务器开始侦听线程的类:
用户可以通过在命令文本框输入命令来管理服务器,同时框架内也会开始工作: