websocket simple implementation based on springboot

Posted by norbie on Tue, 29 Oct 2019 18:03:49 +0100

1. Create a new springboot project and add a maven dependency

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

The file directory structure is as follows:

2. Create websocket server class

MoneyServer.java

/**
 * @author Page
 * @date 2019-07-02 10:00
 * @description websocket service
 */

@Component
@Slf4j
@ServerEndpoint(value = "/money/{userId}", decoders = {
        MessageDecoder.class,}, encoders = {MessageEncoder.class,}, configurator = MoneyRepayConfig.class)
public class MoneyServer {
    private static final Map<String, Session> SESSION_MAP = new HashMap<>();

    @OnOpen
    public void connect(Session session, @PathParam("userId") String userId) {
        // The session is stored according to the room name, and the users of each room are isolated.
        SESSION_MAP.put(userId, session);
        log.info("websocket Successful connection!");
    }

    @OnMessage
    public void repay(RepayReq req, Session session) {
        SESSION_MAP.put(req.getUserId(), session);
        log.info("{}Paying back:{} element", req.getName(), req.getMoneyNum());
    }

    public void send(RepayResultRes res) throws IOException, EncodeException {
        if (SESSION_MAP.get(res.getUserId()) == null) {
            log.info("No connection found, message cannot be pushed");
            return;
        }
        SESSION_MAP.get(res.getUserId()).getBasicRemote().sendObject(res);
        log.info("{}Successful repayment:{} Yuan, userId:{},Repayment results:{}", res.getName(),
                res.getMoneyNum(), res.getUserId(), res.isRepayResult()?"Also succeeded" :"failed");
    }
}

Here I also add a custom decoder and an encoder to parse java objects and strings from the front end, as well as a custom websocket configuration class. However, nothing has been done in this configuration class at present.
MessageDecoder.java

@Slf4j
public class MessageDecoder implements Decoder.Text<RepayReq> {

    @Override
    public RepayReq decode(String s) {
        log.info("primal string" + s);
        RepayReq repayReq = null;
        try {
            repayReq = JSONObject.parseObject(s, RepayReq.class);
        } catch (Exception ex) {
            log.error(ex.getMessage());
        }
        return repayReq;
    }

    @Override
    public boolean willDecode(String s) {

        return (s != null);
    }

    @Override
    public void init(EndpointConfig endpointConfig) {
        // do nothing.
    }

    @Override
    public void destroy() {
        // do nothing.
    }
}

MessageEncoder.java

@Slf4j
public class MessageEncoder implements Encoder.Text<RepayResultRes> {

    @Override
    public String encode(RepayResultRes object) {

        String s = null;
        try {

            s = JSONObject.toJSONString(object);
            log.info("primal: " + object.toString());

        } catch (Exception ex) {
            log.error(ex.getMessage());
        }
        return s;
    }

    @Override
    public void init(EndpointConfig endpointConfig) {
        // do nothing.
    }

    @Override
    public void destroy() {
        // do nothing.
    }
}

MoneyRepayConfig.java

/**
 * @author Page
 * @date 2019-07-05 17:00
 * @description
 */
@Slf4j
public class MoneyRepayConfig extends ServerEndpointConfig.Configurator{
    @Override
    public boolean checkOrigin(String originHeaderValue) {
        log.info("1=========originHeaderValue====={}", originHeaderValue);
        return true;
    }

    @Override
    public <T> T getEndpointInstance(Class<T> clazz) throws InstantiationException {
        log.info("2========{}========={}==",clazz, super.getEndpointInstance(clazz));
        return super.getEndpointInstance(clazz);
    }

    @Override
    public String getNegotiatedSubprotocol(List<String> supported, List<String> requested) {
        log.info("3========{}====={}======{}", supported, requested, super.getNegotiatedSubprotocol(supported, requested));
        return super.getNegotiatedSubprotocol(supported, requested);
    }

    @Override
    public List<Extension> getNegotiatedExtensions(List<Extension> installed, List<Extension> requested) {
        log.info("4======{}====={}======{}", installed, requested, super.getNegotiatedExtensions(installed, requested));
        return super.getNegotiatedExtensions(installed, requested);
    }

    @Override
    public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response) {
        log.info("5======{}======{}======{}", sec, request, response);
        super.modifyHandshake(sec, request, response);
    }
}

There are several rewritable methods in ServerEndpointConfig, through which we can get the information of websocket and modify some information of connection.

3. Create WebSocketConfig

Publish websocket service through this configuration class

@Configuration
@ServletComponentScan
public class WebSocketConfig extends WsSci {
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }
}

4. Create controller

Here I also create a controller class to simulate the response of the server and send a message to the client.
RepaySuccessController.java

/**
 * @author Page
 * @Date: 2019-07-02 10:36
 * @Description:
 */

@Controller
@RequestMapping("/money")
public class RepaySuccessController {
    @Resource
    MoneyServer moneyServer;

    @PostMapping("/repaySuccess")
    public void repaySuccess(RepayResultRes req) throws IOException, EncodeException {
        moneyServer.send(req);
    }
}

The project code has been put in my github warehouse, and can be downloaded if necessary.

Address: Welcome to visit
For more information about websocket, please refer to the official documents:
https://docs.oracle.com/javaee/7/api/javax/websocket/server/package-summary.html

Topics: PHP Session Java SpringBoot Maven