标签:触发 websocket SpringTask sid WebSocket message 连接
Spring Task,WebSocket
Spring Task
介绍:
- Spring Task是Spring框架提供的任务调度工具,可以按照约定的时间自动执行某个代码逻辑;
- 定位:定时任务框架
- 作用:定时自动执行某段Java代码;
应用场景:
- 信用卡每月还款提醒;
- 银行贷款每月还款提醒;
- 火车票售票系统处理未支付订单;
- 入职纪念日为用户发送通知;
cron表达式:
介绍:
- cron表达式其实就是一个字符串,通过cron表达式可以定义任务触发的时间;
- 构成规则:分为6或7个域,由空格分隔开,每个域代表一个含义;
- 每个域的含义分别为:秒、分钟、小时、日、月、周、年(可选);
各字段含义:
字段 |
允许值 |
允许的特殊字符 |
秒(Seconds) |
0~59的整数 |
, - * / 四个字符 |
分(Minutes) |
0~59的整数 |
, - * / 四个字符 |
小时(Hours) |
0~23的整数 |
, - * / 四个字符 |
日期(DayofMonth) |
1~31的整数(但是你需要考虑你月的天数) |
, - * ? / L W C 八个字符 |
月份(Month) |
1~12的整数或者 JAN-DEC |
, - * / 四个字符 |
星期(DayofWeek) |
1~7的整数或者 SUN-SAT(1=SUM) |
, - * ? / L C # 八个字符 |
年(可选,留空)(Year) |
1970~2099 |
, - * / 四个字符 |
特殊字符含义
- * :表示匹配该域的任意值。假如在Minutes域使用,即表示每分钟都会触发事件。
- ?:只能用在DayofMonth和DayofWeek两个域。它也匹配域的任意值,但实际不会。因为DayofMonth和DayofWeek会相互影响。例如想在每月的20日触发调度,不管20日到底是星期几,则只能使用如下写法:1313 15 20*?,其中最后一位只能用?,而不能使用*,如果使用*表示不管星期几都会触发,实际上并不是这样。
-
- :表示范围。例如在Minutes域使用5-20,表示从5分到20分钟每分钟触发一次
- /:表示起始时间开始触发,然后每隔固定时间触发一次。例如在Minutes域使用5/20,则意味着第5分钟触发一次,之后每隔20分钟触发一次;
- ,:表示列出枚举值。例如:在Minutes域使用5,20,则意味着在5和20分每分钟触发一次。
- L:表示最后,只能出现在DayofWeek和DayofMonth域。在DayofMonth域使用L,表示最后一天;如果在DayofWeek域使用5L,意味着在最后的一个星期五触发。
- W:表示有效工作日(周一到周五),只能出现在DayofMonth域,系统将在离指定日期的最近的有效工作日触发事件。例如:在DayofMonth使用5W,如果5日是星期六,则将在最近的工作日:星期五,即4日触发。如果5日是星期天,则在6日(周一)触发;如果5日在星期一到星期五中的一天,则就在5日触发。另外一点,W的最近寻找不会跨过月份。
- LW:这两个字符可以连用,表示在某个月最后一个工作日,即最后一个星期五。
-
:用于确定每个月第几个星期几,只能出现在DayofMonth域。例如在4#2,表示某月的第四个星期二,第四周的星期二。
例子:
秒 |
分钟 |
小时 |
日 |
月 |
周 |
年 |
0 |
0 |
9 |
12 |
10 |
? |
2022 |
- 2022年10月12日上午9点整 对应的表达式为:0 0 9 12 10 ? 2022
在线工具:
使用步骤:
- 导入maven坐标 spring-context(已存在),没有属于自己的jar包,集成在spring-context中;
- 启动类添加注解 @EnableScheduling 开启任务调度;
- 自定义定时任务类:
- 类中添加方法,方法添加 @Scheduled 注解设置定时执行;
- 注解参数为 cron表达式;
自定义定时任务类:
@Component
@Slf4j
public class MyTask {
// 定时任务 每隔5秒触发一次
@Scheduled(cron = "0/5 * * * * ?")
public void executeTask(){
log.info("定时任务开始执行");
}
}
WebSocket
介绍:
简介:
- WebSocket是基于TCP的一种新的网络协议。它实现了浏览器与服务器全双工通信——浏览器和服务器只需要完成一次握手,两者之间就可以创建持久性的连接,并进行双向数据传输;
HTTP协议和WebSocket协议对比:
- HTTP是短连接;
- WebSocket是长连接;
- HTTP通信是单向的,基于请求响应模式;
- WebSocket支持双向通信;
- HTTP和WebSocket底层都是TCP连接;
应用场景:
- 视频弹幕;
- 网页聊天;
- 体育实况更新;
- 股票基金报价实时更新;
后端实施:
简介:
- 导入WebSocket的maven坐标;
- 创建一个配置类,注册WebSocket的服务端组件;
- 创建WebSocket服务端组件自定义类,用于和客户端通信;
导入依赖:
- 在pom.xml中导入WebSocket的maven坐标:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</<artifactId>>
</dependency>
配置类开启对WebSocket的支持:
/**
*注册WebSocket的服务端组件
*/
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter(){
return new ServerEndpointExporter();
}
}
WebSocket服务端, 用于与客户端通信:
- 添加注解会自动回调:
session
: 在WebSocket上下文中,session
对象代表了一个打开的WebSocket会话。这个对象提供了与远程端点通信的方法和属性。
getBasicRemote()
: 这是Session
对象的一个方法,它返回一个RemoteEndpoint.Basic
对象。RemoteEndpoint.Basic
是一个接口,它提供了发送文本消息、二进制消息以及关闭连接等方法。
sendText(message)
: 这是RemoteEndpoint.Basic
接口的一个方法,它用于向远程端点发送一个文本消息。参数message
是一个字符串,代表了要发送的消息内容。
package com.sky.websocket;
import org.springframework.stereotype.Component;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
/**
* WebSocket服务
*/
@Component
// 定义WebSocket服务器端点的访问路径
@ServerEndpoint("/ws/{sid}")
public class WebSocketServer {
//存放会话对象
private static Map<String, Session> sessionMap = new HashMap();
/**
* 连接建立成功调用的方法
*/
@OnOpen
public void onOpen(Session session, @PathParam("sid") String sid) {
System.out.println("客户端:" + sid + "建立连接");
sessionMap.put(sid, session);
}
/**
* 收到客户端消息后调用的方法
*
* @param message 客户端发送过来的消息
*/
@OnMessage
public void onMessage(String message, @PathParam("sid") String sid) {
System.out.println("收到来自客户端:" + sid + "的信息:" + message);
}
/**
* 连接关闭调用的方法
*
* @param sid
*/
@OnClose
public void onClose(@PathParam("sid") String sid) {
System.out.println("连接断开:" + sid);
sessionMap.remove(sid);
}
/**
* 群发
*
* @param message
*/
public void sendToAllClient(String message) {
Collection<Session> sessions = sessionMap.values();
for (Session session : sessions) {
try {
//服务器向客户端发送消息
session.getBasicRemote().sendText(message);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
前端实施:
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<title>WebSocket Demo</title>
</head>
<body>
<input id="text" type="text" />
<button onclick="send()">发送消息</button>
<button onclick="closeWebSocket()">关闭连接</button>
<div id="message">
</div>
</body>
<script type="text/javascript">
var websocket = null;
// 生成随机id,防止重复
var clientId = Math.random().toString(36).substr(2);
// 判断当前浏览器是否支持WebSocket
if('WebSocket' in window){
// 连接WebSocket节点
websocket = new WebSocket("ws://localhost:8080/ws/"+clientId);
}
else{
alert('Not support websocket')
}
// 连接发生错误的回调方法
websocket.onerror = function(){
setMessageInnerHTML("error");
};
// 连接成功建立的回调方法
websocket.onopen = function(){
setMessageInnerHTML("连接成功");
}
// 接收到消息的回调方法
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 send(){
var message = document.getElementById('text').value;
websocket.send(message);
}
// 关闭连接
function closeWebSocket() {
websocket.close();
}
</script>
</html>
标签:触发,
websocket,
SpringTask,
sid,
WebSocket,
message,
连接
From: https://www.cnblogs.com/chj020415/p/18225760