Blog: bugstack.cn

Precipitation, share, grow, let yourself and others can gain something! 😄

One, foreword

This knowledge learns, does not forget at all fast ah? !

Do you feel a lot of information, point to collect cool, watch video when hi, read the article at that time will, as long as the strength, over, do not remember this inside all said what. Time wasted, things have not learned, why?

In fact, because learning is also divided into the best, middle and lower strategies:

  • Bad strategy: look at the eyes on the line, sitting, nest, lying, can, anyway, not tired, but also can reply to blow water under the wechat group
  • Zhongce: Take notes and summarize the materials after reading to accumulate materials in the long term
  • Best policy: practice, get started, apply, debug, summarize, sort out data, summarize experience and output documents

To sum up, the next strategy to learn quickly feel like they will be a lot of, the middle strategy is a little bit to start lazy do not want to move, the best strategy is very time-consuming and exhausting to every knowledge point to their own hands-on. So when you’re learning, you’re unconsciously choosing the wrong strategy, so you’re not really learning anything.

Learning can learn knowledge hand, pay attention to practice, in the article prepared by little Fu Ge, are basically based on the practice code verification results as the core, about the content of the article. 😁 I have been fond of hands-on activities since I was a child. Taking an instant communication project as an example, I have implemented it for 5 or 6 times based on different technical solutions. Just to practice the technology, the screenshots are as follows:

  • Some are just learned Socket and Swing, want to start to try these technologies can write a QQ out.
  • There are also some projects that need to be completed because of internship training, but after you have some foundation, you can write all the functions in a week.
  • Although these projects now look ugly, the code logic may not be perfect either. However, each implementation in the learning phase can bring a lot of technical growth for myself.

So, this IM practice opportunity to you, I hope you can use it! Next I will give you an IM system architecture, communication protocol, single chat group chat, expression sending, UI event driven and other content, as well as provide a full set of source code so that you can start to learn.

Second, the demonstration

Before starting to learn, I will first demonstrate the operation effect of the IM system imitating the wechat interface on the PC side.

The chat page

Add buddy

Video presentation

www.bilibili.com/video/BV1BZ…

3. System design

In this SET of IM, the server uses DDD domain-driven design mode to build. The function of Netty to SpringBoot for start and stop control, at the same time in the server to build a console can be very convenient operation of communication system, user and communication management. UI separation is adopted in the construction of the client to ensure the separation of business code and UI display, so that it is very easy to expand the control.

In addition, the function realization includes; Perfect imitation of wechat desktop client, login, search to add friends, user communication, group communication, emoticon sending and other core functions. If there is a function that needs to be used, it can be extended according to this system framework.

  • UI developmentUse:JavaFxwithMavenSet up UI desktop project, explain UI display and operation events such as login box, chat box, dialog box and friend bar step by step. In this chapter, Java programmers learn to develop desktop applications.
  • Architecture design: In this chapter, we will use the DDD domain-driven design four-tier model structure and Netty to construct a reasonable layered framework. At the same time there are corresponding library table function design. I believe that after learning these contents, you can also assume a better framework.
  • Function realization: In this part, we mainly realize various functions in communication step by step, including; Login, add friends, dialogue notification, message sending, disconnected reconnect and other functions. The final development of the entire project will also allow you to learn skills from hands-on experience.

Iv. UI development

1. Overall structure definition, sidebar

Chat form, compared with the login form, chat form content will be more, but also relatively complex. So we will implement these forms and events and interface functions step by step in sections. In this article we will focus on building the chat box and developing the SIDEBar UI.

  • The first is the definition of our entire main chat form, which is a blank panel with the default border buttons removed (minimize, exit, etc.)
  • Then there is our left sidebar, which we call the Bar, the implementation of the functional area.
  • Finally, add a form event that transforms when the button is clickedThe content of the panelFill in information in.

2. Chat dialog box

Dialog box selected content area display, that is, between users to send and display information. On the whole, this is a linkage process. Click the user in the dialog box on the left, and the corresponding content will be filled on the right. So the list of conversations to be filled on the right side of the ListView needs to be associated with each conversation user. When clicking on the chat user, it is filled by repeatedly switching.

  • Click each dialog box on the left, and the content of the chat box on the right will change accordingly. The names of the conversations will also change.
  • In the dialog box, messages sent by friends are displayed on the left, and messages sent by individuals are displayed on the right. The message content also increases in height and width as the content increases.
  • At the bottom is the text input field. In the later implementation, the text input field is designed in a common way, but you can also design it for individual use.

