精华内容
下载资源
问答
  • SpringBoot webSocket

    2018-11-06 10:50:00
    SpringBoot+websocket+定时任务SpringBoot+websocket概念websocket:由于http协议时基于 请求-响应模型 服务端的每次响应都必须有客户端发起(浏览器)的请求。如果服务端想主动推送消息到客户端是很难满足的。 如果...

    https://blog.csdn.net/u013565163/article/details/80659828

    SpringBoot+websocket+定时任务
    SpringBoot+websocket
    概念
    websocket:由于http协议时基于 请求-响应模型 服务端的每次响应都必须有客户端发起(浏览器)的请求。如果服务端想主动推送消息到客户端是很难满足的。
    如果一定想使用http来做服务端主动推动,只能客户端不停的发起轮询请求,如果访问量很很大,这种模式会拖垮服务器。造成很大的通信开销和服务端流量压力。

    使用websocket可以完成要求实时性的应用:股票的变动、天气、彩票、即时通讯、通知。

    WebSocket 是web客户端和服务器之间新的通讯方式, 依然架构在HTTP协议之上。使用WebSocket连接, web应用程序可以执行实时的交互, 而不是以前的poll方式。

    WebSocket是HTML5开始提供的一种在单个 TCP 连接上进行全双工通讯的协议,可以用来创建快速的更大规模的健壮的高性能实时的web应用程序。WebSocket通信协议于2011年被IETF定为标准RFC 6455,WebSocketAPI被W3C定为标准。
    在WebSocket API中,浏览器和服务器只需要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送。

    现在大概了解了websocket的概念和应用,现在我们来看看如何在springBoot中集成websocket。

    配置类
    创建一个配置类:
    使用@Configuration注解 声明这个类为配置类。
    使用@EnableWebSocket注解表明这是一个websocket配置类,我们会在这个类配置一些websocket的参数和地址。
    我们的配置类实现WebSocketConfigurer接口。

    重写registerWebSocketHandlers方法,

    //配置指定地址:/demo的处理器,及通信允许的域名,这里使用*,表示匹配所有。
    webSocketHandlerRegistry.addHandler(new WebSocketDemoHanlder(),"/demo").setAllowedOrigins("*");


    /**
    * @author xuelongjiang
    */
    @Configuration
    @EnableWebSocket
    public class WebsocketConfig implements WebSocketConfigurer{

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry webSocketHandlerRegistry) {
    webSocketHandlerRegistry.addHandler(new WebSocketDemoHanlder(),"/demo").setAllowedOrigins("*");
    }
    }

    处理器
    这里我们主要绑定WebSocketSession和我们的推送目标。

    如果是聊天室,则根据约定的规则,进行用户与用户,用户与聊天室的绑定。

    如果是彩票,推送消息到所有的WebSocketSession。

    package com.xuelongjiang.websocketdemo.websocket;

    import com.alibaba.fastjson.JSONObject;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.web.socket.CloseStatus;
    import org.springframework.web.socket.TextMessage;
    import org.springframework.web.socket.WebSocketSession;
    import org.springframework.web.socket.handler.TextWebSocketHandler;

    import java.util.Map;
    import java.util.concurrent.ConcurrentHashMap;

    /**
    * @author xuelongjiang
    */

    public class WebSocketDemoHanlder extends TextWebSocketHandler {

    private Logger logger = LoggerFactory.getLogger(WebSocketDemoHanlder.class);

    private static Map<String,WebSocketSession> userIdSessionMap = new ConcurrentHashMap();
    private static Map<WebSocketSession,String> sessionUserIdMap = new ConcurrentHashMap<>();


    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {

    String payload = message.getPayload();
    logger.info("websocket请求参数payload:{}",payload);
    JSONObject jsonObject = JSONObject.parseObject(payload);
    String action = jsonObject.getString("action");

    if("register".equals(action)){
    logger.info("注册websocket连接");
    String userId = jsonObject.getString("userId");
    logger.info("userId:{}注册session:{}",userId,session.getId());
    userIdSessionMap.put(userId,session);
    sessionUserIdMap.put(session,userId);
    }
    }

    //定时任务获取session
    public static Map<String,WebSocketSession> getUserIdSessionMap(){
    return userIdSessionMap;
    }

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
    super.afterConnectionEstablished(session);
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {

    //连接关闭后移除
    String userId = sessionUserIdMap.get(session);
    userIdSessionMap.remove(userId);
    logger.info("websocket session:{}关闭原因:{}",session,status);
    }
    }

    到这里我们测试一下是否可以连接。

     

     

     

     

    从上面可以看到我们已经和服务端建立了连接。

    websocketSession:可以理解为http的一个会话。会话记录了这一次的通讯对象,我们可以使用seesion发送消息给客户端。

    定时任务
    在上面我们用一个线程安全的map,存储了userId和websocketSession的关系。现在我们用定时任务来发送消息给连接。

    在springboot启动类增加注解@EnableScheduling
    由于websocket和定时任务启动的时候会报错。的时候会报错。增加taskScheduler()方法。

    @SpringBootApplication
    @EnableScheduling
    public class WebsocketdemoApplication {

    public static void main(String[] args) {
    SpringApplication.run(WebsocketdemoApplication.class, args);
    }


    /**
    * 使用 websockt注解的时候,使用@EnableScheduling注解
    * 启动的时候一直报错,增加这个bean 则报错解决。
    * 报错信息: Unexpected use of scheduler.
    *https://stackoverflow.com/questions/49343692/websocketconfigurer-and-scheduled-are-not-work-well-in-an-application
    *
    * @return
    */
    @Bean
    public TaskScheduler taskScheduler(){

    ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
    taskScheduler.setPoolSize(10);
    taskScheduler.initialize();
    return taskScheduler;
    }
    }

    定时任务
    package com.xuelongjiang.websocketdemo.schedule;

    import com.xuelongjiang.websocketdemo.websocket.WebSocketDemoHanlder;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.scheduling.annotation.Scheduled;
    import org.springframework.stereotype.Service;
    import org.springframework.web.socket.TextMessage;
    import org.springframework.web.socket.WebSocketSession;

    import java.util.Map;

    /**
    * 定时任务
    * @author xuelongjiang
    */
    @Service
    public class ScheduleTask {

    private Logger logger = LoggerFactory.getLogger(ScheduleTask.class);

    @Scheduled(cron = "* * 0/1 * * ?")
    public void sendMessage(){

    String message = "你好";

    Map<String,WebSocketSession> map = WebSocketDemoHanlder.getUserIdSessionMap();

    WebSocketSession session = map.get("xuelongjiang");//这里用户ID的获取可以根据具体业务,这里为了更简单的演示。
    if(session != null){
    try {
    session.sendMessage(new TextMessage(message));
    }catch (Exception e){
    logger.error("定时任务异常:{}",e);
    }
    }
    }
    }


    websocket测试地址:http://www.blue-zero.com/WebSocket/
    源码地址:https://github.com/longjiangxue/websocketDemo
    ---------------------
    作者:我爱看明朝
    来源:CSDN
    原文:https://blog.csdn.net/u013565163/article/details/80659828
    版权声明:本文为博主原创文章,转载请附上博文链接!

     

     

     

    SpringMVC 使用websocket向前端实时推送信息

    一、maven项目添加websocket依赖
    在pom.xml中添加依赖


    二、项目中添加websocket相关配置


    1、创建一个WebSocket配置类(这里也可以用配置文件来实现其实),实现接口来配置Websocket请求的路径和拦截器

    package com.example.websocket;


    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;

    import org.springframework.stereotype.Component;
    import org.springframework.web.socket.WebSocketHandler;
    import org.springframework.web.socket.config.annotation.EnableWebSocket;
    import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
    import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
    @Configuration
    @EnableWebSocket
    public class WebSocketConfig implements WebSocketConfigurer {

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
    registry.addHandler(myHandler(), "/myHandler").addInterceptors(new WebSocketInterceptor()).setAllowedOrigins("*");
    }

    @Bean
    public WebSocketHandler myHandler() {
    return new MyHandler();
    }

    }


    加个setAllowedOrigins(“*”)不然可能会报403的错误

    3、创建拦截器,用来记录用户标识,便于后面向特定用户发送消息

    package com.example.websocket;

    import org.springframework.http.server.ServerHttpRequest;
    import org.springframework.http.server.ServerHttpResponse;
    import org.springframework.http.server.ServletServerHttpRequest;
    import org.springframework.stereotype.Component;
    import org.springframework.web.socket.WebSocketHandler;
    import org.springframework.web.socket.server.HandshakeInterceptor;

    import javax.servlet.http.HttpSession;
    import java.util.Map;

    @Component
    public class WebSocketInterceptor implements HandshakeInterceptor {

    @Override
    public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler handler, Map<String, Object> map) throws Exception {
    if (request instanceof ServletServerHttpRequest) {
    ServletServerHttpRequest serverHttpRequest = (ServletServerHttpRequest) request;
    HttpSession session = serverHttpRequest.getServletRequest().getSession();
    if (session != null) {
    map.put("username", session.getAttribute("username"));
    }

    }
    return true;
    }

    @Override
    public void afterHandshake(ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Exception e) {

    }
    }

    4、实现Websocket建立连接、发送消息、断开连接等时候的处理类。

    package com.example.websocket;

    import org.springframework.stereotype.Component;
    import org.springframework.stereotype.Service;
    import org.springframework.web.socket.CloseStatus;
    import org.springframework.web.socket.TextMessage;
    import org.springframework.web.socket.WebSocketMessage;
    import org.springframework.web.socket.WebSocketSession;
    import org.springframework.web.socket.handler.TextWebSocketHandler;

    import java.io.IOException;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.Set;

    @Service
    public class MyHandler extends TextWebSocketHandler {
    //在线用户列表
    private static final Map<String, WebSocketSession> users;
    //用户标识
    private static final String CLIENT_ID = "username";

    static {
    users = new HashMap<String, WebSocketSession>();
    }

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
    System.out.println("成功建立连接");
    String username= getClientId(session);
    System.out.println("5555"+username);
    if (username != null) {
    users.put(username, session);
    session.sendMessage(new TextMessage("成功建立socket连接"));
    System.out.println(username);
    System.out.println(session);
    }
    }

    @Override
    public void handleTextMessage(WebSocketSession session, TextMessage message) {
    // ...
    System.out.println(message.getPayload());

    WebSocketMessage message1 = new TextMessage("server:"+message);
    try {
    session.sendMessage(message1);
    } catch (IOException e) {
    e.printStackTrace();
    }
    }

    /**
    * 发送信息给指定用户
    * @param clientId
    * @param message
    * @return
    */
    public boolean sendMessageToUser(String clientId, TextMessage message) {
    if (users.get(clientId) == null) {
    System.out.println("1313313");
    return false;
    }
    WebSocketSession session = users.get(clientId);
    System.out.println("sendMessage:" + session);
    if (!session.isOpen()) {
    System.out.println("7657");
    return false;
    }
    try {
    session.sendMessage(message);
    } catch (IOException e) {
    System.out.println(e);
    return false;
    }
    return true;
    }

    /**
    * 广播信息
    * @param message
    * @return
    */
    public boolean sendMessageToAllUsers(TextMessage message) {
    boolean allSendSuccess = true;
    Set<String> clientIds = users.keySet();
    WebSocketSession session = null;
    for (String clientId : clientIds) {
    try {
    session = users.get(clientId);
    if (session.isOpen()) {
    session.sendMessage(message);
    }
    } catch (IOException e) {
    e.printStackTrace();
    allSendSuccess = false;
    }
    }

    return allSendSuccess;
    }


    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
    if (session.isOpen()) {
    session.close();
    }
    System.out.println("连接出错");
    users.remove(getClientId(session));
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
    System.out.println("连接已关闭:" + status);
    users.remove(getClientId(session));
    }

    @Override
    public boolean supportsPartialMessages() {
    return false;
    }

    /**
    * 获取用户标识
    * @param session
    * @return
    */
    private String getClientId(WebSocketSession session) {
    try {
    String clientId = (String) session.getAttributes().get(CLIENT_ID);
    return clientId;
    } catch (Exception e) {
    return null;
    }
    }
    }

    5、controller

    @Controller
    public class SocketController {

    @Autowired
    MyHandler handler;


    @RequestMapping("/login/{username}")
    public @ResponseBody String login(HttpSession session, @PathVariable("username") String username) {
    System.out.println("登录接口,username="+usename);
    session.setAttribute("username", username);
    System.out.println(session.getAttribute("username"));

    return "成功";
    }

    @RequestMapping("/message")
    public @ResponseBody String sendMessage() {
    boolean flag = handler.sendMessageToAllUser(4, new TextMessage("你好"));
    System.out.println(flag);
    return "发送";
    }

    }

    6、前端

    //建立websocket
    var ws = new WebSocket("ws://localhost:8080/你的项目名/myHandler")
    ---------------------
    作者:HOMERUNIT
    来源:CSDN
    原文:https://blog.csdn.net/HOMERUNIT/article/details/80861096
    版权声明:本文为博主原创文章,转载请附上博文链接!

    转载于:https://www.cnblogs.com/miracle77hp/p/9913958.html

    展开全文
  • springboot websocket

    千次阅读 热门讨论 2018-12-18 16:10:30
    springboot中怎么使用websocket 其实使用方法网上有很多,但搞不懂这些人为什么手写冗余计数代码,而且加锁粒度还这么大,直接进入正题。 本文适合读者:会搭建springboot web 项目,会使用maven。 springboot...

    springboot中怎么使用websocket

    其实使用方法网上有很多,但搞不懂这些人为什么手写冗余计数代码,而且加锁粒度还这么大,直接进入正题。

    本文适合读者:会搭建springboot web 项目,会使用maven。

    springboot相比spring而言所需配置少很多,废话不多说,代码如下

    首先websocket所需pom如下:

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

    Config配置类:

    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.socket.server.standard.ServerEndpointExporter;
    
    @Configuration
    public class WebSocketConfig {
        @Bean
        public ServerEndpointExporter serverEndpointExporter() {
            return new ServerEndpointExporter();
        }
     
    }

    后端:

    import java.io.IOException;
    import java.util.Set;
    import java.util.concurrent.ConcurrentHashMap;
     
    import javax.websocket.OnClose;
    import javax.websocket.OnError;
    import javax.websocket.OnMessage;
    import javax.websocket.OnOpen;
    import javax.websocket.Session;
    import javax.websocket.server.ServerEndpoint;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.stereotype.Component;
    /**
    * Type: WebSocketServer
    * Description: WebSocketServer,实现服务器客户端平等交流,
    * 		达到服务器可以主动向客户端发生消息
    * @author LYM
    * @date Dec 18, 2018
     */
    @ServerEndpoint(value = "/websocket")
    @Component
    public class WebSocketServer {
    	
    	//日志记录器
    	private static final Logger LOGGER = LoggerFactory.getLogger(WebSocketServer.class);
    	
        //使用道格李的ConcurrentHashSet, 放的是WebSocketServer而不是session为了复用自己方法
        private static transient volatile Set<WebSocketServer> webSocketSet = ConcurrentHashMap.newKeySet();
     
        //与某个客户端的连接会话,需要通过它来给客户端发送数据
        private Session session;
     
        /**
         * 连接建立成功调用的方法*/
        @OnOpen
        public void onOpen(Session session) {
            this.session = session;
            webSocketSet.add(this);     //加入set中
            sendMessage("连接成功");
        }
     
        /**
         * 连接关闭调用的方法
         */
        @OnClose
        public void onClose() {
            webSocketSet.remove(this);  //从set中删除
        }
     
        /**
         * 收到客户端消息后调用的方法
         * @param message 客户端发送过来的消息*/
        @OnMessage
        public void onMessage(String message, Session session) {
        	LOGGER.info("来自客户端(" + session.getId() + ")的消息:" + message);
        	sendMessage("Hello, nice to hear you! There are " + webSocketSet.size() + " users like you in total here!");
        }
     
    	/**
    	 * Title: onError
    	 * Description: 发生错误时候回调函数
    	 * @param session
    	 * @param error
    	 */
        @OnError
        public void onError(Session session, Throwable error) {
            LOGGER.error("webSocket发生错误:" + error.getClass() + error.getMessage());
        }
     
        /**
         * Title: sendMessage
         * Description: 向客户端发送消息
         * @param message
         * @throws IOException
         */
        public boolean sendMessage(String message) {
            try {
    			this.session.getBasicRemote().sendText(message);
    			return true;
    		} catch (IOException error) {
    			LOGGER.error("webSocket-sendMessage发生错误:" + error.getClass() + error.getMessage());
    			return false;
    		}
        }
     
     
        /**
         * 群发自定义消息
         * */
        public static void sendInfo(String message) {
        	LOGGER.info("webSocket-sendInfo群发消息:" + message);
            for (WebSocketServer item : webSocketSet) {
                item.sendMessage(message);
            }
        }
     
        /**
         * Title: getOnlineCount
         * Description: 获取连接数
         * @return
         */
        public static int getOnlineCount() {
            return webSocketSet.size();
        }
    }
    

    (仅供测试↑)

    html

    (这使用的是thymeleaf模板,想直接用html可以把th部分去掉,改成自己的)

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head>
    	<title>WebSocket测试</title>
    		<meta charset="utf-8">
    		<script th:src="@{/js/jquery-3.3.1.min.js}"></script>
    		<script th:src="@{/js/sockjs.min.js}"></script>
    </head>
    <body>
    	 <!-----start-main---->
    	 <div class="main">
    			<h2>socketTest</h2>
    			<input type="button" id="send" value="点击向服务器发送消息">
    			<p id="recive"></p>
    
    	</div>
    	<!-----//end-main---->
    </body>
    <script type="text/javascript">
    var ws = null;
    var ws_status = false;
    function openWebSocket(){
        //判断当前浏览器是否支持WebSocket
        if ('WebSocket' in window) {
            ws = new WebSocket("ws://"+window.location.host+"/websocket");
        } else if ('MozWebSocket' in window) {
            websocket = new MozWebSocket("ws://"+window.location.host+"/websocket");
        } else {
            ws = new SockJS("http://"+window.location.host+"/websocket");
        }
        ws.onopen = function () {
    
        };
      //这个事件是接受后端传过来的数据
        ws.onmessage = function (event) {
            //根据业务逻辑解析数据
            console.log("Server:");
            console.log(event);
        };
        ws.onclose = function (event) {
    		console.log("Connection closed!");
        };
        ws.onopen = function (event){
        	ws_status = true;
        	console.log("Connected!");
        };
        ws.onerror = function (event){
        	console.log("Connect error!");
        };
    }
    //如果连接失败,每隔两秒尝试重新连接
    setInterval(function(){
    	if(!ws_status){
    		openWebSocket(); 
    	}
    }, 2000);
    $("#send").click(function(){
    	ws.send("Hello, server, I am browser.");
    });
    </script>
    </html>

    GIT地址:https://github.com/ChinaLym/webpractice

    前端很low,打开F12测试就会看到相应消息,支持断线重接。

     

    若有问题,欢迎留言和指正!

     

    展开全文
  • 主要介绍了springboot websocket简单入门示例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
  • springboot Websocket

    2018-01-12 10:43:14
    springboot项目中使用websocket做推送,虽然挺简单的,但初学也踩过几个坑,特此记录。  使用websocket有两种方式:1是使用sockjs,2是使用h5的标准。使用Html5标准自然更方便简单,所以记录的是配合h5的使用...

    本文只作为个人笔记,大部分代码是引用其他人的文章的。

    在springboot项目中使用websocket做推送,虽然挺简单的,但初学也踩过几个坑,特此记录。

      使用websocket有两种方式:1是使用sockjs,2是使用h5的标准。使用Html5标准自然更方便简单,所以记录的是配合h5的使用方法。

    1、pom

      核心是@ServerEndpoint这个注解。这个注解是Javaee标准里的注解,tomcat7以上已经对其进行了实现,如果是用传统方法使用tomcat发布项目,只要在pom文件中引入javaee标准即可使用。
      

      <dependency>
          <groupId>javax</groupId>
          <artifactId>javaee-api</artifactId>
          <version>7.0</version>
          <scope>provided</scope>
        </dependency>

     但使用springboot的内置tomcat时,就不需要引入javaee-api了,spring-boot已经包含了。使用springboot的websocket功能首先引入springboot组件。
     

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

    顺便说一句,springboot的高级组件会自动引用基础的组件,像spring-boot-starter-websocket就引入了spring-boot-starter-web和spring-boot-starter,所以不要重复引入。

    2、使用@ServerEndpoint创立websocket endpoint

      首先要注入ServerEndpointExporter,这个bean会自动注册使用了@ServerEndpoint注解声明的Websocket endpoint。要注意,如果使用独立的servlet容器,而不是直接使用springboot的内置容器,就不要注入ServerEndpointExporter,因为它将由容器自己提供和管理。
      

    @Component
    public class WebSocketConfig {
        @Bean
        public ServerEndpointExporter serverEndpointExporter() {
            return new ServerEndpointExporter();
        }
    
    }
    @ServerEndpoint(value = "/websocket")
    @Component
    public class MyWebSocket {
        //静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
        private static int onlineCount = 0;
    
        //concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。
        private static CopyOnWriteArraySet<MyWebSocket> webSocketSet = new CopyOnWriteArraySet<MyWebSocket>();
    
        //与某个客户端的连接会话,需要通过它来给客户端发送数据
        private Session session;
    
        /**
         * 连接建立成功调用的方法*/
        @OnOpen
        public void onOpen(Session session) {
            this.session = session;
            webSocketSet.add(this);     //加入set中
            addOnlineCount();           //在线数加1
            System.out.println("有新连接加入!当前在线人数为" + getOnlineCount());
            try {
                sendMessage(CommonConstant.CURRENT_WANGING_NUMBER.toString());
            } catch (IOException e) {
                System.out.println("IO异常");
            }
        }
    
        /**
         * 连接关闭调用的方法
         */
        @OnClose
        public void onClose() {
            webSocketSet.remove(this);  //从set中删除
            subOnlineCount();           //在线数减1
            System.out.println("有一连接关闭!当前在线人数为" + getOnlineCount());
        }
    
        /**
         * 收到客户端消息后调用的方法
         *
         * @param message 客户端发送过来的消息*/
        @OnMessage
        public void onMessage(String message, Session session) {
            System.out.println("来自客户端的消息:" + message);
    
    
        }
    
        /**
         * 发生错误时调用
        @OnError
        public void onError(Session session, Throwable error) {
            System.out.println("发生错误");
            error.printStackTrace();
        }
    
    
        public void sendMessage(String message) throws IOException {
            this.session.getBasicRemote().sendText(message);
            //this.session.getAsyncRemote().sendText(message);
        }
    
    
        /**
         * 群发自定义消息
         * */
        public static void sendInfo(String message) throws IOException {
            for (MyWebSocket item : webSocketSet) {
                try {
                    item.session.getBasicRemote().sendText(message);
                } catch (IOException e) {
                    continue;
                }
            }
        }
    
        public static synchronized int getOnlineCount() {
            return onlineCount;
        }
    
        public static synchronized void addOnlineCount() {
            MyWebSocket.onlineCount++;
        }
    
        public static synchronized void subOnlineCount() {
            MyWebSocket.onlineCount--;
        }
    }

    使用springboot的唯一区别是要@Component声明下,而使用独立容器是由容器自己管理websocket的,但在springboot中连容器都是spring管理的。

    虽然@Component默认是单例模式的,但springboot还是会为每个websocket连接初始化一个bean,所以可以用一个静态set保存起来。

    3、前端代码

    <!DOCTYPE HTML>
    <html>
    <head>
        <title>My WebSocket</title>
    </head>
    
    <body>
    Welcome<br/>
    <input id="text" type="text" /><button onclick="send()">Send</button>    <button onclick="closeWebSocket()">Close</button>
    <div id="message">
    </div>
    </body>
    
    <script type="text/javascript">
        var websocket = null;
    
        //判断当前浏览器是否支持WebSocket
        if('WebSocket' in window){
            websocket = new WebSocket("ws://localhost:8084/websocket");
        }
        else{
            alert('Not support websocket')
        }
    
        //连接发生错误的回调方法
        websocket.onerror = function(){
            setMessageInnerHTML("error");
        };
    
        //连接成功建立的回调方法
        websocket.onopen = function(event){
            setMessageInnerHTML("open");
        }
    
        //接收到消息的回调方法
        websocket.onmessage = function(event){
            setMessageInnerHTML(event.data);
        }
    
        //连接关闭的回调方法
        websocket.onclose = function(){
            setMessageInnerHTML("close");
        }
    
        //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
        window.onbeforeunload = function(){
            websocket.close();
        }
    
        //将消息显示在网页上
        function setMessageInnerHTML(innerHTML){
            document.getElementById('message').innerHTML += innerHTML + '<br/>';
        }
    
        //关闭连接
        function closeWebSocket(){
            websocket.close();
        }
    
        //发送消息
        function send(){
            var message = document.getElementById('text').value;
            websocket.send(message);
        }
    </script>
    </html>

     4、总结

      springboot已经做了深度的集成和优化,要注意是否添加了不需要的依赖、配置或声明。由于很多讲解组件使用的文章是和spring集成的,会有一些配置,在使用springboot时,由于springboot已经有了自己的配置,再这些配置有可能导致各种各样的异常。

    展开全文
  • 什么是WebSocket?WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在 WebSocket API 中,...

    v2-c683aae15ee39b2304c5e4382ecdcc1d_b.jpg

    什么是WebSocket?

    WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。

    WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。

    在 WebSocket API 中,浏览器和服务器只需要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送。

    v2-e5a75028a5356e6fefbca745a5008e98_b.jpg

    话不多说,马上进入干货时刻。

    maven依赖

    SpringBoot2.0对WebSocket的支持简直太棒了,直接就有包可以引入

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

    WebSocketConfig

    启用WebSocket的支持也是很简单,几句代码搞定

    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.socket.server.standard.ServerEndpointExporter;
    
    /**
     * 开启WebSocket支持
     * @author zhengkai
     */
    @Configuration  
    public class WebSocketConfig {  
        @Bean  
        public ServerEndpointExporter serverEndpointExporter() {  
            return new ServerEndpointExporter();  
        }  
    } 
    

    WebSocketServer

    因为WebSocket是类似客户端服务端的形式(采用ws协议),那么这里的WebSocketServer其实就相当于一个ws协议的Controller直接@ServerEndpoint("/websocket")、@Component启用即可,然后在里面实现@OnOpen,@onClose,@onMessage等方法

    import java.io.IOException;
    import java.util.concurrent.CopyOnWriteArraySet;
    
    import javax.websocket.OnClose;
    import javax.websocket.OnError;
    import javax.websocket.OnMessage;
    import javax.websocket.OnOpen;
    import javax.websocket.Session;
    import javax.websocket.server.ServerEndpoint;
    import org.springframework.stereotype.Component;
    import cn.hutool.log.Log;
    import cn.hutool.log.LogFactory;
    import lombok.extern.slf4j.Slf4j;
    
    
    @ServerEndpoint("/websocket/{sid}")
    @Component
    public class WebSocketServer {
    
        static Log log=LogFactory.get(WebSocketServer.class);
        //静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
        private static int onlineCount = 0;
        //concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。
        private static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<WebSocketServer>();
    
        //与某个客户端的连接会话,需要通过它来给客户端发送数据
        private Session session;
    
        //接收sid
        private String sid="";
        /**
         * 连接建立成功调用的方法*/
        @OnOpen
        public void onOpen(Session session,@PathParam("sid") String sid) {
            this.session = session;
            webSocketSet.add(this);     //加入set中
            addOnlineCount();           //在线数加1
            log.info("有新窗口开始监听:"+sid+",当前在线人数为" + getOnlineCount());
            this.sid=sid;
            try {
                 sendMessage("连接成功");
            } catch (IOException e) {
                log.error("websocket IO异常");
            }
        }
    
        /**
         * 连接关闭调用的方法
         */
        @OnClose
        public void onClose() {
            webSocketSet.remove(this);  //从set中删除
            subOnlineCount();           //在线数减1
            log.info("有一连接关闭!当前在线人数为" + getOnlineCount());
        }
    
        /**
         * 收到客户端消息后调用的方法
         *
         * @param message 客户端发送过来的消息*/
        @OnMessage
        public void onMessage(String message, Session session) {
            log.info("收到来自窗口"+sid+"的信息:"+message);
            //群发消息
            for (WebSocketServer item : webSocketSet) {
                try {
                    item.sendMessage(message);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    
        /**
         * 
         * @param session
         * @param error
         */
        @OnError
        public void onError(Session session, Throwable error) {
            log.error("发生错误");
            error.printStackTrace();
        }
        /**
         * 实现服务器主动推送
         */
        public void sendMessage(String message) throws IOException {
            this.session.getBasicRemote().sendText(message);
        }
    
    
        /**
         * 群发自定义消息
         * */
        public static void sendInfo(String message,@PathParam("sid") String sid) throws IOException {
            log.info("推送消息到窗口"+sid+",推送内容:"+message);
            for (WebSocketServer item : webSocketSet) {
                try {
                    //这里可以设定只推送给这个sid的,为null则全部推送
                    if(sid==null) {
                        item.sendMessage(message);
                    }else if(item.sid.equals(sid)){
                        item.sendMessage(message);
                    }
                } catch (IOException e) {
                    continue;
                }
            }
        }
    
        public static synchronized int getOnlineCount() {
            return onlineCount;
        }
    
        public static synchronized void addOnlineCount() {
            WebSocketServer.onlineCount++;
        }
    
        public static synchronized void subOnlineCount() {
            WebSocketServer.onlineCount--;
        }
    }
    

    消息推送

    至于推送新信息,可以再自己的Controller写个方法调WebSocketServer.sendInfo();即可

    @Controller
    @RequestMapping("/checkcenter")
    public class CheckCenterController {
    
        //页面请求
        @GetMapping("/socket/{cid}")
        public ModelAndView socket(@PathVariable String cid) {
            ModelAndView mav=new ModelAndView("/socket");
            mav.addObject("cid", cid);
            return mav;
        }
        //推送数据接口
        @ResponseBody
        @RequestMapping("/socket/push/{cid}")
        public ApiReturnObject pushToWeb(@PathVariable String cid,String message) {  
            try {
                WebSocketServer.sendInfo(message,cid);
            } catch (IOException e) {
                e.printStackTrace();
                return ApiReturnUtil.error(cid+"#"+e.getMessage());
            }  
            return ApiReturnUtil.success(cid);
        } 
    } 
    

    前端页面

    在页面用js代码调用socket,当然,太古老的浏览器是不行的,一般新的浏览器或者谷歌浏览器是没问题的。

    <!DOCTYPE HTML>
    <html>
       <head>
       <meta charset="utf-8">
       <title>菜鸟教程(runoob.com)</title>
    
          <script type="text/javascript">
             function WebSocketTest()
             {
                if ("WebSocket" in window)
                {
                   alert("您的浏览器支持 WebSocket!");
    
                   // 打开一个 web socket
                   var ws = new WebSocket("ws://127.0.0.1:8080/websocket/1212");
    
                   ws.onopen = function()
                   {
                      // Web Socket 已连接上,使用 send() 方法发送数据
                      ws.send("发送数据");
                      alert("数据发送中...");
                   };
    
                   ws.onmessage = function (evt) 
                   { 
                      var received_msg = evt.data;
                      alert(received_msg)
                      alert("数据已接收...");
                   };
    
                   ws.onclose = function()
                   { 
                      // 关闭 websocket
                      alert("连接已关闭..."); 
                   };
                }
    
                else
                {
                   // 浏览器不支持 WebSocket
                   alert("您的浏览器不支持 WebSocket!");
                }
             }
          </script>
    
       </head>
       <body>
    
          <div id="sse">
             <a href="javascript:WebSocketTest()">运行 WebSocket</a>
          </div>
    
       </body>
    </html>
    

    运行

    1、启动springboot项目。

    2、直接打开页面test.html,点击链接

    v2-18369affc149cac5a14c6bc6fe3ceb45_b.jpg

    3、服务端发送消息:

    http://localhost:8080/checkcenter/socket/push/1212?message=xxxx
    

    v2-68cad71f5554204b309680341d1e0779_b.jpg
    展开全文
  • 主要介绍了springboot websocket集群(stomp协议)连接时候传递参数,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
  • 主要介绍了SpringBoot webSocket实现发送广播、点对点消息和Android接收,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。
  • 使用 springboot websocket 定时任务 实现消息的 一连接推送 , 关闭推送 , 连接中定时推送 实现步骤 打开 eclipse ,新建一个 springboot 项目 pom.xml 中加入相关依赖,如下 <dependencies> <...
  • springboot websocket通讯示例目录1.js代码2.java代码总结 目录 1.js代码 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>WebSocket</title> <...
  • SpringBoot WebSocket消息推送(群发和指定到个人或多人),导入项目可以直接运行。
  • springboot websocket service自动注入问题 自动注入失败, 原因:由于websocket是多对象的但是spring是单例的只能创建一个service对 象,因此当websocket进行多次调用的时候,service对象是报空指针异常(java....
  • SpringBoot WebSocket之多人聊天室实现WebSocket简介什么是WebSocket?为什么使用WebSocketWebSocket的技术特点:WebSocket的技术优点:WebSocket事件:实现聊天室的功能功能解析首先实现页面搭建:引入相关的依赖...
  • SpringBoot WebSocket整合

    2021-01-19 14:49:58
    SpringBoot系列-websocket整合SpringBoot整合WebSocket教程前言一、技术介绍1.WebSocket是什么?二、使用步骤1.引入maven库2.WebSocket具体使用示例3.配置文件4.单元测试总结 SpringBoot整合WebSocket教程 从今天起...
  • springboot websocket 解决不能注入bean问题
  • SpringBoot+ WebSocket 学习用Demo,一对一,一对多聊天
  • springboot webSocket实现群聊/单聊 webSocket简介: WebSocket是一种在单个TCP连接上进行全双工通信的协议。WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在WebSocket...
  • 微信小程序,通过实时聊天增强客户体验,websocket首屈一指,看了网上些许资料,终于搞定,特记录此,相关技术:springboot mongodb nginx websocket,如有符合你的技术架构,不胜荣幸。 废话不多说,本人分以下几步 ...
  • 19_SpringBoot WebSocket 广播式 WebSocket 是为浏览器和服务端提供双工异步通信的功能 浏览器可以向服务端发送消息,服务端也可以向浏览器发送消息 WebSocket 需要浏览器的支持(现在的浏览器基本上都支持) ...
  • WebSocket 协议是基于 TCP 的一种新的网络协议。它实现了浏览器与服务器全双工 (full-duplex) 通信—允许服务器主动发送信息给客户端。为什么需要WebSocket?大家都知道以前客户端想知道服务端的处理进度,要不停地...
  • WebSocket协议,客户端和服务端都可以主动的推送消息,可以是文本也可以是二进制数据。而且没有同源策略的限制,不存在跨域问题。协议的标识符就是ws。...SpringBoot集成WebSocket第一步:新建一个spring boot项...
  • 介绍 系统使用springboot开发,用到了websocket推送消息到页面,但是登陆系统后,报错信息如下:WebSocket connection to 'ws://192.168.1.141:8089/finesys_user/lehoon' failed: Error during WebSocket handshake...
  • 所以决定使用另一种方案,websocket。以前就知道websocket,属于全双工长连接,适合实时在线聊天,浏览器之间的协同编辑工作,多人在线游戏等场景。但是一直没机会用,今天正好可以使用一下。简单记录一下步骤,亲测...
  • spring boot+ websocket 推送1.配置类上篇文章我们提到过stomp.js 和 sockjs,下面我将基于stomp上层协议编写配置类,与上篇文章中的配置类有所不同。好了,不多比比,直接上代码@Configuration@EnableWebSocke...
  • 关于springboot websocket 可以参考我之前的文章 https://blog.csdn.net/qq_34168515/article/details/107578932 二、js websocket 传递token websocket协议在握手阶段借用了HTTP的协议,但是在JavaScript websocket

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 5,331
精华内容 2,132
热门标签
关键字:

springbootwebsocket

spring 订阅