WebSocket of SpringBoot realizes single chat and group chat

  • 2021-08-28 20:16:10
  • OfStack

This article example for everyone to share SpringBoot WebSocket to achieve a single chat group chat, for your reference, the specific content is as follows

Say at the beginning

In the HTTP protocol, all requests are sent by the client to the server, and then the server sends the request
There are several methods's to push messages from the server to the client:

1. Polling

A large number of invalid requests, wasting resources

2. Long polling

There is new data to push again, but this will cause the connection to time out, and there is a hidden danger

3. Applet and Flash

Outdated, potential safety hazard, poor compatibility

Mass messaging

Create a new project:

Add dependencies:


<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
 </dependency>
 <dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-websocket</artifactId>
 </dependency>
 <dependency>
  <groupId>org.webjars</groupId>
  <artifactId>sockjs-client</artifactId>
  <version>1.1.2</version>
 </dependency>
 <dependency>
  <groupId>org.webjars</groupId>
  <artifactId>jquery</artifactId>
  <version>3.3.1</version>
 </dependency>
 <dependency>
  <groupId>org.webjars</groupId>
  <artifactId>stomp-websocket</artifactId>
  <version>2.3.3</version>
 </dependency>
 <dependency>
  <groupId>org.webjars</groupId>
  <artifactId>webjars-locator-core</artifactId>
</dependency>

Create an WebSocket configuration class: WebSocketConfig


@Configuration
@EnableWebSocketMessageBroker// Annotation open webSocket Message broker 
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
 /**
 *  Configure webSocket Proxy class 
 * @param registry
 */
 @Override
 public void configureMessageBroker(MessageBrokerRegistry registry) {
 registry.enableSimpleBroker("/topic"); // Prefix of proxy message 
 registry.setApplicationDestinationPrefixes("/app");  // Method prefix for processing messages 
 }
 @Override
 public void registerStompEndpoints(StompEndpointRegistry registry) {
 registry.addEndpoint("/chat").withSockJS();  // Definition 1 A /chat Prefixed endpioint, Used to connect 
 }
}

Create Bean


/**
 *  Group message class 
 */
public class Message {
 private String name;
 private String content;
// Omission getter& setter
}

Method for defining controller:


/**
 * MessageMapping Accept the message from the front end 
 * SendTo  Send to information WebSocket Message broker, broadcast 
 * @param message  From the page json Encapsulate data into customization Bean
 * @return  The returned data is handed over to WebSocket Broadcast 
 * @throws Exception
 */
 @MessageMapping("/hello")
 @SendTo("/topic/greetings")
 public Message greeting(Message message) throws Exception {
 return message;
 }

<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>Title</title>
 <script src="/webjars/jquery/jquery.min.js"></script>
 <script src="/webjars/sockjs-client/sockjs.min.js"></script>
 <script src="/webjars/stomp-websocket/stomp.min.js"></script>
 <script>
 var stompClient = null;
 // The page changes after clicking the connection 
 function setConnected(connection) {
  $("#connect").prop("disable",connection);
  $("#disconnect").prop("disable",!connection);
  if (connection) {
  $("#conversation").show();
  $("#chat").show();

  } else {
  $("#conversation").hide();
  $("#chat").hide();
  }
  $("#greetings").html("");
 }
 // Click the Connect button to establish a connection 
 function connect() {
  // If the user name is empty, jump out directly 
  if (!$("#name").val()) {
  return;
  }
  // Create SockJs Instances , Establish a connection 
  var sockJS = new SockJS("/chat");
  // Create stomp Instance to send connection 
  stompClient = Stomp.over(sockJS);
  stompClient.connect({}, function (frame) {
  setConnected(true);
  // Subscribe to the information sent by the server 
  stompClient.subscribe("/topic/greetings", function (greeting) {
   // Convert messages to json Format, call method presentation 
   showGreeting(JSON.parse(greeting.body));
  });
  });
 }
 // Disconnect 
 function disconnect() {
  if (stompClient !== null) {
  stompClient.disconnect();
  }
  setConnected(false);
 }
 // Send a message 
 function sendName() {
  stompClient.send("/app/hello",{},JSON.stringify({'name': $("#name").val() , 'content': $("#content").val()}));
 }
 // Show chat room 
 function showGreeting(message) {
  $("#greetings").append("<div>"+message.name + ":" + message.content + "</div>");
 }
 $(function () {
  $("#connect").click(function () {
  connect();
  });
  $("#disconnect").click(function () {
  disconnect();
  });
  $("#send").click(function () {
  sendName();
  })
 })
 </script>
