[SpringBoot] 스프링부트 웹소켓(WebSocket) 예제

[SpringBoot] 스프링부트 웹소켓(WebSocket) 예제

1. 스프링부트 웹 프로젝트 생성

우선 스프링부트 웹 프로젝트가 있어야 한다.

새로 시작하려면 아래 포스트를 참고하면 된다.

https://blog.naver.com/bb_/222141978468

2. pom.xml 수정
아래 코드를 추가한다.

<!– websocket –>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-websocket</artifactId>
</dependency>

 

3. Websocket.java 파일 작성

원하는 패키지에 아래 파일을 작성한다.

package 원하는_패키지명;

import java.util.ArrayList;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import org.springframework.stereotype.Component;

@Component
@ServerEndpoint(“/websocket”)
public class Websocket {

    /**
     * 웹소켓 세션을 담는 ArrayList
     */

    private static ArrayList<Session> sessionList = new ArrayList<Session>();

    
    /**
     * 웹소켓 사용자 연결 성립하는 경우 호출
     */

    @OnOpen
    public void handleOpen(Session session) {
        if (session != null) {
            String sessionId = session.getId();
            
            System.out.println(“client is connected. sessionId == [“ + sessionId + “]”);
            sessionList.add(session);
            
            // 웹소켓 연결 성립되어 있는 모든 사용자에게 메시지 전송
            sendMessageToAll(“***** [USER-“ + sessionId + “] is connected. *****”);
        }
    }
    

    /**
     * 웹소켓 메시지(From Client) 수신하는 경우 호출
     */

    @OnMessage
    public String handleMessage(String message, Session session) {
        if (session != null) {
            String sessionId = session.getId();
            System.out.println(“message is arrived. sessionId == [“ + sessionId + “] / message == [“ + message + “]”);

            // 웹소켓 연결 성립되어 있는 모든 사용자에게 메시지 전송
            sendMessageToAll(“[USER-“ + sessionId + “] “ + message);
        }

        return null;
    }
    

    /**
     * 웹소켓 사용자 연결 해제하는 경우 호출
     */

    @OnClose
    public void handleClose(Session session) {
        if (session != null) {
            String sessionId = session.getId();
            System.out.println(“client is disconnected. sessionId == [“ + sessionId + “]”);
            
            // 웹소켓 연결 성립되어 있는 모든 사용자에게 메시지 전송
            sendMessageToAll(“***** [USER-“ + sessionId + “] is disconnected. *****”);
        }
    }

    
    /**
     * 웹소켓 에러 발생하는 경우 호출
     */

    @OnError
    public void handleError(Throwable t) {
        t.printStackTrace();
    }
    
    
    /**
     * 웹소켓 연결 성립되어 있는 모든 사용자에게 메시지 전송
     */

    private boolean sendMessageToAll(String message) {
        if (sessionList == null) {
            return false;
        }

        int sessionCount = sessionList.size();
        if (sessionCount < 1) {
            return false;
        }

        Session singleSession = null;

        for (int i = 0; i < sessionCount; i++) {
            singleSession = sessionList.get(i);
            if (singleSession == null) {
                continue;
            }

            if (!singleSession.isOpen()) {
                continue;
            }

            sessionList.get(i).getAsyncRemote().sendText(message);
        }

        return true;
    }
}

 

4. OOOApplication.java 파일 수정

@SpringBootApplication 가 붙어있는 자바 파일을 수정하면 된다. serverEndpointExporter 메서드를 만들고 @Bean 어노테이션을 붙여준다.

package 원하는_패키지명;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

@SpringBootApplication
public class ProjectNameApplication {

    public static void main(String[] args) {
        SpringApplication.run(WebGameBaseApplication.class, args);
    }
    
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }

}

 

5. chat.jsp 파일 작성
아래 파일을 적당한 위치에 작성한다.
여기서는 프로젝트/src/main/webapp/WEB-INF/views/chat.jsp 경로에 위치한다고 가정한다.

