Backend Development 23 min read

Java Netty‑Based Chat Application with Swing UI and MySQL Integration

This article details the design and implementation of a Java chat system that uses Netty for server‑side networking, Swing for the client UI, and MySQL with C3P0 for data persistence, covering features such as user authentication, friend management, single‑chat messaging, and online status detection.

Top Architect
Top Architect
Top Architect
Java Netty‑Based Chat Application with Swing UI and MySQL Integration

1. Function Implementation

Implemented features include password, nickname, and signature modification; adding and deleting friends; single‑chat messaging; and determining whether a friend is online.

2. Module Division

The project is divided into server‑side controllers, client handlers, UI frames, and utility classes. (The original diagram is omitted for brevity.)

3. Knowledge Used

Netty

Swing

SynchronousQueue

MySQL CRUD operations

C3P0 connection pool

JSON string handling

4. Partial Code Implementation

nettyController.java

package chat.Project.controller;

import chat.Project.bean.information;
import chat.Project.constant.EnMsgType;
import chat.Project.dao.*;
import chat.utils.CacheUtil;
import chat.utils.JsonUtils;
import com.fasterxml.jackson.databind.node.ObjectNode;
import io.netty.channel.Channel;
import java.util.ArrayList;
import java.util.Iterator;

public class NettyController {
    private static UserDao userDao = new UserDaoImpl();
    private static informationDao informationDao = new informationDaoImpl();
    private static friendDao friendDao = new friendDaoImpl();

    public static String processing(String message, Channel channel) {
        // Parse client message
        ObjectNode jsonNodes = JsonUtils.getObjectNode(message);
        String msgtype = jsonNodes.get("msgtype").asText();
        if (EnMsgType.EN_MSG_LOGIN.toString().equals(msgtype)) {
            return loginOperation(jsonNodes, channel);
        } else if (EnMsgType.EN_MSG_MODIFY_SIGNATURE.toString().equals(msgtype)) {
            return modifySignature(jsonNodes);
        } else if (EnMsgType.EN_MSG_MODIFY_NICKNAME.toString().equals(msgtype)) {
            return modifyNickname(jsonNodes);
        } else if (EnMsgType.EN_MSG_GETINFORMATION.toString().equals(msgtype)) {
            return getInformation(jsonNodes);
        } else if (EnMsgType.EN_MSG_VERIFY_PASSWORD.toString().equals(msgtype)) {
            return verifyPasswd(jsonNodes);
        } else if (EnMsgType.EN_MSG_CHAT.toString().equals(msgtype)) {
            return SingleChat(jsonNodes);
        } else if (EnMsgType.EN_MSG_GET_ID.toString().equals(msgtype)) {
            return getId(jsonNodes);
        } else if (EnMsgType.EN_MSG_GET_FRIEND.toString().equals(msgtype)) {
            return getFriend(jsonNodes);
        } else if (EnMsgType.EN_MSG_ADD_FRIEND.toString().equals(msgtype)) {
            return addFriends(jsonNodes);
        } else if (EnMsgType.EN_MSG_DEL_FRIEND.toString().equals(msgtype)) {
            return delFriend(jsonNodes);
        } else if (EnMsgType.EN_MSG_ACTIVE_STATE.toString().equals(msgtype)) {
            return friendIsActive(jsonNodes);
        }
        return "";
    }

    // Determine friend online status
    private static String friendIsActive(ObjectNode jsonNodes) {
        int friendId = jsonNodes.get("friendId").asInt();
        ObjectNode objectNode = JsonUtils.getObjectNode();
        objectNode.put("msgtype", EnMsgType.EN_MSG_ACK.toString());
        objectNode.put("srctype", EnMsgType.EN_MSG_ACTIVE_STATE.toString());
        Channel channel = CacheUtil.get(friendId);
        if (channel == null) {
            objectNode.put("code", 200);
        } else {
            objectNode.put("code", 300);
        }
        return objectNode.toString();
    }

