Spring

Spring 20 - 웹소켓(WebSocket) - 실시간 채팅

inderrom 2023. 2. 9. 03:20

1. <!-- 웹소켓 의존성 추가 -->
<!-- https://mvnrepository.com/artifact/org.springframework/spring-websocket -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-websocket</artifactId>
<version>${org.springframework-version}</version>
</dependency>

2. 클래스 생성
extends TextWebSocketHandler

Override 메소드 생성
afterConnectionEstablished
afterConnectionClosed
handleTextMessage
handleTransportError

3. servlet-context 
맨 위 beans에 추가
xmlns:websocket="http://www.springframework.org/schema/websocket"
schemaLocation = 
http://www.springframework.org/schema/websocket
http://www.springframework.org/schema/websocket/spring-websocket.xsd

아래 추가
<websocket:handlers allowed-origins="*" >
<websocket:mapping handler="wsHandler" path="/socket" />
<websocket:handshake-interceptors>
<beans:bean class="org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor"/>
</websocket:handshake-interceptors>
<websocket:sockjs websocket-enabled="true"/>
</websocket:handlers>
    <beans:bean id="wsHandler" class="kr.or.ddit.controller.SpringWs" />

* mapping에 handler == beans에 id
* mapping에 path는 소켓 연결path
* beans에 class는 소켓 서버클래스의 패키지경로.클래스명

4. jsp 소켓 연결
var webSocket = new SockJS("/ws/socket");

 


 

<ChatController2.java>

package kr.or.ddit.controller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@RequestMapping("/chat")
@Controller
public class ChatController2 {
	
	private static Logger logger = LoggerFactory.getLogger(ChatController2.class);
	
//	@RequestMapping(value = "/home", method = RequestMethod.GET)
//	public String chat () {
//		return "multiChatMain";
//	}
//	
	@RequestMapping(value="/room", method=RequestMethod.GET)
	public String chatWindow () {
		return "chatWindow";
	}
	
}

 

<webSocket.java>

package kr.or.ddit.controller;

import java.util.ArrayList;
import java.util.List;

import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class webSocket extends TextWebSocketHandler {
	
	private List<WebSocketSession> sessionList = new ArrayList<WebSocketSession>();
	
	
	// 클라이언트가 연결 되었을 때 실행
	@Override
	public void afterConnectionEstablished(WebSocketSession session) throws Exception {
		
		sessionList.add(session);
		log.info("{}연결됨",session.getId());
	}
	
	// 클라이언트가 웹소켓 서버로 메세지를 전송했을 때 실행
	@Override
	protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {

		log.info("{}로 부터 {} 받음", session.getId(), message.getPayload());
		// 모든 유저에게 메세지 출력
		//for(WebSocketSession sess : sessionList) {
		//	sess.sendMessage(new TextMessage(message.getPayload()));
			
			String msg = message.getPayload();
		
			for(WebSocketSession s : sessionList) {
				s.sendMessage(new TextMessage(session.getAcceptedProtocol() + msg));
			}
		}
	//}
	
	// 전송에 에러가 났을 때 실행함.
//	@Override
//	public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
//	}
	
	// 클라이언트 연결을 끊었을 떄 실행
	@Override
	public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
		sessionList.remove(session);
		log.info("{} 연결 끊김", session.getId());
	}
}

 

<chatWindow.jsp>

  • 엔터를 눌렀을 때 전송
  • input에 속성을 준다.
  • onkeydown="if(event.keyCode==13){send();}"
<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<script src="https://cdn.jsdelivr.net/npm/sockjs-client@1/dist/sockjs.min.js"></script>
    
</head>
<body>
	<div id="one">
		별명:<input type="text" id="nickname" /> <input type="button"
			id="enter" value="입장" />
	</div>
	<div id="two" style="display: none">
		<input type="button" id="exit" value="퇴장" /><br />
		<div id="chatarea"
			style="width: 400px; height: 600px; border: 1px solid;"></div>
		<input type="text" id="message" onkeydown="if(event.keyCode==13){send();}" /> />
		 <input type="button" id="send"
			value="보내기" />
	</div>
</body>
<script type="text/javascript">
	var websocket = null;
	one = document.getElementById("one");
	two = document.getElementById("two");
	document.getElementById("enter").addEventListener("click", function() {
		//웹 소켓 연결해주는 함수 호출
		connect();
	});
	document.getElementById("exit").addEventListener("click", function() {
		//연결을 해제해주는 함수 호출
		disconnect();
	});
	document.getElementById("send").addEventListener("click", function() {
		//연결을 해제해주는 함수 호출
		send();
	});
	var websocket;
	//입장 버튼을 눌렀을 때 호출되는 함수
	function connect() {
		websocket = new SockJS("/socket");
		//websocket = new WebSocket("ws://localhost:80/socket");
		//웹 소켓에 이벤트가 발생했을 때 호출될 함수 등록
		websocket.onopen = onOpen;
		websocket.onmessage = onMessage;
		websocket.onclose = onClose;
	}
	//퇴장 버튼을 눌렀을 때 호출되는 함수
	function disconnect() {
		msg = document.getElementById("nickname").value;
		websocket.send(msg + "님이 퇴장하셨습니다");
		websocket.close();
	}
	//보내기 버튼을 눌렀을 때 호출될 함수
	function send() {
		nickname = document.getElementById("nickname").value;
		msg = document.getElementById("message").value;
		websocket.send(nickname + ":" + msg);
		document.getElementById("message").value = "";
	}
	//웹 소켓에 연결되었을 때 호출될 함수
	function onOpen() {
		console.log("open");
		nickname = document.getElementById("nickname").value;
		two = document.getElementById("two");
		two.style.display = 'block';
		websocket.send(nickname + "님 입장하셨습니다.");
	}
	//웹 소켓에서 연결이 해제 되었을 때 호출될 함수
	function onMessage(evt) {
		data = evt.data;
		chatarea = document.getElementById("chatarea");
		chatarea.innerHTML = data + "<br/>" + chatarea.innerHTML
	}
	function onClose() {
	}
</script>
</html>

 


localhost/chat/room 으로 들어가게 되면

채팅이 실행된다.

 

 

참고

https://alswns1201.medium.com/spring-websocket-%EC%B1%84%ED%8C%85-c662b33dcb0b