線上聊天項目1.4版 使用Gson方法解析Json字元串以便重構request和response的各種請求和響應 解決聊天不暢問題 Gson包下載地址

来源:http://www.cnblogs.com/qingyundian/archive/2017/12/25/8100363.html
-Advertisement-
Play Games

線上聊天項目結構圖: 多用戶登陸效果圖: 多用戶聊天效果圖: 資料庫效果圖: 重新構建了Server類,使用了Gson方法,通過解析Json字元串,增加Info類,簡化判斷過程。 Server類代碼如下: 新增的工具類Info,通過info對象的get方法把獲得服務端得到的各種字元串直接歸類了。 I ...


線上聊天項目結構圖:

多用戶登陸效果圖:

多用戶聊天效果圖:

資料庫效果圖:


重新構建了Server類,使用了Gson方法,通過解析Json字元串,增加Info類,簡化判斷過程。

Server類代碼如下:

package com.swift.server;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.IOException;
import java.net.BindException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;

import com.google.gson.Gson;
import com.swift.jdbc.DBAdd;
import com.swift.jdbc.DBLogin;
import com.swift.other.User;
import com.swift.util.Info;

public class Server {

    boolean started = false;
    ServerSocket ss = null;
    Socket s = null;
    List<Client> clients = new ArrayList<Client>();
    Vector<String> list = new Vector<String>();

    public static void main(String[] args) {
        new Server().fun();
    }