3. The friend bar

We all often use the PC side of wechat, you can know in the friends bar is divided into several sections of content, including; New friends, public accounts, groups and friends at the bottom.

  • The top part of the search box is the same as before. The way we currently use FXML design, for example, is that this part is generic and can be abstracted into code as a component element class.
  • After our analysis, based on the development of JavaFx components, this part is a nested ListView, that is, the bottom panel is a ListView, friends and groups are each a ListView, so we will be very convenient for data filling.
  • In addition, this structure is mainly conducive to the running of our program, if you add friends, then we need to refresh the friend information in the friends bar, and when filling data, in order to be more convenient and efficient, so we designed a nested ListView. If you don’t understand, you can get the answer from the following code.

4. Event definition

In desktop UI development, in order to keep the UI isolated from the business logic, we need to package the UI to provide the interface to display the effects of the interface and interface action event abstract classes. So it can be understood as follows:

The serial number The interface name describe
1 void doShow() Open the window
2 void setUserInfo(String userId, String userNickName, String userHead) Set the login user ID, nickname, and profile picture
3 void addTalkBox(int talkIdx, Integer talkType, String talkId, String talkName, String talkHead, String talkSketch, Date talkDate, Boolean selected) Populate the dialog box list
4 void addTalkMsgUserLeft(String talkId, String msg, Date msgData, Boolean idxFirst, Boolean selected, Boolean isRemind) Fill dialog box messages – friends (other people’s messages)
  • These interfaces are all the behavior interfaces that our UI provides externally, and a link description of these interfaces is; Open Windows, search for friends, add friends, open dialog boxes, send messages.

5. Communication design

1. System architecture

Earlier we talked about the more appropriate architecture, which is the best one for your current needs. So how do you design this architecture? It’s basically a matter of finding goals that fit. The reason why we did it this way, so there are several things in this system;

  • Our system should have web pages to manage communication users and control and monitor the server side.
  • Database object class, do not be external contamination, to have isolation. For example; Your database class is exposed to external display classes, so now you need to add a field that does not exist in your database. At this point, the database class has been contaminated.
  • At present, Netty communication is implemented in Java language, so both the server and client need to use the protocol definition and parsing in the communication process. So we need to pull out this layer and provide Jar packages externally.
  • Interfaces, business processes, underlying services, and communication interactions should be clearly distinguished and implemented to avoid confusion and difficulty in maintenance.

Combined with our four goals, what model structure do you have in mind? Is there a plan for the technology stack selection? Next we’ll look at two models for architectural design, MVC, which you’re familiar with, and DDD domain-driven design, which you’ve probably heard of.

2. Communication protocol

According to the drawing, when transferring objects, we need to add a frame identifier in the transfer packet to determine which object the current business object is, which can make our business clearer and avoid using a lot of if statements to judge.

Framework agreement

Agreement └ ─ ─ the SRC ├ ─ ─ the main │ ├ ─ ─ Java │ │ └ ─ ─ org. Itstack. Naive. Chat │ │ ├ ─ ─ the codec │ │ │ ├ ─ ─ ObjDecoder. Java │ │ │ └ ─ ─ ObjEncoder. Java │ │ ├ ─ ─ protocol │ │ │ ├ ─ ─ demo │ │ │ ├ ─ ─ Command. The Java │ │ │ └ ─ ─ Packet. Java │ │ └ ─ ─ util │ │ └ ─ ─ SerializationUtil. Java │ ├ ─ ─ resources │ │ └ ─ ─ application. Yml │ └ ─ ─ webapp │ └ ─ ─ chat │ └ ─ ─ res │ └ ─ ─ index. The HTML └ ─ ─ The test └ ─ ─ Java └ ─ ─ org. Itstack. Demo. Test └ ─ ─ ApiTest. JavaCopy the code

Protocol packet

public abstract class Packet {

    private final static Map<Byte, Class<? extends Packet>> packetType = new ConcurrentHashMap<>();

    static {
        packetType.put(Command.LoginRequest, LoginRequest.class);
        packetType.put(Command.LoginResponse, LoginResponse.class);
        packetType.put(Command.MsgRequest, MsgRequest.class);
        packetType.put(Command.MsgResponse, MsgResponse.class);
        packetType.put(Command.TalkNoticeRequest, TalkNoticeRequest.class);
        packetType.put(Command.TalkNoticeResponse, TalkNoticeResponse.class);
        packetType.put(Command.SearchFriendRequest, SearchFriendRequest.class);
        packetType.put(Command.SearchFriendResponse, SearchFriendResponse.class);
        packetType.put(Command.AddFriendRequest, AddFriendRequest.class);
        packetType.put(Command.AddFriendResponse, AddFriendResponse.class);
        packetType.put(Command.DelTalkRequest, DelTalkRequest.class);
        packetType.put(Command.MsgGroupRequest, MsgGroupRequest.class);
        packetType.put(Command.MsgGroupResponse, MsgGroupResponse.class);
        packetType.put(Command.ReconnectRequest, ReconnectRequest.class);
    }

    public static Class<? extends Packet> get(Byte command) {
        return packetType.get(command);
    }

    /** * get protocol instruction **@returnReturn the instruction value */
    public abstract Byte getCommand(a);

}
Copy the code

3. Add friends

  • As you can see from the flow above, there are two parts; (1) Search friends, (2) add friends. After completing friends that day, friends will appear in our friends bar.
  • And here we use unilateral consent to add friends, that is, when you add a friend, the other side also has your friend information.
  • If you need to add friends in your business and agree with them, you can add a status message to request them to add friends. Two users can become friends and communicate with each other only after the other agrees.

Add friends, case code

public class AddFriendHandler extends MyBizHandler<AddFriendRequest> {

    public AddFriendHandler(UserService userService) {
        super(userService);
    }

    @Override
    public void channelRead(Channel channel, AddFriendRequest msg) {
        // 1. Add A friend to database [A->B B->A]
        List<UserFriend> userFriendList = new ArrayList<>();
        userFriendList.add(new UserFriend(msg.getUserId(), msg.getFriendId()));
        userFriendList.add(new UserFriend(msg.getFriendId(), msg.getUserId()));
        userService.addUserFriend(userFriendList);
        // 2. Push the friend to add A
        UserInfo userInfo = userService.queryUserInfo(msg.getFriendId());
        channel.writeAndFlush(new AddFriendResponse(userInfo.getUserId(), userInfo.getUserNickName(), userInfo.getUserHead()));
        // 3. Push friend completion B
        Channel friendChannel = SocketChannelUtil.getChannel(msg.getFriendId());
        if (null == friendChannel) return;
        UserInfo friendInfo = userService.queryUserInfo(msg.getUserId());
        friendChannel.writeAndFlush(newAddFriendResponse(friendInfo.getUserId(), friendInfo.getUserNickName(), friendInfo.getUserHead())); }}Copy the code

4. Message response

  • As can be seen from the overall process, when a user initiates a friend or group communication, an event will be triggered, and then the client will send a request for a conversation with a friend to the server.
  • After receiving a chat request from a friend, the server needs to save the communication information with the friend in the dialog box. At the same time notify friends, I and you are going to communicate. You added me to your list of dialogs.
  • In case of group communication, such notification is not necessary, because it is impossible to notify all group users who are not online (they have not logged in yet), so this part only needs to create a dialog box to the list after the user goes online and receives the information. You can think about it carefully, but you can also think about other ways to implement it.

Message reply, case code

public class MsgHandler extends MyBizHandler<MsgRequest> {

    public MsgHandler(UserService userService) {
        super(userService);
    }

    @Override
    public void channelRead(Channel channel, MsgRequest msg) {
        logger.info("Message processing: {}", JSON.toJSONString(msg));
        // Asynchronous write library
        userService.asyncAppendChatRecord(new ChatRecordInfo(msg.getUserId(), msg.getFriendId(), msg.getMsgText(), msg.getMsgType(), msg.getMsgDate()));
        // Add dialog [add if the other party doesn't have your dialog]
        userService.addTalkBoxInfo(msg.getFriendId(), msg.getUserId(), Constants.TalkType.Friend.getCode());
        // Get the buddy communication channel
        Channel friendChannel = SocketChannelUtil.getChannel(msg.getFriendId());
        if (null == friendChannel) {
            logger.info("User ID: {} not logged in!", msg.getFriendId());
            return;
        }
        // Send a message
        friendChannel.writeAndFlush(newMsgResponse(msg.getUserId(), msg.getMsgText(), msg.getMsgType(), msg.getMsgDate())); }}Copy the code

