SpringMVC WebSocket实现消息推送

第一步: 添加Spring WebSocket的依赖jar包

<!-- 使用spring websocket依赖的jar包 -->
 <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-websocket</artifactId>
      <version>${spring-framework.version}</version>
  </dependency>
  <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-messaging</artifactId>
      <version>${spring-framework.version}</version>
  </dependency>

第二步:建立一个类实现WebSocketConfigurer接口

package com.my.spring.context;

import com.my.business.spring.SpringWebSocketHandler;
import lombok.AllArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
import org.springframework.web.socket.handler.TextWebSocketHandler;
import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor;

import java.util.HashMap;

/**
 * Spring Context - web socket配置
 * @author my Team
 * @version 2.0
 * @see com.my.business.spring.SpringWebSocketHandler
 */
@AllArgsConstructor(onConstructor = @__({@Autowired}))
@EnableWebMvc
@EnableWebSocket
public class SpringWebSocketConfig extends WebMvcConfigurationSupport implements WebSocketConfigurer {

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
		//HttpSessionHandshakeInterceptor拦截器,可以自定义,由于系统实现了session登录,这里就不需要再实现session与用户的绑定。
        registry.addHandler(webSocketHandler(), "/websocket").addInterceptors(new HttpSessionHandshakeInterceptor());
        registry.addHandler(webSocketHandler(), "/sockjs").addInterceptors(new HttpSessionHandshakeInterceptor()).withSockJS();
    }

    @Bean
    public TextWebSocketHandler webSocketHandler(){
        SpringWebSocketHandler springWebSocketHandler = new SpringWebSocketHandler();
        return springWebSocketHandler;
    }
}

第三步:继承WebSocketHandler对象。

实现websocket的登录、关闭、异常、发送消息等方法。

package com.my.business.spring;

import com.my.business.entity.Person;
import com.my.business.model.Principal;
import com.my.business.service.PersonService;
import com.my.spring.context.ApplicationUtils;
import com.my.spring.core.Assert;
import lombok.Setter;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.apache.shiro.subject.support.DefaultSubjectContext;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.adapter.standard.StandardWebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * websocket 发送消息
 */
public class SpringWebSocketHandler extends TextWebSocketHandler {

    @Setter
    private static Map<Long, WebSocketSession> sessionMap = new HashMap<>();

    /**
     * 连接成功的时候,触发页面上onopen方法
     * @param session session
     * @throws Exception 异常
     */
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        Person person = getLoginer(session);
        Assert.notNull(person);
        sessionMap.put(person.getId(), session);
        //TODO 发送离线消息
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        Person person = getLoginer(session);
        Assert.notNull(person);
        sessionMap.remove(person.getId());
    }

    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        if (session.isOpen()) {
            session.close();
        }
        Person person = getLoginer(session);
        if (person != null) {
            sessionMap.remove(person.getId());
        }
    }

    /**
     * 获取当前登录人。这里直接获取用户登录拦截器所存入的用户session
     * @param session session
     * @return 登录人
     */
    private Person getLoginer(WebSocketSession session) {
        Assert.notNull(session);
        SimplePrincipalCollection simplePrincipalCollection = (SimplePrincipalCollection) session.getAttributes().get(DefaultSubjectContext.PRINCIPALS_SESSION_KEY);
        if (simplePrincipalCollection == null) {
            return null;
        }
        Set<Object> objectSet = simplePrincipalCollection.asSet();
        for (Object object : objectSet) {
            if (object instanceof Principal) {
                Principal principal = (Principal) object;
                return ApplicationUtils.getBean(PersonService.class).findByUser(principal.getSn());
            }
        }
        return null;
    }

    /**
     * 发送消息
     * @param session session
     * @param message 消息内容
     */
    private boolean sendMessage(WebSocketSession session, TextMessage message) throws IOException {
        Assert.notNull(session);
        Assert.notNull(message);
        if (session.isOpen()) {
            session.sendMessage(message);
            return true;
        } else {
            return false;
        }
    }

    /**
     * 向用户发送消息
     * @param personId 用户id
     * @param message  message
     * @return
     */
    public boolean sendMessageToUser(Long personId, String message) {
        Assert.notNull(personId);
        Assert.notEmpty(message);
        WebSocketSession session = sessionMap.get(personId);
        if (session == null) {
            return false;
        }
        TextMessage textMessage = new TextMessage(message);
        try {
            return sendMessage(session, textMessage);
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
    }
}

