springboot成神之——websocket发送和请求消息
本文介绍如何使用websocket发送和请求消息
项目目录

依赖
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
DemoApplication
package com.springlearn.learn;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoApplication {
	public static void main(String[] args) {
		SpringApplication.run(DemoApplication.class, args);
	}
}
MessageModel
package com.springlearn.learn.model;
public class MessageModel {
    private String name;
    public String getName() {
        return "测试成功" + name;
    }
    public void setName(String name) {
        this.name = name;
    }
}
WebConfig
package com.springlearn.learn.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
@EnableScheduling
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**").allowedOrigins("*").allowedMethods("GET", "POST", "PUT", "DELETE").allowedOrigins("*")
        .allowedHeaders("*");
    }
}
WebSocketConfig
package com.springlearn.learn.config;
import com.springlearn.learn.Handler.HttpHandshakeInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
    @Autowired
    private HttpHandshakeInterceptor handshakeInterceptor; // 这个是自定义的拦截器
    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/ws").setAllowedOrigins("*").withSockJS().setInterceptors(handshakeInterceptor);
    }
    @Override
    public void configureMessageBroker(MessageBrokerRegistry registry) {
        registry.setApplicationDestinationPrefixes("/app"); // 前端发送消息的前缀
        registry.enableSimpleBroker("/topic"); // 前端接收后台消息和后台发送消息给前端的前缀
    }
}
HttpHandshakeInterceptor
package com.springlearn.learn.Handler;
import java.util.Map;
import javax.servlet.http.HttpSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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;
@Component
public class HttpHandshakeInterceptor implements HandshakeInterceptor {
    private static final Logger logger = LoggerFactory.getLogger(HttpHandshakeInterceptor.class);
    @Override
    public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
        logger.info("Call beforeHandshake"); // 和out一样,输出语句,正式开发用这个多
        if (request instanceof ServletServerHttpRequest) {
            ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request;
            HttpSession session = servletRequest.getServletRequest().getSession();
            attributes.put("sessionId", session.getId());
        }
        return true;
    }
    public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
            Exception ex) {
        logger.info("Call afterHandshake");
    }
}
WebSocketEventListener
// 监听器,监听socket连接和短线
package com.springlearn.learn.listener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.messaging.simp.SimpMessageSendingOperations;
import org.springframework.messaging.simp.stomp.StompHeaderAccessor;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.messaging.SessionConnectedEvent;
import org.springframework.web.socket.messaging.SessionDisconnectEvent;
@Component
public class WebSocketEventListener {
    private static final Logger logger = LoggerFactory.getLogger(WebSocketEventListener.class);
    @Autowired
    private SimpMessageSendingOperations messagingTemplate;
    @EventListener
    public void handleWebSocketConnectListener(SessionConnectedEvent event) {
        logger.info("Received a new web socket connection");
    }
    @EventListener
    public void handleWebSocketDisconnectListener(SessionDisconnectEvent event) {
        StompHeaderAccessor headerAccessor = StompHeaderAccessor.wrap(event.getMessage());
        String username = (String) headerAccessor.getSessionAttributes().get("username");
        if(username != null) {
            logger.info("User Disconnected : " + username);
            messagingTemplate.convertAndSend("/topic/getResponse", "User Disconnected : " + username);
        }
    }
}
WebSocketController
package com.springlearn.learn.controller;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import com.springlearn.learn.model.MessageModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.messaging.simp.SimpMessageHeaderAccessor;
import org.springframework.messaging.simp.SimpMessageSendingOperations;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Controller;
@Controller
public class WebSocketController {
    private static final DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss sss");
    @Autowired
    private SimpMessageSendingOperations messagingTemplate;
    @MessageMapping("/welcome")
    @SendTo("/topic/getResponse")
    public MessageModel sendMessage(@Payload MessageModel requestMessage, SimpMessageHeaderAccessor headerAccessor) {
        headerAccessor.getSessionAttributes().put("username", requestMessage.getName());
        MessageModel message = new MessageModel();
        message.setName(requestMessage.getName());
        return message;
    }
    @Scheduled(cron="* * * * * *" )
    @SendTo("/topic/getResponse")
    public Object callback() throws Exception {
        Date now = new Date();
        messagingTemplate.convertAndSend("/topic/getResponse", df.format(now));
        return "callback";
    }
}
前端测试
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script>
    <link rel="stylesheet" href="//unpkg.com/iview/dist/styles/iview.css">
    <script src="//unpkg.com/iview/dist/iview.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/sockjs-client@1/dist/sockjs.min.js"></script>
    <script  src="https://cdnjs.cloudflare.com/ajax/libs/stomp.js/2.3.3/stomp.min.js"></script>
