java入口程序代码-服务器有界面,可视化操作的分析及知识点分析
Java小程序之服务器的UI实现
1、前言:
前面我们做的服务器都是没有界面的,只是利用简单的输入输出语句在控制台中打印语句;今天,我们要让服务器有界面,可视化操作;
2、UI功能需求:
3、知识点分析:
JTable使用:TableModel和JScrollPane、Vector
JTable:可以理解为表示数据的展现组件
TableModel:用于封装数据组件
Vector: 队列
代码框架
4、具体实现思路
1、先实现全部界面UI(功能暂时不着急)这里主要是JTable的使用,刚开始启动按钮和关闭按钮都不能操作
2、最上方功能按钮的实现,当界面初始化的时候,用1个线程开始不断检测输入框中是不是有内容,有内容则启动按钮可操作;启动按钮启动后,创建服务器对象,等待客户真个连接,并将启动按钮再次设置为不可操作,而关闭按钮设置为可操作;
3、获得客户端输入的账户和密码,服务器校验成功后,将该账号的相干信息进行封装,将封装好的信息加到Table中显示
4、显示聊天功能,消息内容昨天实在控制台中打印的java入口程序代码,这次,我们这要将从客户端接收到的消息放在服务器界面UI中显示便可;
5、源代码:
源代码结构图:
com.huaxin.server包:
MyServer类:(甚么时候启动服务器?当点击启动按钮时,履行者下面的代码)
package com.huaxin.server; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.BindException; import java.net.ServerSocket; import java.net.Socket; import java.net.SocketException; import java.util.ArrayList; import javax.swing.JOptionPane; import com.huaxin.UI.InfoPanel; import com.huaxin.UI.TablePanel; public class MyServer { public static ArrayListserverList = new ArrayList (); public int port; public ServerSocket server; private TablePanel tablePanel; private InfoPanel infoPanel; public MyServer(int port, TablePanel tablePanel, InfoPanel infoPanel) { this.port=port; this.tablePanel=tablePanel; this.infoPanel=infoPanel; } //启动服务器 public void startServer(){ try { //创建服务器对象 server = new ServerSocket(port); System.out.println("服务器已启动......"); while(true){ //服务器连接客户端,阻塞方法 Socket socket=server.accept(); System.out.println("有客户端连进来了......"); ServerThread st = new ServerThread(socket,tablePanel,infoPanel); st.start(); serverList.add(st); } } catch (BindException e) { JOptionPane.showMessageDialog(null, "端口号已占用!请重新启动服务器并输入新的端口号!"); System.exit(0); } catch (SocketException e) { JOptionPane.showMessageDialog(null, "服务器已关闭....."); } catch (Exception e) { e.printStackTrace(); } } public void sendMsgToClient(String s) { for (int i = 0; i ServerThread类:
package com.huaxin.server; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Vector; import com.huaxin.UI.InfoPanel; import com.huaxin.UI.TablePanel; import javafx.scene.control.TabPane; public class ServerThread extends Thread { public Socket socket; public InputStream ins; public OutputStream os; public String str; public String name; public String pwd; private TablePanel tablePanel; private InfoPanel infoPanel; public ServerThread(Socket socket, TablePanel tablePanel, InfoPanel infoPanel) { this.socket = socket; this.tablePanel=tablePanel; this.infoPanel=infoPanel; } public void run() { Vectorvs=null; try { // 获得输入输出流 ins = socket.getInputStream(); os = socket.getOutputStream(); str = "welcome to zhou's Server"; // 向客户端输出信息 sendMsg(os, str); os.flush(); /************客户端登录和验证****************/ //获得客户端输入的账户和密码 getMsg(); //账号和密码校验 boolean falg =loginCheck(); //校验不通过时,循环校验 while(!falg){ str="Fail to connect server......"; sendMsg(os, str); os.flush(); str="please check your name and password and login again....."; sendMsg(os, str); os.flush(); getMsg(); falg =loginCheck(); } //校验成功后:开始聊天 str="successful connected..... you can chat with your friends now ......"; // str="yes"; sendMsg(os, str); os.flush(); //登录成功后,将用户名,ip地址和登录时间加到TabelPanel中的Table中 //先获得到TabelPanel中的Table对象,1层1层传递过来 String ip =socket.getRemoteSocketAddress().toString(); Date date = new Date(); SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String currentTime =sdf.format(date); //封装用户名,ip地址和时间 vs = new Vector (); vs.add(name); vs.add(ip); vs.add(currentTime); //将封装好的vs加入到tablePanel面板的table中,并刷新面板 tablePanel.data.add(vs); tablePanel.table.updateUI(); // 接受客户真个信息 String s = readMsg(ins); while (!s.equals("bye")) { //在消息框中显示发送的信息 infoPanel.jta.append(name+" say:"+s+"\r\n"); for (int i = 0; i < MyServer.serverList.size(); i++) { //群发消息 ServerThread st = MyServer.serverList.get(i); //不给自己发消息 if (st == this) continue; OutputStream ous =st.socket.getOutputStream(); sendMsg(ous,name+" say:"+s); os.flush(); } //循环读取信息 s = readMsg(ins); } // server.close(); } catch (Exception e) { // e.printStackTrace(); System.out.println("客户端不正常退出......"); } //关闭客户端后,将该用户的记录从向量队里中移除,并刷新面板 if(vs!=null){ this.tablePanel.data.remove(vs); this.tablePanel.table.updateUI(); } // 关闭流、服务器、套接字 try { ins.close(); os.close(); socket.close(); MyServer.serverList.remove(this); } catch (IOException e) { // System.out.println("这个地方有毛病......"); e.printStackTrace(); } } //发送消息的函数 public void sendMsg(OutputStream os, String s) throws IOException { // 向客户端输出信息 // byte[] bytes = s.getBytes(); os.write(bytes); os.write(13); os.write(10); os.flush(); } //读取客户端输入数据的函数 public String readMsg(InputStream ins) throws Exception { // 读取客户真个信息 int value = ins.read(); // 读取整行 读取到回车(13)换行(10)时停止读 String str = ""; while (value != 10) { //点击关闭客户端时会返回⑴值 if(value ==⑴){ throw new Exception(); } str = str + ((char) value); value = ins.read(); } str = str.trim(); return str; } //获得客户端账号和密码的函数 public void getMsg() throws Exception { str="please enter your name :"; sendMsg(os, str); os.flush(); name =readMsg(ins); str="please enter your password :"; sendMsg(os, str); os.flush(); pwd =readMsg(ins); } //校验客户端输入的账号和密码的函数 public boolean loginCheck() throws Exception{ if(name.equals("zhou") && pwd.equals("zhou") || name.equals("user") && pwd.equals("pwd") || name.equals("huaxinjiaoyu") && pwd.equals("huaxinjiaoyu")){ return true; } return false; } } com.huaxin.UI包:
(该包分为将全部面板的3个区域分出了3个类,在UIFrame中创建该3个类,并整合3个类,到达上图的整体效果)
StartPanel类:(最上面的面板类)
package com.huaxin.UI; import java.awt.Color; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.IOException; import javax.swing.JButton; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JTextField; import com.huaxin.server.MyServer; import com.huaxin.server.ServerThread; public class StartPanel extends JPanel{ public JTextField jtf; public JButton startBtn; public JButton stoptBtn; public boolean flag=true; public MyServer ms ; public TablePanel tablePanel; public InfoPanel infoPanel; /* * 最上面的面板类 */ public StartPanel(TablePanel tablePanel, InfoPanel infoPanel) { this.tablePanel=tablePanel; this.infoPanel=infoPanel; //创建相干组件 JLabel label =new JLabel("端口号"); jtf = new JTextField(10); startBtn = new JButton("启动服务"); //设置按钮不可操作 startBtn.setEnabled(false); stoptBtn = new JButton("关闭服务"); stoptBtn.setEnabled(false); //设置背景色彩 this.setBackground(Color.green); //设置面板大小 this.setPreferredSize(new Dimension(0,50)); this.setLayout(new FlowLayout()); //组件添加 this.add(label); this.add(jtf); this.add(startBtn); this.add(stoptBtn); //给两个按钮添加监听器 startBtn.addActionListener(al); stoptBtn.addActionListener(al); //检测输入框是不是为空 checkText(); } //按钮监听器的具体实现 ActionListener al = new ActionListener() { public void actionPerformed(ActionEvent e) { String command =e.getActionCommand(); if(command.equals("启动服务")){ //启动服务的相干逻辑操作 flag=false; int port =Integer.parseInt(jtf.getText()); ms = new MyServer(port,tablePanel,infoPanel); infoPanel.ms=ms; stoptBtn.setEnabled(true); startBtn.setEnabled(false); //用线程处理,避免阻塞 new Thread(){ public void run() { ms.startServer(); }; }.start(); }else if(command.equals("关闭服务")){ try { // flag=true; //关闭服务逻辑实现 //移除所有的客户端 while(ms.serverList.size()!=0) { ms.serverList.get(0).socket.close(); ms.serverList.remove(0); } //服务器关闭 ms.server.close(); //设置按钮可操作属性 stoptBtn.setEnabled(false); startBtn.setEnabled(true); } catch (IOException e1) { e1.printStackTrace(); } } } }; //线程检测文本输入框是不是有输入 public void checkText(){ new Thread(){ public void run() { while(flag){ //获得文本输入框的信息 String info=jtf.getText(); //信息不为空或"",则可以启动服务器 if(!(info==null || info.equals(""))){ startBtn.setEnabled(true); } try { this.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } } }; }.start(); } }TablePanel类:登录用户信息显示面板
package com.huaxin.UI; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.util.Vector; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.table.DefaultTableModel; public class TablePanel extends JPanel { public JTable table; public Vector> data; public TablePanel() { //设置面板属性 this.setPreferredSize(new Dimension(450,0)); this.setBackground(Color.white); this.setLayout(new BorderLayout()); //创建表格 Vector colNames = new Vector (); colNames.add("用户名"); colNames.add("IP地址"); colNames.add("登录时间"); data =new Vector >(); Vector vs=new Vector (); //创建表格模型 DefaultTableModel tm =new DefaultTableModel(data, colNames); table = new JTable(tm); //创建转动条 JScrollPane jsp =new JScrollPane(table); this.add(jsp); } } InfoPanel类:聊天信息显示面板
package com.huaxin.UI; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JButton; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.JTextField; import com.huaxin.server.MyServer; public class InfoPanel extends JPanel{ public MyServer ms ; public JTextArea jta; public JTextField jtf; public InfoPanel() { //设置信息面板的属性 this.setPreferredSize(new Dimension(350,0)); this.setBackground(Color.blue); this.setLayout(new BorderLayout()); //文本输入域 jta = new JTextArea(); //设置自动换行 jta.setLineWrap(true); JScrollPane jsp = new JScrollPane(jta); this.add(jsp); //面板底部的发送面板 jtf = new JTextField(25); JButton btn = new JButton("发送"); //发送按钮添加监听器 btn.addActionListener(al); JPanel panel=new JPanel(); panel.setLayout(new FlowLayout()); this.add(panel,BorderLayout.SOUTH); panel.add(jtf); panel.add(btn); } //监听具体实现 ActionListener al = new ActionListener() { public void actionPerformed(ActionEvent e) { //获得内容 String s=jtf.getText(); //为空的提示信息 if( s==null || "".equals(s)){ JOptionPane.showMessageDialog(null, "输入框不能为空!"); } else if(ms.server.isClosed()){ JOptionPane.showMessageDialog(null, "服务器已关闭,不能发送消息!"); }else{ try { //不为空,则将消息发送给服务器,服务器转发给消息给每一个客户端 ms.sendMsgToClient(s); //清空文本 jtf.setText(""); } catch (Exception e1) { e1.printStackTrace(); } } } }; }UIFrame类:程序入口和面板整合类:
package com.huaxin.UI; import java.awt.BorderLayout; import javax.swing.JFrame; /* * 服务器后台界面类 */ public class UIFrame extends JFrame { public TablePanel tablePanel; public InfoPanel infoPanel ; public static void main(String[] args) { UIFrame ui = new UIFrame(); ui.initFrame(); } public void initFrame() { // 设置窗体的相干属性 this.setSize(800, 600); this.setTitle("服务器后台界面"); this.setDefaultCloseOperation(3); this.setLocationRelativeTo(null); this.setLayout(new BorderLayout()); tablePanel = new TablePanel(); infoPanel = new InfoPanel(); StartPanel startPanel = new StartPanel(tablePanel,infoPanel); //在主页面中添加3个面板 this.add(startPanel,BorderLayout.NORTH); this.add(tablePanel, BorderLayout.CENTER); this.add(infoPanel, BorderLayout.EAST); this.setVisible(true); } }6、运行结果:
先启动界面UI类,输入9090点击启动服务,开启服务器,服务器1定要先打开,否则客户端没法连接
利用系统自带的telnet客户端,启动客户端
输入正确的密码进行登录:
当有用户登录进来后的界面显示效果:
以一样的方法开启另外客户端
界面UI小时效果:
在3个客户端分别输入聊天消息:
界面UI显示效果:
测试系统发送功能:(在信息面板中的发送按钮添加监听)
7、总结:
1、不要着急,1步1步实现
2、服务那边的代码可以参看昨天的博客;
3、把界面的单个部份分成3个类出去实现java入口程序代码,最后在1个类中创建3个类的对象,并将3个对象在该类中整合
4、1定依照思路来,越急躁的人越回1通乱来
个人经验分享:之前我也尝试照着书中的代码1句1句去敲,先把1个类的代码敲完,再去敲另外一个了类的代码,其实这样是非常不好的,我们写代码的时候也不是1口气就把1个类的代码全部写完,同时,定义的变量也不是1下就可以想到要那末多的变量,只是在我们需要的时候去定义某个变量;所以,写程序,思路真的非常非常重要;我把源代码都贴上来,也不是让某些人直接copy拿去交作业(固然,有部份人肯定是直接copy的),更重要的是帮助那些自学的朋友在某个地方卡壳的时候,参看1下的代码,能顺时顿悟;而浪费太多没必要要的时间;最最重要的是能和大家1起学习讨论和交换;嗯,相信我的意思大家都明白!
共勉!
------分隔线----------------------------
上一篇 Java的动态代理机制及Spring的实现方式
下一篇 大数据究竟是什么?一篇文章让你认识并读懂大数据
------分隔线----------------------------