Framework/Spring Framework

(22.12.30)Spring ํ”„๋ ˆ์ž„์›Œํฌ:WebSocket์„ ์‚ฌ์šฉํ•œ ์ฑ„ํŒ… ํ”„๋กœ๊ทธ๋žจ ๋งŒ๋“ค๊ธฐ

ํ”„๋กœ๊ทธ๋ž˜๋จธ ์˜ค์›” 2022. 12. 30.

๋ชฉ์ฐจ๏„ƒ

WebSocket์„ ์‚ฌ์šฉํ•œ ์ฑ„ํŒ… ํ”„๋กœ๊ทธ๋žจ ๋งŒ๋“ค๊ธฐ

- Spring boot ๊ธฐ๋ฐ˜ ๊ณ ์ˆ˜์ค€

- ์›น์‚ฌ์ดํŠธ ์ ‘์†์ž ์ „์ฒด๋ฅผ ๋Œ€์ƒ์œผ๋กœ ํ•œ ์ฑ„ํŒ…

- ํŠน์ • ์ด์šฉ์ž ๊ทธ๋ฃน/๊ฐœ์ธ์„ ๋Œ€์ƒ์œผ๋กœ ํ•œ ์ฑ„ํŒ…

(์‘์šฉ ์˜ˆ์‹œ: ์ฑ—๋ด‡ , ์ฑ„ํŒ…)

-์›น ์„œ๋ฒ„์ƒ์— ์„œ๋ฒ„ ์†Œ์ผ“์„ ๋‘๊ณ  ์›น๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์„œ๋ฒ„์†Œ์ผ“์— ์ ‘์†์š”์ฒญํ•˜๋Š” ๊ฐœ๋…(์›น์„œ๋ฒ„-์›น๋ธŒ๋ผ์šฐ์ € ๊ฐ„์˜ ํ†ต์‹ )

-http ํ”„๋กœํ† ์ฝœ์€ ์ ‘์†์š”์ฒญ ํ›„ ์ ‘์†๋˜๋ฉด ์‘๋‹ต์„ ์ „์†กํ•˜๊ณ  ์ ‘์† ํ•ด์ œ

 

ServerSocket : ๋„คํŠธ์›์„œ๋ฒ„, ๋ฌดํ•œํžˆ ํด๋ผ์ด์–ธํŠธ๋ฅผ ๋Œ€๊ธฐํ•จ

Socket : ์„œ๋ฒ„์— ์ ‘์† ์š”์ฒญ์„ ํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ์ด ์žˆ๋‹ค. ํ†ต์‹ ๊ธฐ๋Šฅ์ด ๋“ค์–ด์žˆ๋‹ค.(์ž๋ฐ” ๊ฒฝ์šฐ)

 

 


์ €์ˆ˜์ค€์˜ ์†Œ์ผ“๊ณผ ์„œ๋ฒ„์†Œ์ผ“  ๋ง๊ณ  ๊ณ ์ˆ˜์ค€์˜ ์›น์†Œ์ผ“์„ ์‚ฌ์šฉํ•˜์—ฌ ํ”„๋กœ๊ทธ๋ž˜๋ฐํ•˜๊ธฐ

 

์›น ์†Œ์ผ“ ์„ค์ •ํ•˜๊ธฐ - main Class

(22.12.30)Spring ํ”„๋ ˆ์ž„์›Œํฌ:WebSocket์„ ์‚ฌ์šฉํ•œ ์ฑ„ํŒ… ํ”„๋กœ๊ทธ๋žจ ๋งŒ๋“ค๊ธฐ

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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;
import org.springframework.web.bind.annotation.ResponseBody;
import lombok.extern.slf4j.Slf4j;
 
@Controller
@Slf4j
@RequestMapping("/ws")
public class ChatController 
{
    @RequestMapping("/")
    @ResponseBody
    public String index() {
        return "WebSocket Test";
    }
    
