반응형
스프링부트에서 STOMP를 이용한 메세지 pub/sub 예시
build.gradle에서 라이브러리를 추가해주십쇼
implementation 'org.springframework.boot:spring-boot-starter-websocket'
웹소켓 설정파일 WebsocketConfig.java 을 아래와 같은 내용으로 생성
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
import lombok.RequiredArgsConstructor;
@Configuration
@EnableWebSocketMessageBroker
@RequiredArgsConstructor
public class WebsocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry registry){
// /pub으로 시작하는 요청은 @Controller의 @MessageMapping 메소드로 라우트됨
// 클라이언트가 서버로 메세지를 보낼 때 붙여야하는 prefix
registry.setApplicationDestinationPrefixes("/pub");
//해당 문자열로 시작하는 message 주소값을 받아서 처리하는 Broker를 활성화한다.
registry.enableSimpleBroker("/sub"); //메세지 구독 주소값
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry){
registry.addEndpoint("/websocket") //클라이언트가 연결할 url
.setAllowedOriginPatterns("*")
.withSockJS();
//withSockJS : 웹소켓을 지원하지 않는 환경에서도 웹소켓 사용을 가능하게 해주는 옵션
//이 옵션을 달면 클라이언트에서 SockJS 라이브러리를 사용해야 함
//http 아니면 https 로 연결가능(sockJS가 http를 ws로 변환해줌)
}
}
서버에서 STOMP 메세지 보내기
- convertAndSend 메소드를 호출하면 클라이언트가 구독하고 있는 주소로 메세지가 발행됨.
- /sub/** 주소를 구독하고 있는 클라이언트에게 메세지를 전달하는 예시
import java.util.HashMap;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Component;
import lombok.RequiredArgsConstructor;
@Component
@RequiredArgsConstructor
public class sendService{
private final SimpMessagingTemplate messagingTemplate;
public void sendMessageToSubOrderTopic(String message,String id) {
messagingTemplate.convertAndSend("/sub/"+id, message);
}
}
서버에서 STOMP 메세지 받아서 전달하기
- 서버가 메세지 브로커 역할 수행
- 특정 클라이언트가 /sub/test 주소로 메세지를 보내면 @MessageMapping에서 받아 @SendTo에 설정된 쪽으로 전달
- /sub/** 을 구독하는 클라이언트가 메세지를 받아볼 수 있는 예시
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.DestinationVariable;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Controller
public class StompMessageController {
/* 클라이언트에서 웹소켓을 연결한 뒤 /pub/test 로 메세지를 보내면
여기서 받아 SendTo에 명시된 구독 링크로 메세지를 발행
prefix는 생략
*/
@MessageMapping("/test")
@SendTo("/sub")
public String processMessage(String message){
System.out.println("message : " + message);
return message;
}
//STOMP를 쓰면 좋은점
/* @Controller 적용된 객체를 이용해 조직적으로 관리할 수 있다.
STOMP의 Destination 경로를 기반으로 Spring Security를 적용할 수 있다
외부 브로커를 이용해 여러 서버를 관리할 수 있다.
*/
}
그럼 메세지를 구독하고 보내는 클라이언트 페이지를 띄워 테스트를 해보자..
검색해보면 전부 다 APIC으로 테스트를 하던데 APIC자체를 못찾아서 javascript로 짜서 했음.
html 페이지에 javascript 소스를 넣는다.
메세지 구독하는 클라이언트 페이지 소스 예시 (javascript)
서버에 withSockJS() 설정이 되어있다면 SockJS 를 이용하여 연결해야 하며 이 경우엔 http나 https 로 접속을 해야함.
서버에서 /sub 주소로 구독하고 있는 클라이언트에 메세지를 전달해주므로
/sub/aaa이나 /sub/bbb 를 구독하는 쪽은 메세지를 다 받을 수 있음.
<script src="https://cdnjs.cloudflare.com/ajax/libs/sockjs-client/1.6.1/sockjs.min.js" integrity="sha512-1QvjE7BtotQjkq8PxLeF6P46gEpBRXuskzIVgjFpekzFVF4yjRgrQvTG1MTOJ3yQgvTteKAcO7DSZI92+u/yZw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/stomp.js/2.3.3/stomp.min.js"></script>
<script type="text/javascript">
var socket = new SockJS("http://localhost:8081/websocket");
stompClient = Stomp.over(socket);
stompClient.connect({}, function (frame) {
console.log("연결 완료");
stompClient.subscribe("/sub/aaa",function(response){
console.log(response.body);
});
});
</script>
메세지를 발행하는 클라이언트 페이지 소스 예시(javascript)
<script src="https://cdnjs.cloudflare.com/ajax/libs/sockjs-client/1.6.1/sockjs.min.js" integrity="sha512-1QvjE7BtotQjkq8PxLeF6P46gEpBRXuskzIVgjFpekzFVF4yjRgrQvTG1MTOJ3yQgvTteKAcO7DSZI92+u/yZw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/stomp.js/2.3.3/stomp.min.js"></script>
<script type="text/javascript">
var socket = new SockJS("http://localhost:8081/websocket");
stompClient = Stomp.over(socket);
stompClient.connect({}, function (frame) {
console.log("연결 완료");
stompClient.send("/pub/test",{},"test메시지입니다.");
});
</script>
SockJS를 안 쓰고 싶다면
서버에서 해당 설정을 없애주고
클라이언트에서는 stomp 라이브러리로 바로 연결하면 댐
<script src="https://cdnjs.cloudflare.com/ajax/libs/sockjs-client/1.6.1/sockjs.min.js" integrity="sha512-1QvjE7BtotQjkq8PxLeF6P46gEpBRXuskzIVgjFpekzFVF4yjRgrQvTG1MTOJ3yQgvTteKAcO7DSZI92+u/yZw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/stomp.js/2.3.3/stomp.min.js"></script>
<script type="text/javascript">
var client = Stomp.client("ws://localhost:8081/websocket");
client.connect({},function(){
console.log("연결 완료");
client.subscribe("/sub/aaa",function(message){
console.log("받은 메세지 : " + mesasge);
});
})
</script>
반응형
'코딩 관련 > Spring 관련' 카테고리의 다른 글
[Springboot][JAVA] springboot로 websocket 구현하기 (0) | 2024.02.13 |
---|---|
@Autowired is null (0) | 2023.02.16 |
Springboot JPA 연동 / postgreSQL JPA 연동 (0) | 2023.02.09 |
springboot H2 연동하기 / JPA 사용하기 (0) | 2023.01.27 |
[Spring][Maven] maven 프로젝트 외부 라이브러리 추가하기 (0) | 2022.06.08 |