    // Delete friend
    private static String delFriend(ObjectNode jsonNodes) {
        Integer friendId = jsonNodes.get("friendId").asInt();
        int userId = jsonNodes.get("id").asInt();
        String localName = jsonNodes.get("localName").asText();
        ObjectNode objectNode = JsonUtils.getObjectNode();
        objectNode.put("msgtype", EnMsgType.EN_MSG_ACK.toString());
        objectNode.put("srctype", EnMsgType.EN_MSG_DEL_FRIEND.toString());
        objectNode.put("code", 200);
        information information = informationDao.getInformation(friendId);
        String friendName = information.getNickname();
        boolean exist = friendDao.isExist(friendName, userId);
        if (exist) {
            friendDao.delFriend(userId, friendName);
            friendDao.delFriend(friendId, localName);
            objectNode.put("code", 300);
        }
        return objectNode.toString();
    }

    // Add friend
    private static String addFriends(ObjectNode jsonNodes) {
        Integer friendId = jsonNodes.get("friendId").asInt();
        int userId = jsonNodes.get("id").asInt();
        String localName = jsonNodes.get("localName").asText();
        boolean exists = userDao.verifyExistFriend(friendId);
        ObjectNode objectNode = JsonUtils.getObjectNode();
        objectNode.put("msgtype", EnMsgType.EN_MSG_ACK.toString());
        objectNode.put("srctype", EnMsgType.EN_MSG_ADD_FRIEND.toString());
        objectNode.put("code", 200);
        if (exists) {
            objectNode.put("code", 300);
            information information = informationDao.getInformation(friendId);
            String friendNickname = information.getNickname();
            friendDao.addFriends(userId, localName, friendNickname);
            friendDao.addFriends(friendId, friendNickname, localName);
        }
        return objectNode.toString();
    }

    // Get friend list
    private static String getFriend(ObjectNode jsonNodes) {
        int uid = jsonNodes.get("uid").asInt();
        ArrayList
friends = friendDao.getFriends(uid);
        ObjectNode objectNode = JsonUtils.getObjectNode();
        objectNode.put("msgtype", EnMsgType.EN_MSG_ACK.toString());
        objectNode.put("srctype", EnMsgType.EN_MSG_GET_FRIEND.toString());
        int i = 0;
        for (String f : friends) {
            objectNode.put("res" + i, f);
            i++;
        }
        objectNode.put("count", i);
        return objectNode.toString();
    }

    // Get user ID by nickname
    private static String getId(ObjectNode jsonNodes) {
        String nickname = jsonNodes.get("nickname").asText();
        information information = informationDao.nicknameGetId(nickname);
        int uid = information.getUid();
        ObjectNode objectNode = JsonUtils.getObjectNode();
        objectNode.put("msgtype", EnMsgType.EN_MSG_ACK.toString());
        objectNode.put("srctype", EnMsgType.EN_MSG_GET_ID.toString());
        objectNode.put("uid", uid);
        return objectNode.toString();
    }

    // Single‑chat handling
    private static String SingleChat(ObjectNode jsonNodes) {
        int id = jsonNodes.get("id").asInt();
        ObjectNode objectNode = JsonUtils.getObjectNode();
        objectNode.put("msgtype", EnMsgType.EN_MSG_ACK.toString());
        objectNode.put("srctype", EnMsgType.EN_MSG_CHAT.toString());
        Channel channel = CacheUtil.get(id);
        if (channel == null) {
            objectNode.put("code", 200);
        } else {
            objectNode.put("code", 300);
            channel.writeAndFlush(jsonNodes.toString());
        }
        return objectNode.toString();
    }

    // Verify and change password
    private static String verifyPasswd(ObjectNode jsonNodes) {
        int id = jsonNodes.get("id").asInt();
        String oldPasswd = jsonNodes.get("oldPasswd").asText();
        String newPasswd = jsonNodes.get("newPasswd").asText();
        boolean exists = userDao.verifyPassword(oldPasswd, id);
        ObjectNode objectNode = JsonUtils.getObjectNode();
        objectNode.put("msgtype", EnMsgType.EN_MSG_VERIFY_PASSWORD.toString());
        objectNode.put("code", 200);
        if (exists) {
            userDao.modifyPasswd(newPasswd, id);
            objectNode.put("code", 300);
        }
        return objectNode.toString();
    }