5. Disconnect and reconnect

  • As we can see from the above flow, when the network connection is disconnected, a request is sent to the server to reconnect.

So the process of initiating a link is different from the initial link of the system. Disconnection is to send the user ID information to the server, so that the server can update the binding relationship between the user and the communication Channel.

  • In addition, you need to update the reconnection information in the group and add the reconnection information of users to the group mapping. At this point, the user can resume communication with friends and groups.

Message reply, case code

// Channel status periodic inspection; The command is executed every 5 seconds after 3 seconds
scheduledExecutorService.scheduleAtFixedRate(() -> {while(! nettyClient.isActive()) {System.out.println("Communication Pipeline inspection: Communication pipeline Status" + nettyClient.isActive());
        try {System.out.println("Communication Pipeline inspection: Disconnect and reconnect [Begin]");
            Channel freshChannel = executorService.submit(nettyClient).get();
            if (null == CacheUtil.userId) continue;
            freshChannel.writeAndFlush(new ReconnectRequest(CacheUtil.userId));
        } catch (InterruptedException | ExecutionException e) {System.out.println("Communication pipeline inspection: Disconnection and reconnection [Error]"); }}},3.5, TimeUnit.SECONDS);
Copy the code

6. Cluster communication

  • Cross service cases use Redis publish and subscribe for messaging, or zooKeeper if you are a large service
  • When sending A message to user B, user A needs to pass user B’s channeId so that the server can check whether the channeId belongs to its own service
  • A single machine can also start multiple Netty services, and the program will automatically find available ports

Download the source code

In this project, the author Xiao Fuge uses JavaFx, Netty4.x, SpringBoot, Mysql and other technology stacks and prefers DDD domain driver design to build the imitation desktop version oF wechat to achieve the core communication functions.

This IM code is divided into three groups of modules; UI, client, server. The reason for this split is to isolate THE UI presentation from the business logic, using events and interfaces to drive the code hierarchy cleaner and easier to extend and maintain.

The serial number engineering introduce
1 itstack-naive-chat-ui The UI side, developed using JavaFx, is provided in our UI side; Login box, chat box, and a large number of interactive interfaces, interfaces and events in the chat box. In the end, my UI side used Maven packaging to provide Jar packages to the outside world to separate the UI interface from the business behavior process.
2 itstack-naive-chat-client Client is our communication core project, mainly using Netty4.x as our socket framework to complete communication interaction. In this project, I was responsible for introducing THE Jar package of UI, completing the events defined by UI (login verification, search to add friends, conversation notification, sending information, etc.), and using the communication protocol defined by us in the server side project to complete the information interaction.
3 itstack-navie-chat-server The server side also uses Netty4.x as the socket communication framework, and uses Layui as the management background page in the server side, and our server side adopts the way of DDD domain driven design and Netty collection, in order to achieve our framework structure clean and easy to expand.
4 itstack.sql System engineering database table structure and initialization data information, a total of 6 core tables; User table, group table, user group association table, friends table, chat table and chat record table. Users can expand and improve themselves in actual business development. At present, the structure of library table is only based on core functions.
  • The source code for:https://github.com/fuzhengwei/NaiveChat Pro, source code for me to point a Star, not white fur jacket!!

Seven,

  • This IM system involves a lot of technology stack content, netty4. x, SpringBoot, Mybatis, Mysql, JavaFx, Layui and other technology stack use, as well as the whole system framework using DDD four-layer architecture +Socket module to build. All UIs are designed in a separate event-driven way at the back end, and you can learn a lot from this process if you keep learning it.Enough boasting! 🌶
  • The learning process of any new technology stack will include this route; Running HelloWorld, mastering apis, project practices, and finally deep source code mining. When hearing such a requirement, Java programmers must think of a list of technical points to fill in the modules in our project, such as; Interface with JavaFx, Swing, Socket or know Netty framework, server control with MVC model plus SpringBoot and so on. However, it is the most important part in the process of learning, practicing and growing that how to set up our system properly.