</head>
<body>
<div>
 <label for="name"> User name </label>
 <input type="text" id="name" placeholder=" Please enter a user name ">
</div>
<div>
 <button id="connect" type="button"> Connect </button>
 <button id="disconnect" type="button"> Disconnect </button>
</div>
<div id="chat" style="display: none;">
 <div>
 <label for="name"></label>
 <input type="text" id="content" placeholder=" Chat content ">
 </div>
 <button id="send" type="button"> Send </button>
 <div id="greetings">
 <div id="conversation" style="display: none;"> Group chat in progress </div>
 </div>
</div>
</body>
</html>

Private chat

Since it is a private chat, it is necessary to have an object target and a user, which can be introduced by SpringSecurity
So add additional dependencies:


<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-security</artifactId>
</dependency>

Configuring SpringSecurity


@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
 @Bean
 PasswordEncoder passwordEncoder(){
 return new BCryptPasswordEncoder();
 }
 @Override
 protected void configure(AuthenticationManagerBuilder auth) throws Exception {
 auth.inMemoryAuthentication()
  .withUser("panlijie").roles("admin").password("$2a$10$5Pf0KhCdnrpMxP5aRrHvMOsvV2fvfWJqk0SEDa9vQ8OWwV8emLFhi")
  .and()
  .withUser("suyanxia").roles("user").password("$2a$10$5Pf0KhCdnrpMxP5aRrHvMOsvV2fvfWJqk0SEDa9vQ8OWwV8emLFhi");
 }
 @Override
 protected void configure(HttpSecurity http) throws Exception {
 http.authorizeRequests()
  .anyRequest().authenticated()
  .and()
  .formLogin()
  .permitAll();
 }
}

Modified in the original WebSocketConfig configuration class: that is, one more proxy message prefix: "/queue"


@Configuration
@EnableWebSocketMessageBroker// Annotation open webSocket Message broker 
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
 /**
 *  Configure webSocket Proxy class 
 * @param registry
 */
 @Override
 public void configureMessageBroker(MessageBrokerRegistry registry) {
 registry.enableSimpleBroker("/topic","/queue"); // Prefix of proxy message 
 registry.setApplicationDestinationPrefixes("/app");  // Method prefix for processing messages 
 }
 @Override
 public void registerStompEndpoints(StompEndpointRegistry registry) {
 registry.addEndpoint("/chat").withSockJS();  // Definition 1 A /chat Prefixed endpioint, Used to connect 
 }
}

To create an Bean:


public class Chat {
 private String to;
 private String from;
 private String content;
// Omission getter& setter
}

Add the controller method:


 /**
 *  Send information point to point 
 * @param principal  Information about the current user 
 * @param chat  Messages sent 
 */
 @MessageMapping("chat")
 public void chat(Principal principal, Chat chat) {
 // Gets the current object set as the information source 
 String from = principal.getName();
 chat.setFrom(from);
 // Call convertAndSendToUser(" User name "," Path "," Content ");
 simpMessagingTemplate.convertAndSendToUser(chat.getTo(), "/queue/chat", chat);
 }

Create a page:


@Configuration
@EnableWebSocketMessageBroker// Annotation open webSocket Message broker 
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
 /**
 *  Configure webSocket Proxy class 
 * @param registry
 */
 @Override
 public void configureMessageBroker(MessageBrokerRegistry registry) {
 registry.enableSimpleBroker("/topic"); // Prefix of proxy message 
 registry.setApplicationDestinationPrefixes("/app");  // Method prefix for processing messages 
 }
 @Override
 public void registerStompEndpoints(StompEndpointRegistry registry) {
 registry.addEndpoint("/chat").withSockJS();  // Definition 1 A /chat Prefixed endpioint, Used to connect 
 }
}
0

Temporary!


Related articles: