dependency - pom
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
테스트용으로 생성하며 thymeleaf , web , websocket , devtools 만 추가
application.properties
server.port=7181
#### thymeleaf
spring.thymeleaf.prefix=classpath:templates/
spring.thymeleaf.check-template-location=true
spring.thymeleaf.suffix=.html
spring.thymeleaf.mode=HTML5
spring.thymeleaf.cache=false
spring.thymeleaf.order=0
port 및 thymeleaf 설정
templates 폴더 아래 html을 읽어온다
html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
<head>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4" crossorigin="anonymous"></script>
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
</head>
<body>
<div>
<div class="container">
<div class="col-6">
<label><b>웹소켓 테스트</b></label>
</div>
<div>
<div id="msgArea" class="col"></div>
<div class="col-6">
<div class="input-group mb-3">
<input type="text" id="msg" class="form-control" aria-label="Recipient's username" aria-describedby="button-addon2">
<div class="input-group-append">
<button class="btn btn-outline-secondary" type="button" id="send">전송</button>
</div>
</div>
</div>
</div>
</div>
</div>
<script th:inline="javascript">
$(document).ready(function(){
const username = [[${ip}]];
$("#send").on("click", (e) => {
let msg = document.getElementById("msg");
websocket.send(username + ":" + msg.value);
msg.value = '';
});
// test로 localhost로 진행함, ip 지정해서 사용하면 됨
const websocket = new WebSocket("ws://localhost:7181/ws/test");
websocket.onmessage = onMessage;
websocket.onopen = onOpen;
// websocket.onclose = onClose;
//채팅창에서 나갔을 때 (나가기 버튼 미구현)
// function onClose(evt) {
// let str = username + ": 님이 방을 나가셨습니다.";
// websocket.send(str);
// }
//채팅창에 들어왔을 때
function onOpen(evt) {
let str = username + ": 님이 입장하셨습니다.";
websocket.send(str);
}
function onMessage(msg) {
let data = msg.data;
let sessionId = null;
let message = null;
let arr = data.split(":");
let cur_session = username;
//현재 로그인 한 사람
sessionId = arr[0];
// arr[1] 은 메세지
if(arr.length > 1){
message = arr[1];
}
// 자신과 다른 client를 구분해서 메세지 출력
if(sessionId == cur_session && message != null){
let str = "<div class='col-6'>";
str += "<div style='text-align: right'>";
str += "<b>" + sessionId + " : " + message + "</b>";
str += "</div></div>";
$("#msgArea").append(str);
}
else if(sessionId != cur_session && message != null){
let str = "<div class='col-6'>";
str += "<div style='text-align: left'>";
str += "<b>" + sessionId + " : " + message + "</b>";
str += "</div></div>";
$("#msgArea").append(str);
}
else {
let str = "<div class='col-6'>";
str += "<div style='background-color: darksalmon'>";
str += "<b>" + sessionId + "</b>";
str += "</div></div>";
$("#msgArea").append(str);
}
}
})
</script>
</body>
</html>
bootstrap 과 jquery를 cdn 으로 사용 중
WebSocketHandler
import org.springframework.stereotype.Component;
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 java.util.ArrayList;
import java.util.List;
@Component
public class WebSocketHandler extends TextWebSocketHandler {
// 연결된 client 웹소켓 세션 정보를 담기 위함
private static List<WebSocketSession> list = new ArrayList<>();
protected void handleTextMessage(WebSocketSession session , TextMessage message) throws Exception{
String payload = message.getPayload();
System.err.println("payload : " + payload);
for(WebSocketSession sess : list){
sess.sendMessage(message);
}
}
// client 접속
public void afterConnectionEstablished(WebSocketSession session) throws Exception{
list.add(session);
System.err.println(session + " client 접속");
}
// client 접속 해제
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception{
list.remove(session);
System.err.println(session + "client 접속 해제");
// 접속해있는 client들에게 메세지 전송
for(WebSocketSession sess : list){
sess.sendMessage(new TextMessage("상대방이 퇴장하였습니다."));
}
}
}
WebSocketConfig
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;
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
private final WebSocketHandler webSocketHandler;
public WebSocketConfig(WebSocketHandler webSocketHandler){
this.webSocketHandler = webSocketHandler;
}
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(webSocketHandler, "/ws/test").setAllowedOrigins("*");
}
}
Controller
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class TestController {
@GetMapping("/")
public String index(Model model) throws Exception{
// 임의의 숫자 ID
// 로그인 및 이름이나 ID를 지정하는 기능이 없어서 현재 접속하는 Client에게 1~100 사이의 무작위 숫자를 부여
int a = (int)(Math.random() * 100) + 1;
model.addAttribute("ip" , a);
return "index";
}
}
프로젝트 폴더 구조
테스트
'개발 > Spring' 카테고리의 다른 글
[SpringBoot] Interceptor 구현하기 (0) | 2024.06.18 |
---|---|
[SpringBoot] Gradle + React 같이 빌드하기 (0) | 2024.06.17 |
[SpringBoot] Cors 적용 및 테스트 하기 (0) | 2024.05.11 |
[SpringBoot] 외부 파일 불러오기 (0) | 2024.05.08 |
[SpringBoot] DataTable(JavaScript) - 적용하기 (0) | 2024.05.05 |
댓글