Backend Development 19 min read

Netty‑Based Chat Application: Functional Implementation and Code Walkthrough

This article presents a comprehensive walkthrough of a Java chat application built with Netty for server‑side communication and Swing for the client UI, detailing functional features such as password, nickname, and signature updates, friend management, single‑chat messaging, online status detection, and includes full source code snippets and execution screenshots.

Java Captain
Java Captain
Java Captain
Netty‑Based Chat Application: Functional Implementation and Code Walkthrough

The document describes a complete Java chat system that uses Netty on the server side for network communication and Swing on the client side for the graphical user interface.

Functional implementation includes modifying password, nickname, and personal signature; adding and deleting friends; single‑chat messaging; and determining whether a friend is online.

Module division is illustrated with a diagram (image omitted) showing the separation between the Netty controller, client handler, UI frames, and utility classes.

Technologies employed are Netty, Swing, Java synchronized collections (SynchronousQueue), MySQL CRUD operations, C3P0 connection pool, and JSON handling.

NettyController.java implements the server‑side message processing logic, routing messages based on EnMsgType values and interacting with DAO layers for user, information, and friend data. Key methods include friendIsActive , addFriends , delFriend , getFriend , getId , SingleChat , verifyPasswd , getInformation , modifyNickname , modifySignature , loginOperation , and others that construct JSON responses using JsonUtils .

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 "";
    }
    // ... (other methods omitted for brevity) ...
}

ClientHandler.java receives messages from the server, parses the JSON payload, and uses a SynchronousQueue to communicate status codes back to the UI thread. It updates UI components such as nickname, signature, friend list, and handles chat messages.

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 {}

    @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();
            // handle various ACK types ...
        } else if (EnMsgType.EN_MSG_VERIFY_PASSWORD.toString().equals(msgtype)) {
            int code = jsonNodes.get("code").asInt();
            queue.offer(code);
        } 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 defines the main contact window UI, constructing panels for user information, friend list, status selection, and system settings. It includes listeners for friend selection, adding/deleting friends, and modifying user attributes via the sendServers service.

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 java.awt.*;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;

public class linkmen extends JFrame {
    // UI components and fields ...
    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;
    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() {
        // Build panels, labels, combo boxes, list, and frame layout ...
        // Listeners for status, nickname, password, signature changes
        // Add/Del friend actions invoke sendServers methods
    }

    public void mian() {
        model = new DefaultListModel<>();
        for (int i = 0; i < fd.length; i++) {
            model.addElement(fd[i]);
        }
        init();
        new sendServers(channel).update(id);
    }

    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 provides a simple dialog window to display operation status or error messages, with a confirmation button to close the dialog.

package chat.Frame;

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();
            }
        });
    }
}

The article also includes several screenshots showing the login window, contact list interface, chat window, communication flow diagram, and examples of modifying user information and managing friends.

Finally, the author invites readers to like and share the post if they find the tutorial helpful.

JavaNettySocket ProgrammingSwingChat ApplicationFriend Management
Java Captain
Written by

Java Captain

Focused on Java technologies: SSM, the Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading; occasionally covers DevOps tools like Jenkins, Nexus, Docker, ELK; shares practical tech insights and is dedicated to full‑stack Java development.

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.