blog : chatting - init
This commit is contained in:
@@ -1,6 +1,10 @@
|
||||
package com.example.chatting.config;
|
||||
|
||||
import com.example.chatting.redis.RedisSubscriber;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
|
||||
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@@ -11,7 +15,8 @@ import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactor
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.listener.ChannelTopic;
|
||||
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
|
||||
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
|
||||
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;
|
||||
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
|
||||
import org.springframework.data.redis.serializer.StringRedisSerializer;
|
||||
|
||||
@Slf4j
|
||||
@@ -27,6 +32,14 @@ public class RedisConfig {
|
||||
@Value("${spring.redis.password}")
|
||||
private String password;
|
||||
|
||||
@Bean
|
||||
public ObjectMapper objectMapper() {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
|
||||
mapper.registerModules(new JavaTimeModule(), new Jdk8Module());
|
||||
return mapper;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RedisConnectionFactory redisConnectionFactory() {
|
||||
RedisStandaloneConfiguration configuration = new RedisStandaloneConfiguration();
|
||||
@@ -43,7 +56,7 @@ public class RedisConfig {
|
||||
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
|
||||
redisTemplate.setConnectionFactory(connectionFactory);
|
||||
redisTemplate.setKeySerializer(new StringRedisSerializer());
|
||||
redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<>(String.class));
|
||||
redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer(objectMapper()));
|
||||
return redisTemplate;
|
||||
}
|
||||
|
||||
@@ -52,7 +65,12 @@ public class RedisConfig {
|
||||
RedisSubscriber redisSubscriber) {
|
||||
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
|
||||
container.setConnectionFactory(connectionFactory);
|
||||
container.addMessageListener(redisSubscriber, new ChannelTopic("message"));
|
||||
container.addMessageListener(messageListenerAdapter(redisSubscriber), new ChannelTopic("message"));
|
||||
return container;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public MessageListenerAdapter messageListenerAdapter(RedisSubscriber redisSubscriber) {
|
||||
return new MessageListenerAdapter(redisSubscriber, "sendMessage");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +1,28 @@
|
||||
package com.example.chatting.config;
|
||||
|
||||
import com.example.chatting.handler.HandshakeHandler;
|
||||
import com.example.chatting.handler.MessageHandler;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.messaging.simp.config.ChannelRegistration;
|
||||
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
|
||||
@RequiredArgsConstructor
|
||||
@EnableWebSocketMessageBroker
|
||||
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
|
||||
|
||||
private final MessageHandler messageHandler;
|
||||
private final HandshakeHandler handshakeHandler;
|
||||
|
||||
@Override
|
||||
public void registerStompEndpoints(StompEndpointRegistry registry) {
|
||||
registry.addEndpoint("/ws-stomp")
|
||||
.setAllowedOriginPatterns("*")
|
||||
.setHandshakeHandler(handshakeHandler)
|
||||
.withSockJS();
|
||||
}
|
||||
|
||||
@@ -22,4 +31,9 @@ public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
|
||||
registry.setApplicationDestinationPrefixes("/pub");
|
||||
registry.enableSimpleBroker("/sub");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configureClientInboundChannel(ChannelRegistration registration) {
|
||||
registration.interceptors(messageHandler);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,62 @@
|
||||
package com.example.chatting.controller;
|
||||
|
||||
import com.example.chatting.domain.dto.ChatMessage;
|
||||
import com.example.chatting.redis.RedisPublisher;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.core.ValueOperations;
|
||||
import org.springframework.messaging.handler.annotation.MessageMapping;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import java.security.Principal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Controller
|
||||
@RequiredArgsConstructor
|
||||
public class MessageController {
|
||||
|
||||
private final RedisPublisher redisPublisher;
|
||||
private final RedisTemplate<String, Object> redisTemplate;
|
||||
private final ObjectMapper objectMapper;
|
||||
|
||||
@MessageMapping("/message")
|
||||
public void message(String message) {
|
||||
redisPublisher.publish("message", message);
|
||||
public void message(Principal principal, ChatMessage chatMessage) throws JsonProcessingException {
|
||||
System.out.println("controller");
|
||||
chatMessage.setSessionId(principal.getName());
|
||||
redisPublisher.publish("message", chatMessage);
|
||||
}
|
||||
|
||||
@ResponseBody
|
||||
@GetMapping("/test")
|
||||
public void test() {
|
||||
ChatMessage chatMessage = new ChatMessage();
|
||||
chatMessage.setSessionId("session");
|
||||
chatMessage.setMessage("hello");
|
||||
|
||||
ChatMessage chatMessage2 = new ChatMessage();
|
||||
chatMessage2.setSessionId("session");
|
||||
chatMessage2.setMessage("hello");
|
||||
chatMessage2.setDate(LocalDateTime.now());
|
||||
|
||||
chatMessage2.setTestEnum(ChatMessage.TestEnum.A);
|
||||
|
||||
List<ChatMessage> testList = new ArrayList<>();
|
||||
|
||||
testList.add(chatMessage);
|
||||
testList.add(chatMessage2);
|
||||
|
||||
ValueOperations<String, Object> ops = redisTemplate.opsForValue();
|
||||
ops.set("test", testList);
|
||||
|
||||
List<ChatMessage> test = (List<ChatMessage>) ops.get("test");
|
||||
System.out.println("test = " + test);
|
||||
|
||||
// redisPublisher.publish("message", chatMessage);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.example.chatting.domain.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
public class ChatMessage {
|
||||
|
||||
public enum TestEnum {
|
||||
A, B, C
|
||||
}
|
||||
|
||||
private String sessionId;
|
||||
private String message;
|
||||
private LocalDateTime date;
|
||||
private TestEnum testEnum;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.example.chatting.handler;
|
||||
|
||||
import org.springframework.http.server.ServerHttpRequest;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.socket.WebSocketHandler;
|
||||
import org.springframework.web.socket.server.support.DefaultHandshakeHandler;
|
||||
|
||||
import java.security.Principal;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
@Component
|
||||
public class HandshakeHandler extends DefaultHandshakeHandler {
|
||||
|
||||
@Override
|
||||
protected Principal determineUser(ServerHttpRequest request, WebSocketHandler wsHandler, Map<String, Object> attributes) {
|
||||
return new StompPrincipal(UUID.randomUUID().toString());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.example.chatting.handler;
|
||||
|
||||
import com.example.chatting.domain.dto.ChatMessage;
|
||||
import com.example.chatting.redis.RedisPublisher;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
import org.springframework.messaging.simp.SimpMessageType;
|
||||
import org.springframework.messaging.simp.stomp.StompCommand;
|
||||
import org.springframework.messaging.simp.stomp.StompHeaderAccessor;
|
||||
import org.springframework.messaging.support.ChannelInterceptor;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class MessageHandler implements ChannelInterceptor {
|
||||
|
||||
private final RedisPublisher redisPublisher;
|
||||
|
||||
@Override
|
||||
public Message<?> preSend(Message<?> message, MessageChannel channel) {
|
||||
StompHeaderAccessor accessor = StompHeaderAccessor.wrap(message);
|
||||
|
||||
StompPrincipal simpUser = (StompPrincipal) accessor.getHeader("simpUser");
|
||||
System.out.println("simpUser = " + simpUser);
|
||||
|
||||
String destination = accessor.getDestination();
|
||||
StompCommand command = accessor.getCommand();
|
||||
String sessionId = accessor.getSessionId();
|
||||
SimpMessageType messageType = accessor.getMessageType();
|
||||
|
||||
|
||||
if (accessor.getCommand() == StompCommand.SUBSCRIBE) {
|
||||
System.out.println("destination = " + destination);
|
||||
System.out.println("command = " + command);
|
||||
System.out.println("sessionId = " + sessionId);
|
||||
System.out.println("messageType = " + messageType);
|
||||
ChatMessage chatMessage = new ChatMessage();
|
||||
chatMessage.setSessionId("session");
|
||||
chatMessage.setMessage("interceptor");
|
||||
redisPublisher.publish("message", chatMessage);
|
||||
}
|
||||
|
||||
return message;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.example.chatting.handler;
|
||||
|
||||
import lombok.ToString;
|
||||
|
||||
import java.security.Principal;
|
||||
|
||||
@ToString
|
||||
public class StompPrincipal implements Principal {
|
||||
|
||||
private final String name;
|
||||
|
||||
public StompPrincipal(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.example.chatting.redis;
|
||||
|
||||
import com.example.chatting.domain.dto.ChatMessage;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -10,7 +11,7 @@ public class RedisPublisher {
|
||||
|
||||
private final RedisTemplate<String, Object> redisTemplate;
|
||||
|
||||
public void publish(String topic, String message) {
|
||||
public void publish(String topic, ChatMessage message) {
|
||||
redisTemplate.convertAndSend(topic, message);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
package com.example.chatting.redis;
|
||||
|
||||
import com.example.chatting.domain.dto.ChatMessage;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.data.redis.connection.Message;
|
||||
import org.springframework.data.redis.connection.MessageListener;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.messaging.simp.SimpMessageSendingOperations;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -12,17 +11,17 @@ import org.springframework.stereotype.Service;
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
public class RedisSubscriber implements MessageListener {
|
||||
public class RedisSubscriber {
|
||||
|
||||
private final ObjectMapper objectMapper;
|
||||
private final RedisTemplate<String, Object> redisTemplate;
|
||||
private final SimpMessageSendingOperations messagingTemplate;
|
||||
|
||||
@Override
|
||||
public void onMessage(Message message, byte[] pattern) {
|
||||
public void sendMessage(String message) {
|
||||
try {
|
||||
String pubMessage = redisTemplate.getStringSerializer().deserialize(message.getBody());
|
||||
messagingTemplate.convertAndSend("/sub/message", pubMessage == null ? "" : pubMessage);
|
||||
ChatMessage chatMessage = objectMapper.readValue(message, ChatMessage.class);
|
||||
messagingTemplate.convertAndSend("/sub/message", chatMessage);
|
||||
// messagingTemplate.convertAndSendToUser(chatMessage.getSessionId(), "/sub/message", chatMessage);
|
||||
} catch (Exception e) {
|
||||
log.error("Subscriber Error", e);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
server:
|
||||
port: 28080
|
||||
|
||||
|
||||
spring:
|
||||
redis:
|
||||
host: localhost
|
||||
port: 6379
|
||||
password: 1234
|
||||
password: 1234
|
||||
|
||||
|
||||
Reference in New Issue
Block a user