Springboot integrates websocket push messages

websocket push message

Websocket is a two-way communication protocol, and HTTP is one-way.
Directly on the code:
1. First create a springboot module to integrate websocket
This article explains the main classes used:
Insert picture description here

Configuration file:

server:
  port: 1013

spring:
  application:
    name: IDEAL-WEBSOCKET

2. Add dependency It is
recommended that idea create springboot module online or https://start.spring.io/.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>demo</artifactId>
        <groupId>com.example</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>ideal-websocket-1013</artifactId>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- websocket的基本依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.73</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-commons</artifactId>
        </dependency>
    </dependencies>


    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

3. This project demonstrates pushing to different clients based on user id: In actual scenarios, an account may support multiple logins at the same time, and the client interface of each login person must display the user's instant business information.
Create a user DTO;

package com.demo.websocket.dto;

import com.alibaba.fastjson.JSONObject;
import lombok.Data;

@Data
public class UserDto {
    
    

    private String userId;

    private String userName;

    @Override
    public String toString () {
    
    
        return JSONObject.toJSONString(this);
    }
}

4. Write websocet service: the url is /show/user/peoples, this is the front-end call to the
front-end when you can use websocket to test online URL: address: ws://127.0.0.1:1013/show/user/peoples, specific A screenshot will be shown later.

package com.demo.websocket.websocket;

import com.alibaba.fastjson.JSON;
import com.demo.websocket.config.WebSocketConfig;
import com.demo.websocket.dto.UserDto;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;

@Slf4j
@Component
@ServerEndpoint(value = "/show/user/peoples")
public class UserWebSocket {
    
    

    private static Map<String, List<Session>> clients = new ConcurrentHashMap<>();

    @OnOpen
    public void onOpen(Session session) {
    
    
        log.info("有新的客户端上线: {}", session.getId());
        List<Session> list = new CopyOnWriteArrayList<>();
        list.add(session);
        clients.put(session.getId(), list);
    }

    @OnClose
    public void onClose(Session session) {
    
    
        String sessionId = session.getId();
        log.info("有客户端离线: {}", sessionId);
        clients.remove(sessionId);
    }

    @OnError
    public void onError(Session session, Throwable throwable) {
    
    
        throwable.printStackTrace();
        if (clients.get(session.getId()) != null) {
    
    
            clients.remove(session.getId());
        }
    }

    @OnMessage
    public void onMessage(String message, Session session){
    
    
       UserDto userDto = JSON.parseObject(message, UserDto.class);
        List<Session> list = clients.get(userDto.getUserId());
        if(null == list){
    
    
            list = new CopyOnWriteArrayList<Session>();
            list.add(session);
        }else {
    
    
            list.add(session);
        }
        clients.put(userDto.getUserId(),list);
        log.info("用户新的客户端加入成功");
    }

    /**
     * 发送消息
     *
     * @param userDto 消息对象
     */
    public void sendToUser(UserDto userDto) {
    
    
        List<Session> list = clients.get(userDto.getUserId());
        if(null != list){
    
    
            log.info("需要发送的消息个数==={}",list.size());
            for(Session  session : list){
    
    
                try {
    
    
                    session.getBasicRemote().sendText(userDto.toString());
                }catch (IOException e){
    
    
                    log.error("发送websocket消息失败:{}", e);
                }

            }
        }
    }
}

4. Test interface: WebSocketController

package com.demo.websocket.controller;

import com.alibaba.fastjson.JSONObject;
import com.demo.websocket.dto.UserDto;
import com.demo.websocket.websocket.OneToManyWebSocket;
import com.demo.websocket.websocket.OneToOneWebSocket;
import com.demo.websocket.websocket.UserWebSocket;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.Map;

@RestController
@Slf4j
@RequestMapping("")
public class WebSocketController {
    
    
    @Autowired
    private UserWebSocket userWebSocket;

    /**
     * 模拟给同一个用户的不同客户段发送消息
     * @return
     */
    @PostMapping(value = "/send/user")
    String sendUser(@RequestBody UserDto userDto){
    
    
        log.info("开始给用户发送消息");
        userWebSocket.sendToUser(userDto);
        return "成功";
    }
}

5. To facilitate testing, swagger2 configuration is introduced in the module

SwaggerConfig类:

package com.demo.websocket.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;

/**
 * Description:swagger2配置类
 * @Date 2019-04-29 00:05
 */
@Configuration
public class SwaggerConfig {
    
    

  @Bean
  public Docket myDocket() {
    
    
    Docket docket = new Docket(DocumentationType.SWAGGER_2);
    ApiInfo apiInfo = new ApiInfoBuilder()
        .title("websocket---Api接口文档") // 标题
        .description("websocket学习") // 描述
        .contact(new Contact("", "", ""))
        .version("1.0") // 版本号
        .build();
    docket.apiInfo(apiInfo);
    //设置只生成被Api这个注解注解过的Ctrl类中有ApiOperation注解的api接口的文档
    docket.select()
        .apis(RequestHandlerSelectors.basePackage("com.demo.websocket.controller"))
        .paths(PathSelectors.any())
        .build();
    return docket;
  }

}

SwaggerAddressConfig类:

package com.demo.websocket.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.web.context.WebServerInitializedEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.UnknownHostException;

/**
 * @Date :2019/9/9 10:41
 * @Description:控制台输出 Swagger 接口文档地址
 */
@Slf4j
@Component
public class SwaggerAddressConfig implements ApplicationListener<WebServerInitializedEvent> {
    
    

    private int serverPort;

    public int getPort(){
    
    
        return this.serverPort;
    }

    @Override
    public void onApplicationEvent(WebServerInitializedEvent webServerInitializedEvent) {
    
    
        try {
    
    
            InetAddress localHost = Inet4Address.getLocalHost();
            this.serverPort = webServerInitializedEvent.getWebServer().getPort();
            log.info("启动完成,接口文档地址:http://"+localHost.getHostAddress()+":"+serverPort+"/swagger-ui.html");
        } catch (UnknownHostException e) {
    
    
            log.info("获取本机的ip异常错误=={}",e);
        }

    }
}

WebSocketApplication module startup class: add @EnableSwagger2

package com.demo.websocket;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@EnableDiscoveryClient // 除了eureka,还可以注册到其它的注册中心,如zookeeper上;
@SpringBootApplication
@EnableSwagger2
public class WebSocketApplication {
    
    
    public static void main(String[] args) {
    
    
        SpringApplication.run(WebSocketApplication.class,args);
    }
}

After starting the project: Visit the address in the red circle in the picture to open the swagger page
Insert picture description here

6. Effect display
As shown in the figure below: Open the website of http://www.websocket-test.com/ online test, it may be blocked by the browser safely, choose to continue to visit.
Websocket connection address: ws://127.0.0.1:1013/show/user/peoples
and then send a user body in the sent content: indicating that a certain client of user 111 is online.

{
    
    
  "userId": "111",
  "userName": "bbb"
}

Client 1 that
Insert picture description here
simulates user 111 : Client that simulates user 111 2: Client that
Insert picture description here
simulates user 222:
Insert picture description here

Next, simulate the background data changes to push messages to the front end: the
test interface is called using swagger. For the specific use of swagger, you can use Baidu; if you don't have it, you can directly use postman or jmeter.
Switch the value of userId between "111" and "222", and you can see the corresponding message displayed on the right side of the websocket line test page. If userId="111", only the sent message will be displayed on the "111" page, if userId="222", only the sent message will be displayed on the "222" page.
Insert picture description here
This is the end of the demo
Insert picture description here

Guess you like

Origin blog.csdn.net/qq_37488998/article/details/109999853