    @RequestMapping(value = "/chat", method = RequestMethod.GET)
    public String chat(Locale locale, Model model) {
        return "thymeleaf/chat";
    }
}
cs

 

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
import java.util.ArrayList;
import jakarta.websocket.EndpointConfig;
import jakarta.websocket.OnClose;
import jakarta.websocket.OnError;
import jakarta.websocket.OnMessage;
import jakarta.websocket.OnOpen;
import jakarta.websocket.Session;
import jakarta.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. ");
        }
    }
 
    /* ์›น์†Œ์ผ“ ์ด์šฉ์ž๋กœ๋ถ€ํ„ฐ ๋ฉ”์‹œ์ง€๊ฐ€ ์ „๋‹ฌ๋œ ๊ฒฝ์šฐ ์‹คํ–‰๋จ */
    @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;
    }
}
cs

 

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
<!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() {
        //host = "152.70.92.222";   /* ๋ฐฐํฌ์‹œ์— ํ˜ธ์ŠคํŠธ ์ฃผ์†Œ๋กœ ๋ณ€๊ฒฝ */
        host = "localhost";
        g_webSocket = new WebSocket("ws://" + host + "/websocket");
 
        /* ์›น์†Œ์ผ“ ์ ‘์† ์„ฑ๊ณต์‹œ ์‹คํ–‰ */
        g_webSocket.onopen = function(message) {
            addLineToChatBox("Server is connected.");
        };
 
        /* ์›น์†Œ์ผ“ ์„œ๋ฒ„๋กœ๋ถ€ํ„ฐ ๋ฉ”์‹œ์ง€ ์ˆ˜์‹ ์‹œ ์‹คํ–‰ */
        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"); //$('#inputMsgBox').val();
        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;
        }
 
        // ์—”ํ„ฐํ‚ค ๋ˆ„๋ฅผ ๊ฒฝ์šฐ ์„œ๋ฒ„๋กœ ๋ฉ”์‹œ์ง€ ์ „์†ก keyCode 13์€ ์—”ํ„ฐํ‚ค๋ฅผ ๋งํ•œ๋‹ค.
        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>
cs

 

window.onload ์›น๋ธŒ๋ผ์šฐ์ €์ฐฝ์— html๋ฌธ์„œ๊ฐ€ ๋กœ๋“œ๊ฐ€ ๋‹ค ๋œ๊ฒฝ์šฐ "/websocket" -> @ServerEndpoint("/websocket")์— ์—ฐ๊ฒฐ ๋˜๋ฉด g_webSocket ํ†ต์‹  ์†Œ์ผ“ ์ƒ์„ฑ

ํ†ต์‹ ์†Œ์ผ“์˜ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ๋‹ฌ์•„์ค€๋‹ค.

 

์‹คํ–‰๊ฒฐ๊ณผ : 

(22.12.30)Spring ํ”„๋ ˆ์ž„์›Œํฌ:WebSocket์„ ์‚ฌ์šฉํ•œ ์ฑ„ํŒ… ํ”„๋กœ๊ทธ๋žจ ๋งŒ๋“ค๊ธฐ

 

 

(22.12.30)Spring ํ”„๋ ˆ์ž„์›Œํฌ:WebSocket์„ ์‚ฌ์šฉํ•œ ์ฑ„ํŒ… ํ”„๋กœ๊ทธ๋žจ ๋งŒ๋“ค๊ธฐ

 


 

ํŠน์ • ์ด์šฉ์ž๊ฐ„์˜ ํ†ต์‹ (์ฑ„ํŒ…)

๋กœ๊ทธ์ธํ•œ ํ›„ ์ด์šฉ์ž์˜ ์•„์ด๋”” ํ™œ์šฉ(HttpSession)

WebSocket ํด๋ž˜์Šค์—์„œ ๋ฉ”์‹œ์ง€ ์†ก์ˆ˜์‹  ๋ถ€๋ถ„์—์„œ

ํŠน์ • ์•„์ด๋””๋ฅผ ๊ฐ€์ง„ ์ด์šฉ์ž์˜ ์†Œ์ผ“์— ๋ฉ”์‹œ์ง€๋ฅผ ์ „์†ก ํ•ด์•ผ ํ•œ๋‹ค.