<%@ page contentType=“text/html; charset=utf-8” %>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv=“Content-Type” content=“text/html; charset=UTF-8”>
<title>웹소켓 테스트 페이지</title>
<script type=“text/javascript”>
var g_webSocket = null;
window.onload = function() {
    g_webSocket = new WebSocket(“ws://localhost:8080/websocket”);
    
    
    /**
     * 웹소켓 사용자 연결 성립하는 경우 호출
     */

    g_webSocket.onopen = function(message) {
        addLineToChatBox(“Server is connected.”);
    };
    
    
    /**
     * 웹소켓 메시지(From Server) 수신하는 경우 호출
     */

    g_webSocket.onmessage = function(message) {
        addLineToChatBox(message.data);
    };

    /**
     * 웹소켓 사용자 연결 해제하는 경우 호출
     */

    g_webSocket.onclose = function(message) {
        addLineToChatBox(“Server is disconnected.”);
    };

    /**
     * 웹소켓 에러 발생하는 경우 호출
     */

    g_webSocket.onerror = function(message) {
        addLineToChatBox(“Error!”);
    };
}

/**
* 채팅 박스영역에 내용 한 줄 추가
*/

function addLineToChatBox(_line) {
    if (_line == null) {
        _line = “”;
    }
    
    var chatBoxArea = document.getElementById(“chatBoxArea”);
    chatBoxArea.value += _line + “\n”;
    chatBoxArea.scrollTop = chatBoxArea.scrollHeight;    
}

/**
* Send 버튼 클릭하는 경우 호출 (서버로 메시지 전송)
*/

function sendButton_onclick() {
    var inputMsgBox = document.getElementById(“inputMsgBox”);
    if (inputMsgBox == null || inputMsgBox.value == null || inputMsgBox.value.length == 0) {
        return false;
    }
    
    var chatBoxArea = document.getElementById(“chatBoxArea”);
    
    if (g_webSocket == null || g_webSocket.readyState == 3) {
        chatBoxArea.value += “Server is disconnected.\n”;
        return false;
    }
    
    // 서버로 메시지 전송
    g_webSocket.send(inputMsgBox.value);
    inputMsgBox.value = “”;
    inputMsgBox.focus();
    
    return true;
}

/**
* Disconnect 버튼 클릭하는 경우 호출
*/

function disconnectButton_onclick() {
    if (g_webSocket != null) {
        g_webSocket.close();    
    }
}

/**
* inputMsgBox 키입력하는 경우 호출
*/

function inputMsgBox_onkeypress() {
    if (event == null) {
        return false;
    }
    
    // 엔터키 누를 경우 서버로 메시지 전송
    var keyCode = event.keyCode || event.which;
    if (keyCode == 13) {
        sendButton_onclick();
    }
}
</script>
</head>
<body>
    <input id=“inputMsgBox” style=“width: 250px;” type=“text” onkeypress=“inputMsgBox_onkeypress()”>
    <input id=“sendButton” value=“Send” type=“button” onclick=“sendButton_onclick()”>
    <input id=“disconnectButton” value=“Disconnect” type=“button” onclick=“disconnectButton_onclick()”>
    <br/>
    <textarea id=“chatBoxArea” style=“width: 100%;” rows=“10” cols=“50” readonly=“readonly”></textarea>
</body>
</html>

 

6. OOOController.java 파일 수정
@Controller 가 붙어있는 아무 컨트롤러나 상관없다. @Controller 가 붙어있는 파일이 없다면 새로 생성하자.
도메인:포트/chat 을 주소창에 입력하면 chat.jsp 파일이 열리도록 컨트롤러를 내에 chat 메서드를 만들고 @RequestMapping 어노테이션을 붙여준다.

package 원하는_패키지명;

import java.util.Locale;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
public class MainController {

    @RequestMapping(value=“/”)
    public String main() {
        return “index”;
    }
    
    @RequestMapping(value = “/chat”, method = RequestMethod.GET)
    public String chat(Locale locale, Model model) {
        return “chat”;
    }

}

 

7. 테스트

브라우저 여러 개를 띄워, 도메인:포트/chat (예를 들어 localhost:8080/chat) 에 접속한 후 채팅을 해보자.