    // Get user information
    private static String getInformation(ObjectNode jsonNodes) {
        int id = jsonNodes.get("id").asInt();
        information information = informationDao.getInformation(id);
        ObjectNode objectNode = JsonUtils.getObjectNode();
        objectNode.put("msgtype", EnMsgType.EN_MSG_ACK.toString());
        objectNode.put("srctype", EnMsgType.EN_MSG_GETINFORMATION.toString());
        objectNode.put("Nickname", information.getNickname());
        objectNode.put("Signature", information.getSignature());
        return objectNode.toString();
    }

    // Modify nickname
    private static String modifyNickname(ObjectNode jsonNodes) {
        int id = jsonNodes.get("id").asInt();
        String nickname = jsonNodes.get("nickname").asText();
        informationDao.storeNickname(nickname, id);
        return "";
    }

    // Modify signature
    private static String modifySignature(ObjectNode jsonNodes) {
        int id = jsonNodes.get("id").asInt();
        String signature = jsonNodes.get("signature").asText();
        informationDao.storeSignature(signature, id);
        return "";
    }

    // Login operation
    private static String loginOperation(ObjectNode objectNode, Channel channel) {
        int id = objectNode.get("id").asInt();
        String passwd = objectNode.get("passwd").asText();
        boolean exists = userDao.getInformation(id, passwd);
        ObjectNode jsonNodes = JsonUtils.getObjectNode();
        jsonNodes.put("msgtype", EnMsgType.EN_MSG_ACK.toString());
        jsonNodes.put("srctype", EnMsgType.EN_MSG_LOGIN.toString());
        jsonNodes.put("code", 300);
        if (exists) {
            jsonNodes.put("code", 200);
            CacheUtil.put(id, channel);
        }
        return jsonNodes.toString();
    }
}

ClientHandler.java

package chat.Project.netty;

import chat.Frame.chat.ChatFrame;
import chat.Frame.chat.linkmen;
import chat.Frame.chat.login;
import chat.Project.constant.EnMsgType;
import chat.util.JsonUtils;
import com.fasterxml.jackson.databind.node.ObjectNode;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import java.util.concurrent.SynchronousQueue;

public class ClientHandler extends SimpleChannelInboundHandler
{
    public static SynchronousQueue
queue = new SynchronousQueue<>();
    public static String Nickname;
    public String Signature;

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, String s) throws Exception {
        // Not used
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        System.out.println(msg);
        ObjectNode jsonNodes = JsonUtils.getObjectNode((String) msg);
        String msgtype = jsonNodes.get("msgtype").asText();
        if (EnMsgType.EN_MSG_ACK.toString().equals(msgtype)) {
            String srctype = jsonNodes.get("srctype").asText();
            if (EnMsgType.EN_MSG_LOGIN.toString().equals(srctype)) {
                queue.offer(jsonNodes.get("code").asInt());
            } else if (EnMsgType.EN_MSG_GETINFORMATION.toString().equals(srctype)) {
                Nickname = jsonNodes.get("Nickname").asText();
                Signature = jsonNodes.get("Signature").asText();
                linkmen.label_1.setText(Nickname);
                linkmen.field.setText(Signature);
            } else if (EnMsgType.EN_MSG_CHAT.toString().equals(srctype)) {
                queue.offer(jsonNodes.get("code").asInt());
            } else if (EnMsgType.EN_MSG_GET_ID.toString().equals(srctype)) {
                queue.offer(jsonNodes.get("uid").asInt());
            } else if (EnMsgType.EN_MSG_GET_FRIEND.toString().equals(srctype)) {
                int count = jsonNodes.get("count").asInt();
                login.friend = new String[count];
                for (int i = 0; i < count; i++) {
                    login.friend[i] = jsonNodes.get("res" + i).asText();
                    System.out.println(jsonNodes.get("res" + i));
                }
            } else if (EnMsgType.EN_MSG_ADD_FRIEND.toString().equals(srctype)) {
                queue.offer(jsonNodes.get("code").asInt());
            } else if (EnMsgType.EN_MSG_DEL_FRIEND.toString().equals(srctype)) {
                queue.offer(jsonNodes.get("code").asInt());
            } else if (EnMsgType.EN_MSG_ACTIVE_STATE.toString().equals(srctype)) {
                queue.offer(jsonNodes.get("code").asInt());
            }
        } else if (EnMsgType.EN_MSG_VERIFY_PASSWORD.toString().equals(msgtype)) {
            queue.offer(jsonNodes.get("code").asInt());
        } else if (EnMsgType.EN_MSG_CHAT.toString().equals(msgtype)) {
            String message = " " + jsonNodes.get("message").asText();
            ChatFrame.sb.append(message + "\n");
            ChatFrame.displayTextPanel.setText(ChatFrame.sb.toString());
        }
    }
}

