반응형
1) 채팅시스템 (WebSocket이용)
webapp/chat/chat.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:set var="port" value="${pageContext.request.localPort}"/>
<c:set var="server" value="${pageContext.request.serverName}"/>
<c:set var="path" value="${pageContext.request.contextPath}"/>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>WebSocket Chat</title>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
<script type="text/javascript">
$(function(){
//서버에서 수신할 수 있는 준비 필요
let ws = new WebSocket("ws://${server}:${port}${path}/chatting");
let username = "User" + Math.floor(Math.random() * 1000);
let sessionId = null;
//서버와 연결 성공된 경우
ws.onopen = function() {
$("#chatStatus").text("메시지 💨");
console.log("WebSocket opened for user:", username);
// 이벤트 중복 방지
$("input[name=chatInput]").off('keydown').on("keydown", function(evt) {
if (evt.keyCode == 13) {
//enter키가 눌리면 sendMessage호출
sendMessage();
}
});
//class="send-btn"을 클릭해도 sendMessage호출
$(".send-btn").off('click').on("click", sendMessage);
};
function sendMessage() {
let msg = $("input[name=chatInput]").val().trim();
if (msg !== "") {
let payload = JSON.stringify({ username: username, message: msg });
ws.send(payload);
console.log("Sent:", payload);
$("input[name=chatInput]").val("");
}
}
//onmessage: 서버로부터 메시지를 받으면 실행
ws.onmessage = function(event) {
let data = JSON.parse(event.data);
console.log("Received:", data);
let $msgDiv = $('<div>').addClass('message').text(data.message);
if (data.username === username) {
$msgDiv.addClass('sent');
} else {
$msgDiv.addClass('received');
}
$(".chat-messages").append($msgDiv);
$(".chat-messages").scrollTop($(".chat-messages")[0].scrollHeight);
};
//onclose: 연결 종료 시 상태를 "connection close"로 표시.
ws.onclose = function(event) {
$("#chatStatus").text("info: connection closed");
console.log("WebSocket closed:", event);
};
ws.onerror = function(event) {
$("#chatStatus").text("error: connection failed");
console.error("WebSocket error:", event);
};
});
</script>
</head>
<body>
<div class="chat-container">
<div id="chatStatus"></div>
<div class="chat-messages"></div>
<div class="chat-input-container">
<input type="text" name="chatInput" class="w3-input" placeholder="메시지를 입력하세요...">
<button class="send-btn">➤</button>
</div>
</div>
<textarea name="chatMsg" rows="15" cols="40" class="w3-input" style="display:none;"></textarea>
</body>
</html>
kr.gdu/webSocekt / EchoHandler.java
package kr.gdu.webSocket;
import java.util.HashSet;
import java.util.Set;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.WebSocketMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;
@Component
public class EchoHandler extends TextWebSocketHandler implements InitializingBean {
private Set<WebSocketSession> clients = new HashSet<>();
//클라이언트로부터 요청이들어오고 연결완료 후
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
//session : 웹소켓 접속객체의 고유한ID값
super.afterConnectionEstablished(session);
System.out.println("클라이언트 접속 : "+session.getId());
clients.add(session);
}
//메시지가 수신된 경우
@Override
public void handleMessage
(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
/* loadMessage : 클라이언트가 전송한 메시지 */
String loadMessage = (String)message.getPayload();
System.out.println(session.getId()+" > 클라이언트 메시지 : "+loadMessage);
//클라이언트의 session을 clients(map)에 추가
clients.add(session);
for (WebSocketSession s : clients) {
// s : 접속 된 클라이언트 객체
s.sendMessage(new TextMessage(loadMessage));
}
}
@Override
public void handleTransportError(WebSocketSession session, Throwable exception)
throws Exception {
super.handleTransportError(session, exception);
System.out.println("오류발생 : "+exception.getMessage());
}
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
super.afterConnectionClosed(session, status);
System.out.println("클라이언트 접속 해제 : "+status.getReason());
clients.remove(session);
}
@Override
public void afterPropertiesSet() throws Exception { }
}
config/WebSocketConfig.java
package kr.gdu.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
import kr.gdu.webSocket.EchoHandler;
@Configuration
@EnableWebSocket //웹소켓 처리
public class WebSocketConfig implements WebSocketConfigurer{
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
//chatting : 웹소켓에서 호출되는URL정보
// ws://localhost:8080/chatting
registry.addHandler(new EchoHandler(),"chatting")
.setAllowedOrigins("*");
}
}
ChatController (그냥 주소매핑말고는 하는게없음)
package kr.gdu.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("chat")
public class ChatController {
@RequestMapping("*")
public String chat() {
return null;
}
}
'Spring' 카테고리의 다른 글
parameter값 or logic대신 Dto객체 사용 (0) | 2025.06.22 |
---|---|
Exception과 AOP의 동작원리 (2) | 2025.06.21 |
부트캠프88일차(ajax 2) (0) | 2025.06.17 |
부트캠프87일차 (ajax) (2) | 2025.06.16 |
부트캠프86일차 (interceptor) (1) | 2025.06.13 |