반응형
메이븐 라이브러리 불러오기
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-websocket</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
- 웹소켓은 데이터 이동방식이 JSON형식이라 jackson이 필요함
- 미들웨어는 8.5이상 지원
- 스프링은 2.5버전 이상 지원되고
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:websocket="http://www.springframework.org/schema/websocket"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/websocket http://www.springframework.org/schema/websocket/spring-websocket-4.3.xsd">
<websocket:handlers allowed-origins="*" >
<websocket:mapping handler="handlerChat" path="/chat" />
<websocket:sockjs websocket-enabled="true" />
</websocket:handlers>
<bean id="handlerChat" class="com.chat.handler.HandlerChat" />
</beans>
하위 컨테이너에 bean 설정해줘야한다
@Component
public class HandlerChat extends TextWebSocketHandler {
// 세션리스트를 담을 List(나중에는 세션접속자의 정보까지 들고와야해서 Map으로 바꿔야함)
private List<WebSocketSession> sessionList = new ArrayList<WebSocketSession>();
// 클라이언트가 처음 접속했을때(init역할)
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
// 채팅방에 접속한 사용자 세션을 리스트에 저장
sessionList.add(session);
// 모든 세션에 채팅 전달
for (int i = 0; i < sessionList.size(); i++) {
WebSocketSession s = sessionList.get(i);
s.sendMessage(new TextMessage(session.getId() + "님이 입장 했습니다."));
}
}
// 클라이언트에서 메세지가 전달되면
// 서버에서 모든 클라이언트에 전송
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
// 모든 세션에 채팅 전달
for (int i = 0; i < sessionList.size(); i++) {
WebSocketSession s = sessionList.get(i);
s.sendMessage(new TextMessage(session.getId() + " : " + message.getPayload()));
}
}
// 클라이언트가 연결을 끊음 처리
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
// 채팅방에서 퇴장한 사용자 세션을 리스트에서 제거
sessionList.remove(session);
// 모든 세션에 연결종료채팅 전달
for (int i = 0; i < sessionList.size(); i++) {
WebSocketSession s = sessionList.get(i);
s.sendMessage(new TextMessage(session.getId() + "님이 퇴장 했습니다."));
}
}
}
새로운 세션이 접속하거나 메세지를 전송하면 socket핸들러에서 제어해서 메세지를 보낸다
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>웹소켓 채팅</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/sockjs-client/1.4.0/sockjs.js"></script>
<script type="text/javascript">
var webSocket = {
init: function(param) {
this._url = param.url;
this._initSocket();
},
sendChat: function() {
this._sendMessage($('#message').val());
$('#message').val('');
},
// 메세지 데이터가 들어오면 그 메세지를 보여줌
receiveMessage: function(str) {
$('#divChatData').append('<div>' + str + '</div>');
},
// 소켓에연결되지않음
closeMessage: function(str) {
$('#divChatData').append('<div>' + '연결 끊김 : ' + str + '</div>');
},
//소켓연결종료
disconnect: function() {
this._socket.close();
},
// 소켓연결
_initSocket: function() {
this._socket = new SockJS(this._url);
this._socket.onmessage = function(evt) {
webSocket.receiveMessage(evt.data);
};
// 종료이벤트
this._socket.onclose = function(evt) {
//(나갔다는 메세지를 출력)
webSocket.closeMessage(evt.data);
}
},
// 메세지가입력되면 HandlerChat.java로 문자를 모냄
_sendMessage: function(str) {
this._socket.send(str);
}
};
</script>
<script type="text/javascript">
$(document).ready(function() {
/* 서버의 url주로를 가져와서 init메소드에 넣어주면서 접속한다 */
webSocket.init({ url: '<c:url value="/chat" />' });
});
</script>
</head>
<body>
<div style="width: 800px; height: 700px; padding: 10px; border: solid 1px #e1e3e9;">
<div id="divChatData"></div>
</div>
<div style="width: 100%; height: 10%; padding: 10px;">
<input type="text" id="message" size="110" onkeypress="if(event.keyCode==13){webSocket.sendChat();}" />
<input type="button" id="btnSend" value="채팅 전송" onclick="webSocket.sendChat()" />
</div>
</body>
</html>
JSP에서 필요한 JS로 소켓 호출인데 여기서는 메세지 처리가 text이지만 JSON형태로 다양한 정보를 전달가능하다
속성의 종류
STOMP
websocket에서의 거의 유일한 단점은 클라이언트에서 전송받을수 있는 메세지가 규격이 없음인데 양 피어에서의 메세지를 합의하고 합의된 형식에 따라 메세지를 파싱하는 식으로 보안하다 STOMP라는 것을 알게되었다 stomp 는 상위와 같이 프레임 구조 가 명확하게 정의되어 있고, 발행/구독 형태의 메시지 전송 구조를 갖기 때문에 전송에 관련된 양 피어가 독립적으로 동작할 수 있는 구조를 갖는다 나중에 따로 한번 다뤄보려고 한다.
반응형
'Spring' 카테고리의 다른 글
VO와 DTO란(VO vs DTO 차이) (0) | 2021.07.25 |
---|---|
Reactive Stream 리액티브 스트림이란. (0) | 2021.07.10 |
Batch Job(일괄처리프로그램) (0) | 2021.07.01 |
IOC(DI)컨테이너 (0) | 2021.05.29 |
Spring에서 모듈(컨테이너) (0) | 2021.04.24 |