linkmen.java

package chat.Frame.chat;

import chat.Frame.operation.alterColumn.changeNickname;
import chat.Frame.operation.alterColumn.changePassword;
import chat.Frame.operation.alterColumn.changeSignature;
import chat.Frame.operation.friendHandle.addFriend;
import chat.Frame.operation.friendHandle.delFriend;
import chat.Frame.tipFrame;
import chat.Project.services.sendServers;
import io.netty.channel.Channel;
import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.awt.*;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;

public class linkmen extends JFrame {
    private JFrame frame;
    private JLabel label_2, label_3, label_4, label;
    public static JLabel label_1;
    private JComboBox box, box_1, box_2;
    private ImageIcon icon_1, icon;
    private JTextField field_1;
    public static JTextField field;
    private JPanel panel_1, panel_3, panel;
    public JScrollPane panel_2;
    public static JList
list;
    private Channel channel;
    private Integer id;
    public static JLabel label_5, label_6;
    private String[] fd;
    public static DefaultListModel
model;

    public linkmen(Integer id, Channel channel, String[] fd) {
        this.id = id;
        this.channel = channel;
        this.fd = fd;
    }

    public void init() {
        // Initialize UI components (panels, labels, list, combo boxes, etc.)
        // ... (omitted for brevity)
    }

    public void mian() {
        model = new DefaultListModel<>();
        for (int i = 0; i < fd.length; i++) {
            model.addElement(fd[i]);
        }
        init();
        new sendServers(channel).update(id);
        label_1.setFont(new Font("宋体", Font.PLAIN, 18));
        field.setFont(new Font("宋体", Font.PLAIN, 18));
    }

    private static boolean judgeDigit(String string) {
        for (int i = 0; i < string.length(); i++) {
            if (!Character.isDigit(string.charAt(i))) {
                return false;
            }
        }
        return true;
    }
}

tipFrame.java

package chat.Frame;

import chat.Frame.chat.linkmen;
import chat.Frame.operation.alterColumn.changeNickname;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class tipFrame extends JDialog {
    private Container container;
    public JLabel label;
    private JButton button;

    public tipFrame() {}

    public void init(String msg) {
        container = getContentPane();
        label = new JLabel(msg);
        label.setBounds(70, 0, 200, 70);
        label.setFont(new Font("微软雅黑", Font.PLAIN, 20));
        container.add(label);
        button = new JButton("确认");
        button.setBounds(35, 50, 140, 40);
        container.add(button);
        setBounds(780, 170, 220, 140);
        setLayout(null);
        setVisible(true);
        container.setBackground(new Color(0xD8FFD5));
        setAlwaysOnTop(true);
        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                tipFrame.this.dispose();
            }
        });
    }
}

5. Runtime Screenshots

The article includes screenshots of the login window, contacts list, chat window, and various operation flows, demonstrating that all implemented features are functional.

Overall, the project showcases a complete Java‑based instant messaging client and server, illustrating the integration of Netty networking, Swing UI, MySQL persistence, and JSON message handling.

javaNettyMySQLnetworkingSwingChat Application
Top Architect
Written by

Top Architect

Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.