</head>
<body>
    <div id="app">
    </div>
    <script>
        new Vue({
            el: '#app',
            mounted () {
                var stompClient = null;
                var socket = new SockJS('http://localhost:9001/ws');
                stompClient = Stomp.over(socket);
                stompClient.connect(
                    {},
                    function (frame) {
                        stompClient.subscribe('/topic/getResponse', function (payload) {
                            console.log(payload.body)
                        })
                        stompClient.send(
                            "/app/welcome",
                            {},
                            JSON.stringify({name: "yejiawei"})
                        )
                    },
                    function(error) {
                        connectingElement.textContent = 'Could not connect to WebSocket server. Please refresh this page to try again!';
                        connectingElement.style.color = 'red';
                    }
                );
                setTimeout(function() {
                    stompClient.send(
                        "/app/welcome",
                        {},
                        JSON.stringify({name: "来自前端的请求"})
                    )
                }, 3000)
            }
        })
    </script>
</body>
</html>
springboot成神之——websocket发送和请求消息的更多相关文章
- springboot成神之——ioc容器(依赖注入)
		springboot成神之--ioc容器(依赖注入) spring的ioc功能 文件目录结构 lang Chinese English GreetingService MyRepository MyC ... 
- springboot成神之——springboot入门使用
		springboot创建webservice访问mysql(使用maven) 安装 起步 spring常用命令 spring常见注释 springboot入门级使用 配置你的pom.xml文件 配置文 ... 
- springboot成神之——mybatis和mybatis-generator
		项目结构 依赖 generator配置文件 properties配置 生成文件 使用Example 本文讲解如何在spring-boot中使用mybatis和mybatis-generator自动生成 ... 
- springboot成神之——swagger文档自动生成工具
		本文讲解如何在spring-boot中使用swagger文档自动生成工具 目录结构 说明 依赖 SwaggerConfig 开启api界面 JSR 303注释信息 Swagger核心注释 User T ... 
- springboot成神之——log4j2的使用
		本文介绍如何在spring-boot中使用log4j2 说明 依赖 日志记录语句 log4j2配置文件 本文介绍如何在spring-boot中使用log4j2 说明 log4j2本身使用是非常简单的, ... 
- springboot成神之——mybatis在spring-boot中使用的几种方式
		本文介绍mybatis在spring-boot中使用的几种方式 项目结构 依赖 WebConfig DemoApplication 方式一--@Select User DemoApplication ... 
- springboot成神之——发送邮件
		本文介绍如何用spring发送邮件 目录结构 依赖 MailConfig TestController 测试 本文介绍如何用spring发送邮件 目录结构 依赖 <dependency> ... 
- springboot成神之——basic auth和JWT验证结合
		本文介绍basic auth和JWT验证结合 目录结构 依赖 config配置文件WebSecurityConfig filter过滤器JWTLoginFilter filter过滤器JWTAuthe ... 
- springboot成神之——Basic Auth应用
		本文介绍Basic Auth在spring中的应用 目录结构 依赖 入口DemoApplication 验证Authenication 配置WebSecurityConfig 控制器TestContr ... 
随机推荐
- python基础之函数名称空间与作用域
- LeetCode OJ:Integer to Roman(转换整数到罗马字符)
			Given an integer, convert it to a roman numeral. Input is guaranteed to be within the range from 1 t ... 
- Android studio 导入ApiDemo
			1.import 项目,sdk目录:sdk\samples\android-21\legacy\ApiDemos,import时一直下一步就ok了. 2.Error:Error: The file n ... 
- 剑指offer--37.和为S的两个数字
			链接:https://www.nowcoder.com/questionTerminal/390da4f7a00f44bea7c2f3d19491311b来源:牛客网@华科渣硕 不要被题目误导了!证明 ... 
- Golang使用MongoDB通用操作
			MongoDB是Nosql中常用的一种数据库,今天笔者就简单总结一下Golang如何使用这些通用的供能的,不喜勿喷... 研究的事例结构如下: type LikeBest struct { Autho ... 
- ORM版,学生管理系统03
			关于老师信息管理 建立多对多关系 第一种(通过外键建立) 自己写类,自己使其建立关系 缺点: 不能用Django ORM 多对多操作的语法 class Teacher(models.Model): t ... 
- docx转doc时,防止公式被转成图片的解决办法
			编辑社回复需要doc(Word 97-2003)格式的文档,可是将docx(Word 2007+)另存为doc格式时,发现公式被转成了图片.其实,最简单的办法就是,打个电话过去给编辑社:“大爷,拜托您 ... 
- POJ1160 Post Office (四边形不等式优化DP)
			There is a straight highway with villages alongside the highway. The highway is represented as an in ... 
- Python之xpath
			xpath是一种在XML文档中定位元素的语言,常用于xml.html文件解析,比css选择器使用方便XML文件最小构成单元: - element(元素节点) - attribute(属性节点) - t ... 
- YII缓存之数据缓存
			1.开启缓存组件 2. ================ 二 先在配置文件components数组中加上: 'cache'=>array( 'class'=>'CFileCache'), ... 