๋ฉ”์„ธ์ง€ ๊ตฌ์„ฑ(์„œ๋ฒ„์ชฝ์— json ์œผ๋กœ ๋ณด๋‚ธ๋‹ค)

-์†ก์‹ ์ž, ์ˆ˜์‹ ์ž, ์ปจํ…์ธ 

์„œ๋ฒ„์ธก์—์„œ๋Š” ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐ›์•„์„œ ์ˆ˜์‹ ์ž๊ฐ€ ๋ˆ„๊ตฐ์ง€ ํ™•์ธํ•˜๊ณ  ๊ทธ ์‚ฌ๋žŒํ•œํ…Œ๋งŒ ๋ฐœ์†กํ•ด์•ผํ•œ๋‹ค.

์„œ๋ฒ„์ธก์—์„œ JSON์„ ๋‹ค๋ฃจ๊ธฐ ์œ„ํ•ด์„œ json-simple ์‚ฌ์šฉ (dependency ์ถ”๊ฐ€)

 

Controller / WebSocket

- Configurator : WebSocket์—์„œ HttpSession ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ์„ค์ •

 

๋กœ๊ทธ์ธํ•œ ํ›„ ์ด์šฉ์ž์˜ ์•„์ด๋”” ํ™œ์šฉ(HttpSession)ํ•˜์—ฌ ์ฑ„ํŒ… ํ•˜๊ธฐ

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import jakarta.servlet.ServletContext;
import jakarta.servlet.http.HttpSession;
import jakarta.websocket.HandshakeResponse;
import jakarta.websocket.server.HandshakeRequest;
import jakarta.websocket.server.ServerEndpointConfig;
import jakarta.websocket.server.ServerEndpointConfig.Configurator;
 
/** ServerEndPoint ํด๋ž˜์Šค(์›น์†Œ์ผ“ ์„œ๋ฒ„)์—์„œ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ์„ค์ •์ž ํด๋ž˜์Šค */
public class HttpSessionConfig extends Configurator //์ƒ์†์€ ๊ผญํ•ด์ค˜์•ผํ•œ๋‹ค.
{
   @Override
   public void modifyHandshake( //์ด ๋ฉ”์†Œ๋“œ๋„ ๊ผญ ํ•„์š”ํ•˜๋‹ค.
         /* ์•„๋ž˜์˜ config ์— ์ €์žฅํ•œ ๋‚ด์šฉ์€ ServerEndPoint ํด๋ž˜์Šค์— ์ „๋‹ฌ๋œ๋‹ค */
         ServerEndpointConfig config, 
         HandshakeRequest request, 
         HandshakeResponse response) 
   {
      HttpSession session = (HttpSession) request.getHttpSession();
      ServletContext context = session.getServletContext();
      
      /* ์œ„์—์„œ ๊ตฌํ•œ HttpSession ๊ฐ์ฒด์˜ ์ฐธ์กฐ๋ฅผ config์— ์ €์žฅํ•œ๋‹ค */
      config.getUserProperties().put("session", session);
      // ์•„๋ž˜์ฒ˜๋Ÿผ ๋‹ค์ˆ˜๊ฐœ์˜ ๊ฐ’๋„ ์ €์žฅ ๊ฐ€๋Šฅ
      config.getUserProperties().put("context", context);
   }
}
cs

 

 

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import java.util.Locale;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import com.ezen.spring.web.vo.User;
import jakarta.servlet.http.HttpSession;
import lombok.extern.slf4j.Slf4j;
 
@Controller
@Slf4j
@RequestMapping("/ws")
public class ChatController 
{    
    
    
    @RequestMapping("/")
    @ResponseBody
    public String index() {
        return "WebSocket Test";
    }
    @GetMapping("/login")
    public String login() {
        return "thymeleaf/loginForm";
    }
    @PostMapping("/login")
    public String login(HttpSession session, User user) {
        session.setAttribute("userid", user.getUserid());
        return "redirect:/ws/chat";
    }
    @RequestMapping(value = "/chat", method = RequestMethod.GET)
    public String chat(Locale locale, Model model) {
        return "thymeleaf/chat";
    }
}
cs

 

 

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
import java.util.*;
import jakarta.servlet.http.HttpSession;
import jakarta.websocket.EndpointConfig;
import jakarta.websocket.OnClose;
import jakarta.websocket.OnError;
import jakarta.websocket.OnMessage;
import jakarta.websocket.OnOpen;
import jakarta.websocket.Session;
import jakarta.websocket.server.ServerEndpoint;
import org.springframework.stereotype.Component;
 