    private void fun() {
        try {
            ss = new ServerSocket(8888);
            started = true;
        } catch (BindException e) {
            System.out.println("埠使用中......");
        } catch (IOException e1) {
            e1.printStackTrace();
        }
        try {
            while (started) {
                s = ss.accept();
                System.out.println("a client connected success");
                Client c = new Client(s);
                clients.add(c);
                new Thread(c).start();

            }
        } catch (EOFException e) {
            System.out.println("client has closed.");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                ss.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

    class Client implements Runnable {

        public Socket s;
        public DataInputStream dis;
        public DataOutputStream dos;
        private boolean connected = false;

        public Client(Socket s) {
            this.s = s;
            try {
                this.dis = new DataInputStream(s.getInputStream());
                this.dos = new DataOutputStream(s.getOutputStream());
                connected = true;
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void run() {
            try {
                while (connected) {
                    // 接收客戶端請求
                    String json = dis.readUTF();
                    Gson gson = new Gson();
                    Info info = gson.fromJson(json, Info.class);
                    if (info.getState().equals("login")) {

                        String phone = info.getPhone();
                        String password = info.getPassword();
                        System.out.println(phone);
                        System.out.println(password);

                        User user = new User(phone, password);
                        boolean login = DBLogin.login(user);
                        if (login) {
                            dos.writeUTF("success");
                            dos.flush();
                            String userName = dis.readUTF();
                            // 添加進好友列表Vector
                            list.addElement(userName);

                            System.out.println();
                            // 每當有成功登陸就向各個客戶端發送完整列表
                            for (int i = 0; i < clients.size(); i++) {
                                Client c = clients.get(i);
                                System.out.println(c.s.getPort());
                                for (int j = 0; j < list.size(); j++) {
                                    String name = list.get(j);
                                    System.out.println(name);
                                    String json_name = "{\"state\":\"friends\",\"msg\":\"" + name + "\"}";
                                    c.send(json_name);
                                }
                            }

                        } else {
                            dos.writeUTF("fail");
                            dos.flush();
                        }

                    } else if (info.getState().equals("reg")) {
                        String phone = info.getPhone();
                        String password = info.getPassword();
                        System.out.println(phone);
                        System.out.println(password);

                        User user = new User(phone, password);
                        boolean flag = DBAdd.add(user);
                        if (flag) {
                            dos.writeUTF("success");
                        }else {
                            dos.writeUTF("fail");
                        }
                    } else if (info.getState().equals("chat")) {
                        System.out.println(json);
                        for (int i = 0; i < clients.size(); i++) {
                            Client c = clients.get(i);
                            c.send(json);
                        }
                    }

                }
            } catch (SocketException e) {
                System.out.println("一個登陸窗已經關閉....");
            } catch (EOFException e) {
                System.out.println("a client has been closed,can't read message from it.");
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (s != null) {
                    try {
                        s.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if (dis != null) {
                    try {
                        dis.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if (dos != null) {
                    try {
                        dos.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }

        private void send(String str) {
            try {
                this.dos.writeUTF(str);
                this.dos.flush();
            } catch (SocketException e) {
                clients.remove(this);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
}

新增的工具類Info,通過info對象的get方法把獲得服務端得到的各種字元串直接歸類了。

Info類代碼如下:

package com.swift.util;

public class Info {
    private String state;
    private String msg;
    private String phone;
    private String password;
    public String getPhone() {
        return phone;
    }
    public void setPhone(String phone) {
        this.phone = phone;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public String getState() {
        return state;
    }
    public void setState(String state) {
        this.state = state;
    }
    public String getMsg() {
        return msg;
    }
    public void setMsg(String msg) {
        this.msg = msg;
    }
    
}

重構了登陸視窗的登陸和註冊請求

登陸視窗的代碼如下:

package com.swift.frame;

import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ConnectException;
import java.net.Socket;

import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.TitledBorder;

import com.swift.util.Center;

public class LoginDialog extends JDialog {

    private static final long serialVersionUID = 1L;
    private JPasswordField passwordField_2;
    private JPasswordField passwordField_1;
    private JTextField textField_2;
    private JTextField textField;

    Socket s;
    DataOutputStream dos;
    DataInputStream dis;

    public static void main(String args[]) {
        JFrame.setDefaultLookAndFeelDecorated(true);
        JDialog.setDefaultLookAndFeelDecorated(true);

        try {
            UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel");
        } catch (ClassNotFoundException e1) {
            e1.printStackTrace();
        } catch (InstantiationException e1) {
            e1.printStackTrace();
        } catch (IllegalAccessException e1) {
            e1.printStackTrace();
        } catch (UnsupportedLookAndFeelException e1) {
            e1.printStackTrace();
        }

        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    LoginDialog dialog = new LoginDialog();
                    dialog.addWindowListener(new WindowAdapter() {
                        public void windowClosing(WindowEvent e) {
                            System.exit(0);
                        }
                    });
                    dialog.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    public LoginDialog() {
        super();
        setResizable(false);
        setTitle("線上聊天登錄框");
        getContentPane().setLayout(null);
        setBounds(100, 100, 427, 301);// 註冊時高度為578,不註冊是301

        // 設置視窗居中
        this.setLocation(Center.getPoint(this.getSize()));

        final JTextField textField_1 = new JTextField();
        textField_1.setBounds(148, 90, 192, 42);
        getContentPane().add(textField_1);

        final JLabel label = new JLabel();
        label.setText("帳    號");
        label.setBounds(76, 102, 66, 18);
        getContentPane().add(label);

        final JLabel label_1 = new JLabel();
        label_1.setText("密    碼");
        label_1.setBounds(76, 167, 66, 18);
        getContentPane().add(label_1);

        final JPasswordField passwordField = new JPasswordField();
        passwordField.setBounds(148, 155, 192, 42);
        getContentPane().add(passwordField);

        final JButton button_1 = new JButton();
        button_1.addActionListener(new ActionListener() {
            public void actionPerformed(final ActionEvent e) {

                String phone = new String(textField_1.getText()).trim();
                String password = new String(passwordField.getPassword()).trim();
                if (!phone.equals("") && !password.equals("")) {
                    try {
                        String json_login = "{\"state\":\"login\",\"phone\":\"" + phone + "\",\"password\":\""
                                + password + "\"}";
                        dos.writeUTF(json_login);
                        dos.flush();
                        String flag = dis.readUTF();
                        if (flag.equals("success")) {
                            javax.swing.JOptionPane.showMessageDialog(LoginDialog.this, "登錄成功");
                            // 把登陸成功的用戶發送給服務端,作為好友列表信息
                            dos.writeUTF(phone);
                            dos.flush();
                            // 登陸窗消失
                            LoginDialog.this.dispose();
                            // 好友列表窗出現
                            new FriendsFrame(phone, s);

                        } else if (flag.equals("fail")) {
                            javax.swing.JOptionPane.showMessageDialog(LoginDialog.this, "登錄失敗");
                        }
                    } catch (IOException e1) {
                        e1.printStackTrace();
                    }
                } else {
                    javax.swing.JOptionPane.showMessageDialog(LoginDialog.this, "用戶名密碼必須填寫...");
                    return;
                }
            }
        });
        button_1.setText("登錄");
        button_1.setBounds(230, 222, 106, 36);
        getContentPane().add(button_1);

        final JButton button = new JButton();
        button.addActionListener(new ActionListener() {
            public void actionPerformed(final ActionEvent e) {
                if (LoginDialog.this.getHeight() == 301) {
                    LoginDialog.this.setSize(427, 578);
                } else {
                    LoginDialog.this.setSize(427, 301);
                }
                // 設置視窗不斷居中
                LoginDialog.this.setLocation(Center.getPoint(LoginDialog.this.getSize()));
            }
        });
        button.setText("註冊");
        button.setBounds(76, 222, 106, 36);
        getContentPane().add(button);

        final JPanel panel = new JPanel();
        panel.setLayout(null);
        panel.setBorder(new TitledBorder(null, "註冊用戶", TitledBorder.DEFAULT_JUSTIFICATION,
                TitledBorder.DEFAULT_POSITION, null, null));
        panel.setBounds(10, 278, 401, 226);
        getContentPane().add(panel);

        final JLabel label_2 = new JLabel();
        label_2.setBounds(44, 41, 65, 18);
        label_2.setText("手機號:");
        panel.add(label_2);

        textField = new JTextField();
        textField.setBounds(115, 35, 225, 30);
        panel.add(textField);

        final JButton button_2 = new JButton();
        button_2.setText("發送驗證");
        button_2.setBounds(243, 75, 97, 30);
        panel.add(button_2);

        textField_2 = new JTextField();
        textField_2.setBounds(115, 104, 95, 30);
        panel.add(textField_2);

        final JLabel label_3 = new JLabel();
        label_3.setText("驗證碼:");
        label_3.setBounds(44, 110, 65, 18);
        panel.add(label_3);

        passwordField_1 = new JPasswordField();
        passwordField_1.setBounds(115, 143, 231, 30);
        panel.add(passwordField_1);

        passwordField_2 = new JPasswordField();
        passwordField_2.setBounds(115, 175, 231, 30);
        panel.add(passwordField_2);

        final JLabel label_4 = new JLabel();
        label_4.setText("密        碼:");
        label_4.setBounds(44, 149, 65, 18);
        panel.add(label_4);

        final JLabel label_5 = new JLabel();
        label_5.setText("驗證密碼:");
        label_5.setBounds(44, 181, 65, 18);
        panel.add(label_5);

        final JButton button_3 = new JButton();
        button_3.setBounds(47, 510, 97, 30);
        getContentPane().add(button_3);
        button_3.setText("放棄");

        final JButton button_4 = new JButton();
        button_4.addActionListener(new ActionListener() {
            public void actionPerformed(final ActionEvent e) {

                String phone = textField.getText();
                String password = null;
                String str1 = new String(passwordField_1.getPassword()).trim();
                String str2 = new String(passwordField_2.getPassword()).trim();
                if (!phone.equals("") && !str1.equals("") && !str2.equals("")) {
                    if (str1.equals(str2)) {
                        password = new String(passwordField_2.getPassword()).trim();
                        try {
                            String json_reg = "{\"state\":\"reg\",\"phone\":\"" + phone + "\",\"password\":\""
                                    + password + "\"}";
                            dos.writeUTF(json_reg);
                            dos.flush();
                            String flag = dis.readUTF();
                            if (flag.equals("success")) {
                                javax.swing.JOptionPane.showMessageDialog(LoginDialog.this, "註冊成功...");
                                textField.setText("");
                                passwordField_1.setText("");
                                passwordField_2.setText("");
                            } else {
                                javax.swing.JOptionPane.showMessageDialog(LoginDialog.this, "註冊失敗...");
                            }
                        } catch (IOException e1) {
                            e1.printStackTrace();
                        }
                    } else {
                        javax.swing.JOptionPane.showMessageDialog(LoginDialog.this, "輸入密碼不一致...");
                        System.out.println("輸入密碼不一致...");
                        passwordField_1.setText("");
                        passwordField_2.setText("");
                    }

                } else {
                    javax.swing.JOptionPane.showMessageDialog(LoginDialog.this, "用戶名密碼必須填寫...");
                    return;
                }
            }
        });

        button_4.setBounds(262, 510, 97, 30);
        getContentPane().add(button_4);
        button_4.setText("註冊用戶");

        connect();

    }

    public void connect() {
        try {
            s = new Socket("127.0.0.1", 8888);// 以本機做server
            System.out.println("一個客戶端登陸中....!");
            dos = new DataOutputStream(s.getOutputStream());
            dis = new DataInputStream(s.getInputStream());

        } catch (ConnectException e) {
            System.out.println("服務端異常.........");
            System.out.println("請確認服務端是否開啟.........");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

對好友列表窗的死迴圈傻傻等待服務端信息,進行了重構,通過Gson方法自動判斷所獲得的Json串信息到底是好友的更新還是聊天信息的更新。

好友列表窗代碼如下:

package com.swift.frame;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.SocketException;
import java.util.Vector;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JTabbedPane;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.swift.util.Info;

public class FriendsFrame extends JFrame {

    private static final long serialVersionUID = 1L;
    private Socket s;
    private DataOutputStream dos;
    private DataInputStream dis;
    private boolean connected = false;
    Vector<String> names = new Vector<String>();
    JList<String> list = null;

    public FriendsFrame(String name, Socket socket) {
        super("歡迎 " + ":" + socket.getLocalPort());
        this.s = socket;
        connected = true;
        names.add("登錄用戶");
        try {
            this.dos = new DataOutputStream(s.getOutputStream());
            this.dis = new DataInputStream(s.getInputStream());
        } catch (IOException e) {
            e.printStackTrace();
        }
        JFrame.setDefaultLookAndFeelDecorated(true);
        JDialog.setDefaultLookAndFeelDecorated(true);

        try {
            UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel");
        } catch (ClassNotFoundException e1) {
            e1.printStackTrace();
        } catch (InstantiationException e1) {
            e1.printStackTrace();
        } catch (IllegalAccessException e1) {
            e1.printStackTrace();
        } catch (UnsupportedLookAndFeelException e1) {
            e1.printStackTrace();
        }

        setBounds(100, 100, 247, 581);
        setVisible(true);
        final JPanel panel = new JPanel();
        panel.setLayout(new BorderLayout());
        getContentPane().add(panel, BorderLayout.NORTH);

        final JLabel label = new JLabel(new ImageIcon("Images/logo.jpg"));
        label.setText("New JLabel");
        panel.add(label, BorderLayout.WEST);
        label.setPreferredSize(new Dimension(74, 74));

        final JPanel panel_1 = new JPanel();
        panel_1.setLayout(new BorderLayout());
        panel.add(panel_1, BorderLayout.CENTER);

        final JLabel advancingSwiftLabel = new JLabel();
        advancingSwiftLabel.setText(name);
        panel_1.add(advancingSwiftLabel, BorderLayout.CENTER);

        final JLabel neverWasterLabel = new JLabel();
        neverWasterLabel.setText("Never waste time any more");
        panel_1.add(neverWasterLabel, BorderLayout.SOUTH);

        final JPanel panel_2 = new JPanel();
        panel_2.setLayout(new BorderLayout());
        getContentPane().add(panel_2, BorderLayout.SOUTH);

        final JPanel panel_3 = new JPanel();
        final FlowLayout flowLayout = new FlowLayout();
        flowLayout.setAlignment(FlowLayout.LEFT);
        panel_3.setLayout(flowLayout);
        panel_2.add(panel_3);

        final JButton button = new JButton();
        panel_3.add(button);
        button.setHorizontalTextPosition(SwingConstants.LEFT);
        button.setHorizontalAlignment(SwingConstants.LEFT);
        button.setText("設置");

        final JButton button_1 = new JButton();
        panel_3.add(button_1);
        button_1.setText("查找");

        final JPanel panel_4 = new JPanel();
        panel_2.add(panel_4, BorderLayout.EAST);

        final JButton button_2 = new JButton();
        panel_4.add(button_2);
        button_2.setText("退出");

        final JTabbedPane tabbedPane = new JTabbedPane();
        getContentPane().add(tabbedPane, BorderLayout.CENTER);

        final JPanel panel_5 = new JPanel();
        tabbedPane.addTab("好友列表", null, panel_5, null);
        list = new JList<String>();

        panel_5.add(list);

        final JPanel panel_6 = new JPanel();
        tabbedPane.addTab("群聊", null, panel_6, null);

        final JPanel panel_7 = new JPanel();
        tabbedPane.addTab("聊天記錄", null, panel_7, null);

        this.setDefaultCloseOperation(EXIT_ON_CLOSE);

        final JMenuBar menuBar = new JMenuBar();
        setJMenuBar(menuBar);

        final JMenu menu = new JMenu();
        menu.setText("操作");
        menuBar.add(menu);

        final JMenuItem newItemMenuItem = new JMenuItem();
        newItemMenuItem.setText("設置");
        menu.add(newItemMenuItem);

        final JMenuItem newItemMenuItem_1 = new JMenuItem();
        newItemMenuItem_1.setText("空間");
        menu.add(newItemMenuItem_1);

        final JMenuItem newItemMenuItem_2 = new JMenuItem();
        newItemMenuItem_2.setText("郵箱");
        menu.add(newItemMenuItem_2);

        final JMenu menu_1 = new JMenu();
        menu_1.setText("會員");
        menu.add(menu_1);

        final JMenuItem newItemMenuItem_3 = new JMenuItem();
        newItemMenuItem_3.setText("會員官網");
        menu_1.add(newItemMenuItem_3);

        final JMenuItem newItemMenuItem_4 = new JMenuItem();
        newItemMenuItem_4.setText("會員專區");
        menu_1.add(newItemMenuItem_4);

        menu.addSeparator();

        final JMenu menu_2 = new JMenu();
        menu_2.setText("安全");
        menu.add(menu_2);

        final JMenuItem newItemMenuItem_5 = new JMenuItem();
        newItemMenuItem_5.setText("緊急凍結");
        menu_2.add(newItemMenuItem_5);

        final JMenuItem newItemMenuItem_6 = new JMenuItem();
        newItemMenuItem_6.setText("密碼保護");
        menu_2.add(newItemMenuItem_6);

        final JMenuItem newItemMenuItem_7 = new JMenuItem();
        newItemMenuItem_7.setText("退出");
        menu.add(newItemMenuItem_7);
        final FlowLayout flowLayout_1 = new FlowLayout();
        flowLayout_1.setAlignment(FlowLayout.RIGHT);

        this.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                disconnect();
                System.exit(0);
            }
        });

        // 調用傻傻的等待接收列表信息
        new Thread(new WaitingReceive()).start();
        // 雙擊激活聊天對話框
        list.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                if (e.getClickCount() == 2) {
                    new ChatFrame(s);
                }
            }
        });

    }

    public void disconnect() {
        try {
            if (dos != null)
                dos.close();
            if (dis != null)
                dis.close();
            if (s != null)
                s.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    class WaitingReceive implements Runnable {

        @Override
        public void run() {
            try {
                while (connected) {
                    String json = dis.readUTF();
                    Gson gson = new Gson();
                    Info info = gson.fromJson(json, Info.class);
                    System.out.println(json + "~~~~~~~~~~~~~~~~~~~~~~~~");
                    if (info.getState().equals("friends")) {
                        int flag = 0;
                        for (int i = 0; i < names.size(); i++) {
                            if (info.getMsg().equals(names.get(i))) {
                                flag = 1;
                            }
                        }
                        if (flag == 0) {
                            names.add(info.getMsg());
                        }
                        list.setListData(names);
                    }
                    if(info.getState().equals("chat")) {
                        ChatFrame.showTa(info.getMsg());
                        
                        System.out.println(info.getMsg());
                    }
                    
                }
            } catch (SocketException e) {
                System.out.println("a client has been closed!");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * WindowBuilder generated method.<br>
     * Please don't remove this method or its invocations.<br>
     * It used by WindowBuilder to associate the {@link javax.swing.JPopupMenu} with
     * parent.
     */
    private static void addPopup(Component component, final JPopupMenu popup) {
        component.addMouseListener(new MouseAdapter() {
            public void mousePressed(MouseEvent e) {
                if (e.isPopupTrigger())
                    showMenu(e);
            }

            public void mouseReleased(MouseEvent e) {
                if (e.isPopupTrigger())
                    showMenu(e);
            }

            private void showMenu(MouseEvent e) {
                popup.show(e.getComponent(), e.getX(), e.getY());
            }
        });
    }
}

對聊天窗異常進行了處理,發現聊天窗與好友列表窗同時傻傻等待服務端信息,會引發衝突,聊天窗後於好友窗打開所以接不到任何信息。

所以將聊天窗的死迴圈去掉,而增加一個static靜態方法showTa()用來在聊天窗之外供好友窗通過類名.(點)的方式調用,以改變ta(textArea)中的內容。

聊天窗代碼如下:

package com.swift.frame;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ConnectException;
import java.net.Socket;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPan

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 前言 本文介紹 框架的核心 的實現 由於在最新版本中,已經沒有考慮 等低版本,因此在選用方案時沒有採用 方式,而是直接基於 實現 交互原理 具體H5和Native的交互原理可以參考前文的 交互原理圖如下: 預計的最終效果 如果一步一步來分析,最後再看效果,可能會很枯燥,甚至還有點化簡為繁的樣子。(感 ...
  • 淺拷貝只複製指向某個對象的指針,而不複製對象本身,新舊對象還是共用同一塊記憶體。修改新對象也會修改了舊對象 深拷貝會另外創造一個一模一樣的對象,新對象跟原對象不共用記憶體,修改新對象不會改到原對象。 為了讓對象數組能深拷貝,通過百度對各種深拷貝函數的理解,融合出一種對數組和對象的深拷貝函數 ...
  • 繼 Browserify、Webpack 之後,又一款打包工具 Parcel 橫空出世 Parcel.js 的官網有這樣的自我介紹 “極速零配置Web應用打包工具” 簡單接觸了一下,單從效率上來說,確實要比 webpack 強上不少,可坑也挺多,未來升級之後應該會逐漸普及 官方文檔:https:// ...
  • 在body下麵加上 這段是從別人那抄過來的,用的時候發現兩個問題 1、頁面不能同名,比如都叫Index的就會一起被選中 2、如果頁面中的href屬性存在其他內容,比如js方法,一些針對string類型的方法就會報錯,比如lastIndexOf(),這種可以把url強制轉換成string類型,有兩種方 ...
  • 學習技術最好的方式就是在做中學,做一個小demo來對前端輸入進行實時驗證。 利用ajax技術和Sevlet技術來實現,使用原生的js。 源碼可訪問, "我的Github" 什麼是ajax Ajax 即“Asynchronous Javascript And XML”(非同步 JavaScript 和 ...
  • 前言 架構的核心就是 交互,而實現這個交互的前提是弄清楚H5和Native端的交互 本文主要介紹Native端(Android/iOS)和H5端(泛指前端)的交互原理 (之前也整理過類似的文章,本系列重新梳理) 與`H5`交互的兩種方式 原生和前端的交互有兩種方式: 以及 (在Android中是 ) ...
  • jquery中ajax請求後臺數據成功後既不執行success也不執行error,此外系統報錯:Uncaught SyntaxError: Unexpected identifier at Object.success,但後臺能夠返回數據,原代碼如下: 主要原因在於後臺返回的數據並非json格式,而 ...
  • 國際化環境下系統架構演化資料庫架構Related Link:JFrog Artifactory https://jfrog.com/open-source/Ansible http://www.ansible.com.cn/index.htmlgrafana https://grafana.com/... ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...