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 ...
随机推荐
- (http请求+cookie)的交互流程
如果步骤5携带的是过期的cookie或者是错误的cookie,那么将认证失败,返回至要求身份认证页面. 当前 Cookie 有两个版本:Version 0 和 Version 1.通过它们有两种设置响 ...
- Unity3D事件顺序与功能
Unity3D中所有控制脚本的基类MonoBehaviour有一些虚函数用于绘制中事件的回调,也可以直接理解为事件函数,例如大家都很清楚的Start,Update等函数,以下做个总结. Awake 当 ...
- 在一个Activity中启动另一个Activity
一.新建一个空的工程 二.添加一个Activity并命名为BAty 三.在activity_main.xml中添加一个按钮,设置id号为btnStartB <Button android:lay ...
- UIPickerView/UIDatePicker/程序启动的完整过程
一.UIPickerView 1.UIPickerView的常见属性 数据源(用来告诉UIPickerView有多少列多少行) @property(nonatomic,assign) id<UI ...
- pip国内镜像(清华大学镜像)
网上搜到的pip国内镜像大部分是豆瓣的 http://pypi.douban.com/simple/ 但是根本不全,很多包没有 所以推荐清华大学的 https://pypi.tuna.tsinghua ...
- 7.usr下重要目录和文件详解
1./usr下重要目录和文件详解: /usr(存放用户安装的应用软件目录,如MySQL,Apache,这是一个非常重要的目录,类似于Windows下的Program Files目录,用户的很多应用程序 ...
- for-in和for 循环 的区别
以前早就知道,for...in 语句用于对数组或者对象的属性进行循环操作,而for循环是对数组的元素进行循环,而不能引用于非数组对象, 但咱在js项目里,遇到循环,不管是数组还是对象,经常使用for- ...
- 部署tinyproxy透明代理服务
线上需要一个https的透明代理,开始打算用nginx,调试了一段时间发现配置较复杂且没有成功.后来用的tinyproxy做的透明代理.安装配置过程就是下载.解压.编译.安装.配置.启动一波流: 安装 ...
- input光标位置不居中问题
文本输入框默认在谷歌,火狐浏览器中,光标是居中显示的.但在IE7中一开始会在顶部闪烁(输入文字后光标居中),加上行高就可以,值为文本框的高度. 注意要加*号,否则在谷歌浏览其中光标会在顶部闪烁. *l ...
- LeetCode 621. Task Scheduler
原题链接在这里:https://leetcode.com/problems/task-scheduler/description/ 题目: Given a char array representin ...