第四部 测试代码

HTML代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<script src="./resources/js/jquery-1.11.3.min.js"></script>
<script src="./resources/js/sockjs.js"></script>
<script>
    var websocket = null;
    if ('WebSocket' in window) {
        websocket = new WebSocket("ws://localhost:8801/websocket");
    }
    else if ('MozWebSocket' in window) {
        websocket = new MozWebSocket("ws://localhost:8801/websocket");
    }
    else {
        websocket = new SockJS("http://localhost:8801/sockjs");
    }
    websocket.onopen = onOpen;
    websocket.onmessage = onMessage;
    websocket.onerror = onError;
    websocket.onclose = onClose;

    function onOpen(openEvt) {
        //alert(openEvt.Data);
    }

	//接收消息方法
    function onMessage(evt) {
        alert(evt.data);
    }
    function onError() {}
    function onClose() {}

	//发送消息
    function doSend() {
        if (websocket.readyState == websocket.OPEN) {
            var msg = document.getElementById("inputMsg").value;
            websocket.send(msg);//调用后台handleTextMessage方法
            alert("发送成功!");
        } else {
            alert("连接失败!");
        }
    }
    window.close=function()
    {
        websocket.onclose();
    }
</script>
</body>
</html>

java代码

package com.my.business.controller;

import com.my.business.model.Pageable;
import com.my.business.service.PersonService;
import com.my.business.spring.SpringWebSocketHandler;
import lombok.AllArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

@AllArgsConstructor(onConstructor = @__({@Autowired}))
@Controller
@RequestMapping("/test")
public class TestController {
    private PersonService personService;
    private SpringWebSocketHandler webSocketHandler;

    @RequestMapping(method = RequestMethod.GET)
    public String test(String name, ModelMap model) {
        model.addAttribute("name", name);
        model.addAttribute("persons", personService.findPage(new Pageable()).getContent());
        return "/test";
    }

    @ResponseBody
    @RequestMapping(value = "/name", method = RequestMethod.GET)
    public boolean name(String name) {
        return webSocketHandler.sendMessageToUser(personService.findLoginer().getId(), "你好socket");
    }
}

先访问http://localhost:8801/test返回页面,创建WebSocket连接,再访问http://localhost:8801/test/name向当前用户发送消息。

代码及sockjs.js下载

本文参考:https://www.cnblogs.com/3dianpomian/p/5902084.html

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java SpringMVC WebSocket 是一种在 web 应用中实现实时通信的技术。WebSocket协议是一种基于TCP协议的全双工通信协议,通过 WebSocket 可以在浏览器和服务器之间建立持久连接,实现服务器向客户端实时推送数据的功能。 SpringMVC 是一个基于 Java 的开源框架,用于构建 JavaEE 应用程序的 Web 层。它提供了一种轻量级的、快捷的开发方式,可以同时支持传统的请求-响应模式和 WebSocket 实时通信模式。 为了在 SpringMVC 中使用 WebSocket,我们需要使用到 Spring 的一个模块——Spring Websocket。它提供了一组类和接口,用于定义 WebSocket 的端点(Endpoint),配置 WebSocket 的拦截器(Interceptor),处理客户端发送的消息和向客户端发送消息等操作。通过这些类和接口,我们可以非常方便地实现 WebSocket 的功能。 首先,我们需要定义一个继承自`AbstractWebSocketMessageBrokerConfigurer`的配置类,通过它可以配置 WebSocket 的相关参数,比如设置允许的来源(allowed origins)、配置拦截器等等。 然后,我们需要定义一个继承自`AbstractWebSocketMessageBrokerConfigurer`的类,通过它可以配置消息代理(Message Broker)。消息代理负责接收客户端发送的消息并转发到目标客户端,同时也负责接收服务器推送消息并发送给目标客户端。 最后,我们可以通过在控制器中添加`@MessageMapping`注解来处理客户端发送的消息,并通过`@SendTo`注解将处理结果发送给客户端。 总之,使用 Java SpringMVC WebSocket 可以很方便地实现实时通信功能,在需要实现实时推送数据的场景下,非常适用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值