@Component
@ServerEndpoint(value = "/websocket", configurator = HttpSessionConfig.class// ์„ค์ • ํด๋ž˜์Šค ์ด๋ฆ„์„ ๋„ฃ๋Š”๋‹ค.
public class WebSocket {
    /* ์›น์†Œ์ผ“ ์„ธ์…˜ ๋ณด๊ด€์šฉ ArrayList */
    // ๋ฆฌ์ŠคํŠธ ์“ฐ์ง€๋ง๊ณ  ๋งต์„ ์จ์„œ ์•„์ด๋””๋กœ ์•„์ด๋””์™€ ์„ธ์…˜์„ ๊ฐ€์ง„ ๋งต
    // private static ArrayList<Session> sessionList = new ArrayList<Session>();
    private static Map<String, Session> userMap = new HashMap<>();
 
    /* ์›น์†Œ์ผ“ ์‚ฌ์šฉ์ž ์ ‘์†์‹œ ํ˜ธ์ถœ๋จ */
    @OnOpen
    public void handleOpen(Session session, EndpointConfig config) {
        if (session != null) {
            String sessionId = session.getId();
 
            System.out.println("client is connected. sessionId == [" + sessionId + "]");
 
            HttpSession httpSession = (HttpSession) config.getUserProperties().get("session");
            String userid = (String) httpSession.getAttribute("userid");
            userMap.put(userid, session);
            /* ์›น์†Œ์ผ“์— ์ ‘์†ํ•œ ๋ชจ๋“  ์ด์šฉ์ž์—๊ฒŒ ๋ฉ”์‹œ์ง€ ์ „์†ก */
            sendMessageToAll("--> [USER-" + userid + "] is connected. ");
        }
    }
 
    /* ์›น์†Œ์ผ“ ์ด์šฉ์ž๋กœ๋ถ€ํ„ฐ ๋ฉ”์‹œ์ง€๊ฐ€ ์ „๋‹ฌ๋œ ๊ฒฝ์šฐ ์‹คํ–‰๋จ */
    @OnMessage
    public String handleMessage(String message, Session session) {
        if (session != null) {
            //String sessionId = session.getId();
            String findUserid = "";
            for (String userid : userMap.keySet()) {
                if (userMap.get(userid).equals(session)) { // ํ‚ค๊ฐ€ null์ด๋ฉด NullPointerException ์˜ˆ์™ธ ๋ฐœ์ƒ
                    findUserid = userid;
                    break;
                }
            }
            System.out.println("message is arrived. sessionId == [" + findUserid + "] / message == [" + message + "]");
 
            /* ์›น์†Œ์ผ“์— ์ ‘์†ํ•œ ๋ชจ๋“  ์ด์šฉ์ž์—๊ฒŒ ๋ฉ”์‹œ์ง€ ์ „์†ก */
            sendMessageToAll("[USER-" + findUserid + "] " + 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 (userMap == null) {
            return false;
        }
 
        int sessionCount = userMap.size();
        if (sessionCount < 1) {
            return false;
        }
 
        Session singleSession = null;
 
        for (int i = 0; i < sessionCount; i++) {
            List<Session> list = new ArrayList<>(userMap.values());
            singleSession = list.get(i);
            if (singleSession == null) {
                continue;
            }
 
            if (!singleSession.isOpen()) {
                continue;
            }
 
            list.get(i).getAsyncRemote().sendText(message);
            // ์„ธ์…˜ ๋ฆฌ์ŠคํŠธ์—์„œ ์„ธ์…˜์„ ๊บผ๋‚ด
        }
 
        return true;
    }
}
 
cs

 

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>๋กœ๊ทธ์ธํ•ด์ฃผ์„ธ์š”</title>
<style>
   label{display:inline-block;width:3em; text-align: right; 
      margin-right:1em; }
   input { width: 5em; }
   form {width:fit-content; padding:0.5em; margin:0 auto; 
      border:1px solid black;}
   button { margin: 5px; }
   div:last-child { text-align: center;
</style>
</head>
<body>
<h1>๋กœ๊ทธ์ธ</h1>
<form action="/ws/login" method="post">
   <input id="cmd" type="hidden" name="cmd" value="login">
   <div><label>์•„์ด๋””</label> 
      <input id="uid" type="text" name="userid" value="">
   </div>
   <div><label>์•” ํ˜ธ</label> 
      <input id="pwd" type="password" name="userpwd" value="">
   </div>
   <div><button type="submit">๋กœ๊ทธ์ธ</button></div>
</form>
</body>
</html>
cs

 

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
<!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() {
        //host = "152.70.92.222";   /* ๋ฐฐํฌ์‹œ์— ํ˜ธ์ŠคํŠธ ์ฃผ์†Œ๋กœ ๋ณ€๊ฒฝ */
        host = "localhost";
        g_webSocket = new WebSocket("ws://" + host + "/websocket");
 
        /* ์›น์†Œ์ผ“ ์ ‘์† ์„ฑ๊ณต์‹œ ์‹คํ–‰ */
        g_webSocket.onopen = function(message) {
            addLineToChatBox("Server is connected.");
        };
 
        /* ์›น์†Œ์ผ“ ์„œ๋ฒ„๋กœ๋ถ€ํ„ฐ ๋ฉ”์‹œ์ง€ ์ˆ˜์‹ ์‹œ ์‹คํ–‰ */
        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"); //$('#inputMsgBox').val();
        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;
        }
 
        // ์—”ํ„ฐํ‚ค ๋ˆ„๋ฅผ ๊ฒฝ์šฐ ์„œ๋ฒ„๋กœ ๋ฉ”์‹œ์ง€ ์ „์†ก keyCode 13์€ ์—”ํ„ฐํ‚ค๋ฅผ ๋งํ•œ๋‹ค.
        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>
cs

 

์‹คํ–‰ ๊ฒฐ๊ณผ : 

(22.12.30)Spring ํ”„๋ ˆ์ž„์›Œํฌ:WebSocket์„ ์‚ฌ์šฉํ•œ ์ฑ„ํŒ… ํ”„๋กœ๊ทธ๋žจ ๋งŒ๋“ค๊ธฐ
๋กœ๊ทธ์ธ 1

 

(22.12.30)Spring ํ”„๋ ˆ์ž„์›Œํฌ:WebSocket์„ ์‚ฌ์šฉํ•œ ์ฑ„ํŒ… ํ”„๋กœ๊ทธ๋žจ ๋งŒ๋“ค๊ธฐ
๋กœ๊ทธ์ธ 2

 

(22.12.30)Spring ํ”„๋ ˆ์ž„์›Œํฌ:WebSocket์„ ์‚ฌ์šฉํ•œ ์ฑ„ํŒ… ํ”„๋กœ๊ทธ๋žจ ๋งŒ๋“ค๊ธฐ

 

(22.12.30)Spring ํ”„๋ ˆ์ž„์›Œํฌ:WebSocket์„ ์‚ฌ์šฉํ•œ ์ฑ„ํŒ… ํ”„๋กœ๊ทธ๋žจ ๋งŒ๋“ค๊ธฐ

 

 

(22.12.30)Spring ํ”„๋ ˆ์ž„์›Œํฌ:WebSocket์„ ์‚ฌ์šฉํ•œ ์ฑ„ํŒ… ํ”„๋กœ๊ทธ๋žจ ๋งŒ๋“ค๊ธฐ

 

(22.12.30)Spring ํ”„๋ ˆ์ž„์›Œํฌ:WebSocket์„ ์‚ฌ์šฉํ•œ ์ฑ„ํŒ… ํ”„๋กœ๊ทธ๋žจ ๋งŒ๋“ค๊ธฐ

๋Œ“๊ธ€