-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #91 from yomankum-project/feature/85-socket
feat: webSocket
- Loading branch information
Showing
14 changed files
with
257 additions
and
21 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
12 changes: 0 additions & 12 deletions
12
src/main/java/com/account/yomankum/kafka/AccountBookInputNotice.java
This file was deleted.
Oops, something went wrong.
43 changes: 39 additions & 4 deletions
43
src/main/java/com/account/yomankum/kafka/KafkaService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,52 @@ | ||
package com.account.yomankum.kafka; | ||
|
||
import com.account.yomankum.auth.common.Auth; | ||
import com.account.yomankum.auth.common.LoginUser; | ||
import com.account.yomankum.common.exception.BadRequestException; | ||
import com.account.yomankum.common.exception.Exception; | ||
import com.account.yomankum.kafka.dto.AccountBookCreateNotice; | ||
import com.account.yomankum.kafka.dto.AccountBookInputNotice; | ||
import com.account.yomankum.kafka.dto.AccountBookUpdateNotice; | ||
import com.account.yomankum.socket.common.CustomWebSocketHandler; | ||
import com.account.yomankum.socket.dto.AccountBookWebSocketNotice; | ||
import com.account.yomankum.user.domain.User; | ||
import com.account.yomankum.user.service.UserFinder; | ||
import lombok.RequiredArgsConstructor; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.springframework.kafka.annotation.KafkaListener; | ||
import org.springframework.stereotype.Component; | ||
|
||
@Slf4j | ||
@Component | ||
@RequiredArgsConstructor | ||
public class KafkaService { | ||
|
||
@KafkaListener(topics = "accountBook_input", groupId = "accountServiceConsumers") | ||
public void listenAccountNotifications(AccountBookInputNotice notice) { | ||
// 처리 로직 | ||
System.out.println("Received Account Notification: " + notice.nickname()); | ||
private final UserFinder userFinder; | ||
private final CustomWebSocketHandler customWebSocketHandler; | ||
|
||
@KafkaListener(topics = "input", groupId = "accountBook") | ||
public void inputAccountBookNotification(AccountBookInputNotice notice) { | ||
customWebSocketHandler.sendAccountBookMessage(AccountBookWebSocketNotice.from(notice)); | ||
log.info("[Kafka] input 메시지 수신 - accountBookId : {}", notice.accountBookId()); | ||
} | ||
|
||
@KafkaListener(topics = "create", groupId = "accountBook") | ||
public void createAccountBookNotification(AccountBookCreateNotice notice) { | ||
// 알림 추가 -> Http ? | ||
log.info("[Kafka] create 메시지 수신 - accountBookId : {}", notice.accountBookId()); | ||
} | ||
|
||
@KafkaListener(topics = "update", groupId = "accountBook") | ||
public void updateAccountBookNotification(@Auth LoginUser loginUser, AccountBookUpdateNotice notice) { | ||
User user = userFinder.findById(loginUser.getUserId()) | ||
.orElseThrow(() -> new BadRequestException(Exception.USER_NOT_FOUND)); | ||
|
||
boolean isExist = user.isUsersAccountBook(notice.accountBookId()); | ||
|
||
if (isExist) { | ||
// 알림 추가 -> Http ? | ||
log.info("[Kafka] update 메시지 수신 - accountBookId : {}", notice.accountBookId()); | ||
} | ||
} | ||
} | ||
|
11 changes: 11 additions & 0 deletions
11
src/main/java/com/account/yomankum/kafka/dto/AccountBookCreateNotice.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package com.account.yomankum.kafka.dto; | ||
|
||
import java.time.LocalDateTime; | ||
|
||
public record AccountBookCreateNotice( | ||
Long accountBookId, | ||
String nickname, // 쓰기 시작하는 닉네임 | ||
LocalDateTime accountBookCreatedAt, | ||
LocalDateTime eventCreatedAt | ||
) { | ||
} |
11 changes: 11 additions & 0 deletions
11
src/main/java/com/account/yomankum/kafka/dto/AccountBookInputNotice.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package com.account.yomankum.kafka.dto; | ||
|
||
import java.time.LocalDateTime; | ||
|
||
public record AccountBookInputNotice( | ||
Long accountBookId, | ||
String nickname, // 쓰기 시작하는 닉네임 | ||
LocalDateTime accountBookCreatedAt, | ||
LocalDateTime eventCreatedAt | ||
) { | ||
} |
11 changes: 11 additions & 0 deletions
11
src/main/java/com/account/yomankum/kafka/dto/AccountBookUpdateNotice.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package com.account.yomankum.kafka.dto; | ||
|
||
import java.time.LocalDateTime; | ||
|
||
public record AccountBookUpdateNotice( | ||
Long accountBookId, | ||
String nickname, // 쓰기 시작하는 닉네임 | ||
LocalDateTime accountBookCreatedAt, | ||
LocalDateTime eventCreatedAt | ||
) { | ||
} |
26 changes: 26 additions & 0 deletions
26
src/main/java/com/account/yomankum/socket/common/CustomHttpSessionHandshakeInterceptor.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package com.account.yomankum.socket.common; | ||
|
||
import jakarta.servlet.http.HttpServletRequest; | ||
import org.springframework.http.server.ServerHttpRequest; | ||
import org.springframework.http.server.ServerHttpResponse; | ||
import org.springframework.util.StringUtils; | ||
import org.springframework.web.socket.WebSocketHandler; | ||
import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor; | ||
|
||
import java.util.Map; | ||
|
||
public class CustomHttpSessionHandshakeInterceptor extends HttpSessionHandshakeInterceptor { | ||
|
||
@Override | ||
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception { | ||
HttpServletRequest httpReq = (HttpServletRequest) request; | ||
String userId = httpReq.getParameter("userId"); | ||
|
||
if (StringUtils.hasText(userId)) { | ||
attributes.put("userId", userId); | ||
} | ||
|
||
return super.beforeHandshake(request, response, wsHandler, attributes); | ||
} | ||
|
||
} |
96 changes: 96 additions & 0 deletions
96
src/main/java/com/account/yomankum/socket/common/CustomWebSocketHandler.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
package com.account.yomankum.socket.common; | ||
|
||
import com.account.yomankum.common.exception.BadRequestException; | ||
import com.account.yomankum.common.exception.Exception; | ||
import com.account.yomankum.socket.dto.AccountBookWebSocketNotice; | ||
import com.account.yomankum.user.domain.User; | ||
import com.account.yomankum.user.service.UserFinder; | ||
import com.fasterxml.jackson.core.JsonProcessingException; | ||
import com.fasterxml.jackson.databind.ObjectMapper; | ||
import lombok.RequiredArgsConstructor; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.springframework.stereotype.Component; | ||
import org.springframework.util.StringUtils; | ||
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.io.IOException; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.concurrent.ConcurrentHashMap; | ||
import java.util.concurrent.CopyOnWriteArraySet; | ||
|
||
@Slf4j | ||
@Component | ||
@RequiredArgsConstructor | ||
public class CustomWebSocketHandler extends TextWebSocketHandler { | ||
// 소켓에 연결되어있는 세션 목록 | ||
private final CopyOnWriteArraySet<WebSocketSession> sessions = new CopyOnWriteArraySet<>(); | ||
private final Map<Long, WebSocketSession> userIdSessionMap = new ConcurrentHashMap<>(); | ||
|
||
private final UserFinder userFinder; | ||
private final ObjectMapper mapper; | ||
|
||
@Override | ||
public void afterConnectionEstablished(WebSocketSession session) { | ||
sessions.add(session); | ||
String userId = (String) session.getAttributes().get("userId"); | ||
|
||
if (StringUtils.hasText(userId)) { | ||
userIdSessionMap.put(Long.parseLong(userId), session); | ||
} | ||
|
||
log.info("소켓 연결 성공 - userID : {}", userId); | ||
} | ||
|
||
@Override | ||
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) { | ||
sessions.remove(session); | ||
String userId = (String) session.getAttributes().get("userId"); | ||
|
||
if (StringUtils.hasText(userId)) { | ||
userIdSessionMap.remove(Long.parseLong(userId), session); | ||
} | ||
|
||
log.info("소켓 연결 종료 - userID : {}", userId); | ||
} | ||
|
||
@Override | ||
protected void handleTextMessage(WebSocketSession session, TextMessage message) { | ||
// message 받으면.. | ||
} | ||
|
||
// 클라이언트에게 메시지 보내기 | ||
public void sendAccountBookMessage(AccountBookWebSocketNotice notice) { | ||
List<Long> userIdList = new ArrayList<>(userIdSessionMap.keySet()); | ||
List<User> userList = userFinder.findAllById(userIdList); | ||
|
||
Long accountBookId = notice.accountBookId(); | ||
List<Long> accountBookUserIdList = userList.stream() | ||
.filter(user -> user.isUsersAccountBook(accountBookId)) | ||
.map(User::getId) | ||
.toList(); | ||
|
||
accountBookUserIdList.forEach(userId -> { | ||
WebSocketSession session = userIdSessionMap.get(userId); | ||
|
||
if (session != null && session.isOpen()) { | ||
try { | ||
String message = mapper.writeValueAsString(notice); | ||
session.sendMessage(new TextMessage(message)); | ||
} catch (JsonProcessingException e) { | ||
log.error("JSON 파싱 에러"); | ||
throw new BadRequestException(Exception.SERVER_ERROR); | ||
} catch (IOException e) { | ||
log.error("세션 메시지 전송 에러"); | ||
throw new BadRequestException(Exception.SERVER_ERROR); | ||
} | ||
} | ||
}); | ||
|
||
} | ||
|
||
} |
24 changes: 24 additions & 0 deletions
24
src/main/java/com/account/yomankum/socket/common/WebSocketConfig.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package com.account.yomankum.socket.common; | ||
|
||
import lombok.RequiredArgsConstructor; | ||
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 | ||
@RequiredArgsConstructor | ||
public class WebSocketConfig implements WebSocketConfigurer { | ||
|
||
private final CustomWebSocketHandler customWebSocketHandler; | ||
|
||
@Override | ||
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { | ||
registry.addHandler(customWebSocketHandler, "/ws") | ||
.setAllowedOrigins("https://www.yomankum.com") // FE Server 오리진 추가.. | ||
.addInterceptors(new CustomHttpSessionHandshakeInterceptor()) | ||
.withSockJS(); | ||
} | ||
|
||
} |
19 changes: 19 additions & 0 deletions
19
src/main/java/com/account/yomankum/socket/dto/AccountBookWebSocketNotice.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package com.account.yomankum.socket.dto; | ||
|
||
import com.account.yomankum.kafka.dto.AccountBookInputNotice; | ||
import lombok.Builder; | ||
|
||
@Builder | ||
public record AccountBookWebSocketNotice( | ||
Long accountBookId, | ||
String nickname, | ||
EventType eventType | ||
) { | ||
public static AccountBookWebSocketNotice from(AccountBookInputNotice notice) { | ||
return AccountBookWebSocketNotice.builder() | ||
.accountBookId(notice.accountBookId()) | ||
.eventType(EventType.ACCOUNT_BOOK_INPUT) | ||
.nickname(notice.nickname()) | ||
.build(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
package com.account.yomankum.socket.dto; | ||
|
||
public enum EventType { | ||
ACCOUNT_BOOK_INPUT | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters