STOMP 설정하기
환경설정
pom.xml
<!-- 스프링 웹소켓 의존성 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-websocket</artifactId>
<version>5.3.5</version> <!-- 사용하는 스프링 버전에 맞게 조정 -->
</dependency>
<!-- 스프링 메시징 의존성 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-messaging</artifactId>
<version>5.3.5</version> <!-- 사용하는 스프링 버전에 맞게 조정 -->
</dependency>
servlet.context.xml
xmlns:websocket="http://www.springframework.org/schema/websocket"
xsi:schemaLocation="http://www.springframework.org/schema/websocket http://www.springframework.org/schema/websocket/spring-websocket-4.3.xsd
config 코드
package com.study.config;
import java.util.List;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.converter.DefaultContentTypeResolver;
import org.springframework.messaging.converter.MappingJackson2MessageConverter;
import org.springframework.messaging.converter.MessageConverter;
import org.springframework.messaging.handler.invocation.HandlerMethodArgumentResolver;
import org.springframework.messaging.handler.invocation.HandlerMethodReturnValueHandler;
import org.springframework.messaging.simp.config.ChannelRegistration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.util.MimeTypeUtils;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketTransportRegistration;
import com.fasterxml.jackson.databind.ObjectMapper;
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.enableSimpleBroker("/topic/"); // 클라이언트가 구독할 수 있는 주소의 prefix
registry.setApplicationDestinationPrefixes("/app"); // 메시지를 보낼 때 사용할 prefix
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
System.out.println("초기화 : "+ registry);
registry.addEndpoint("/stomp-endpoint").withSockJS();
}
@Override
public void configureWebSocketTransport(WebSocketTransportRegistration registry) {
// TODO Auto-generated method stub
}
@Override
public void configureClientInboundChannel(ChannelRegistration registration) {
// TODO Auto-generated method stub
}
@Override
public void configureClientOutboundChannel(ChannelRegistration registration) {
// TODO Auto-generated method stub
}
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
// TODO Auto-generated method stub
}
@Override
public void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> returnValueHandlers) {
// TODO Auto-generated method stub
}
@Override
public boolean configureMessageConverters(List<MessageConverter> converters) {
DefaultContentTypeResolver resolver = new DefaultContentTypeResolver();
resolver.setDefaultMimeType(MimeTypeUtils.APPLICATION_JSON);
MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();
converter.setObjectMapper(new ObjectMapper());
converter.setContentTypeResolver(resolver);
converters.add(converter);
return false; // 기본 컨버터를 추가하지 않음
}
}
jsp코드
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page session="false" %>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>WebSocket Chatting</title>
</head>
<body>
<div>
<button type="button" id="connect" onclick="openSocket();">대화방 참여</button>
<button type="button" id="disconnect" onclick="closeSocket();">대회방 나가기</button>
<br/><br/><br/>
메세지 입력 :
<input type="text" id="sender" value="${sessionScope.id}" style="display: none;">
<input type="text" id="messageinput">
<button type="button" onclick="send();">메세지 전송</button>
<button type="button" onclick="javascript:clearText();">대화내용 지우기</button>
</div>
<div id="messages">
</div>
<script src="https://cdn.jsdelivr.net/npm/sockjs-client/dist/sockjs.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/stompjs/lib/stomp.min.js"></script>
<script type="text/javascript">
var socket = new SockJS('/assetmanager/stomp-endpoint');
var stompClient = Stomp.over(socket);
var messages = document.getElementById("messages");
function openSocket() {
if (stompClient !== null && stompClient.connected) {
writeResponse("WebSocket is already opened.");
return;
}
var socket = new SockJS("/assetmanager/stomp-endpoint");
stompClient = Stomp.over(socket);
stompClient.connect({}, function(frame) {
setConnected(true);
console.log('Connected: ' + frame);
stompClient.subscribe('/topic/greetings', function(greeting) {
console.log('Received: ', JSON.parse(greeting.body).content);
showGreeting(JSON.parse(greeting.body).content);
});
},
function(error) { // 연결 실패 콜백
console.log('연결 안됨: ' + error);
}
);
console.log("연결프로세스종료");
}
function setConnected(connected) {
document.getElementById("connect").disabled = connected;
document.getElementById("disconnect").disabled = !connected;
if (connected) {
messages.style.display = "";
} else {
messages.style.display = "none";
}
}
function send() {
var name = document.getElementById("messageinput").value;
stompClient.send("/app/hello", {}, JSON.stringify({ 'name': name }));
}
function closeSocket() {
if (stompClient !== null) {
stompClient.disconnect();
}
setConnected(false);
console.log("Disconnected");
}
function showGreeting(message) {
var messages = document.getElementById("messages");
messages.innerHTML += "<br/>" + message;
}
function clearText() {
var messages = document.getElementById("messages");
messages.innerHTML = "";
}
</script>
</body>
</html>
controller
@MessageMapping("/hello") // 클라이언트에서 보낸 메시지를 받을 경로
@SendTo("/topic/greetings") // 메시지를 다시 발행할 경로
public GreetingVO greeting(HelloMessageVO message) throws Exception {
Date now = new Date();
System.out.println(now);
return new GreetingVO(HtmlUtils.htmlEscape(message.getName()));
}