웹소켓을 이용한 호출과 주문

  1. 웹소켓 의존성 추가

bulid.gradle에 추가

implementation 'org.springframework.boot:spring-boot-starter-websocket'
  1. WebSocketConfig에 설정 추가 - 일단 테스트로 내 컴퓨터 ip를 넣어둠
package kr.ganjuproject.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        config.enableSimpleBroker("/topic");
        config.setApplicationDestinationPrefixes("/app");
    }
    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/ws")
                .setAllowedOrigins("<http://192.168.10.28> :8081")
                .withSockJS();
    }
}
  1. Controller에 처리 로직 추가 - 테스트로 db에 값 넣어보고 전
package kr.ganjuproject.controller;

import kr.ganjuproject.entity.Orders;
import kr.ganjuproject.service.OrdersService;
import lombok.RequiredArgsConstructor;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.stereotype.Controller;

@Controller
@RequiredArgsConstructor
public class WebSocketController {

    private final OrdersService ordersService;

    @MessageMapping("/call")
    @SendTo("/topic/calls")
    public Orders call(Orders order) throws Exception {
        // 처리 로직
        ordersService.add(order);
        return order;
    }
}

  1. 보내는페이지 받는 페이지 전부 웹소켓 관련 스크립트 참조
  1. 이제 호출하기에서 클릭 했을 때 값을 받아서 웹소켓을 통해 보내줌
// 호출하기 모달에서 호출하기 버튼 클릭 이벤트
document.getElementById('submitCall').addEventListener('click', () => {
    // 실제 애플리케이션에서는 이곳에 선택된 옵션을 처리하는 로직을 구현합니다.
    const selectedOption = document.querySelector('input[name="callOption"]:checked').value;
    console.log('호출 옵션:', selectedOption);

    // WebSocket을 통해 서버로 선택된 옵션 정보 전송
    fetch('/validUserCall', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
        },
        body: selectedOption,
    })
        .then(response => response.json())
        .then(data => {
            // fetch 성공 후, 저장된 주문 정보를 WebSocket을 통해 전송
            if (window.stompClient && window.stompClient.connected) {
                const orderInfo = {
                    id: data.order.id, // 저장된 주문 ID
                    content: data.order.content, // 호출 내용
                    restaurantTableNo: data.order.restaurantTableNo, // 테이블 번호
                    regDate: data.order.regDate, // 등록 날짜
                    division: data.order.division, // 호출인가?
                    restaurantId: data.order.restaurantId
                };

                console.log(orderInfo);
                stompClient.send("/app/calls", {}, JSON.stringify(orderInfo));
            }
            console.log("성공");
        })
        .catch((error) => {
            console.error('Error:', error);
        });

    document.getElementById('callModal').style.display = 'none'; // 모달 닫기
    document.body.style.overflow = ''; // 스크롤 활성화
});
  1. controller 측에서 db에 저장해 entity를 만든 다음에 json으로 가져와서 보내줌
    // 호출하기에서 값을 가져와서 orders에 저장하고 다시 orders로 내보냄
    @PostMapping("/validUserCall")
    public ResponseEntity<?> save(HttpSession session, @RequestBody String content){
        long restaurantId = (long) session.getAttribute("restaurantId");
        int restaurantTableNo = (int) session.getAttribute("restaurantTableNo");
        Orders order = new Orders();
        order.setRestaurantTableNo(restaurantTableNo);
        order.setPrice(0);
        order.setRegDate(LocalDateTime.now());
        order.setRestaurant(restaurantService.findById(restaurantId).get());
        order.setContent(content);
        order.setDivision(RoleOrders.CALL);

        Orders saveOrder = ordersService.save(order);

        // Orders 엔티티를 OrderResponseDTO로 변환
        OrderResponseDTO orderResponseDTO = ordersService.convertToOrderResponseDTO(saveOrder);
        System.out.println(orderResponseDTO);
        System.out.println("저장성공");
        return ResponseEntity.ok().body(Map.of("order", orderResponseDTO));
    }
  1. 통신을 하려면 스크립트 측에서 실시간 감지하는 로직이 필요, 페이지 전체를 관장하는 js 부분에 추가
// 초기화 코드는 페이지 로드 시 한 번만 실행
const socket = new SockJS('/ws');
const stompClient = Stomp.over(socket);

// home.js에서 메시지 처리를 위한 함수를 전역으로 선언
window.handleReceivedCall = function(message) {
    // 추가적인 메시지 처리 로직...
};

stompClient.connect({}, function(frame) {
    console.log('Connected: ' + frame);
    stompClient.subscribe('/topic/calls', function(callMessage) {
        var callInfo = JSON.parse(callMessage.body);
        // 전역으로 선언된 메시지 처리 함수를 호출
        window.handleReceivedCall(callInfo);
    });
});

// 전역 변수로 설정하여 페이지 전체에서 사용 가능
window.stompClient = stompClient;
  1. 받는 쪽에도 해볼까
// order.js에서는 home.js에서 선언한 함수를 활용하여 메시지를 처리
if (window.handleReceivedCall) {
    // 기존의 handleReceivedCall 함수를 백업
    const originalHandleReceivedCall = window.handleReceivedCall;

    // handleReceivedCall 함수 확장
    window.handleReceivedCall = function(callInfo) {
        // 기존 로직 호출
        originalHandleReceivedCall(callInfo);

        // order.js에서 추가 로직 구현
        console.log("order.js:", callInfo);
        // 예: 화면에 메시지를 표시하는 로직
    }
}

성공

+ Recent posts