hooyantsing's Blog

第121次课程_Springboot_websocket_定时任务

字数统计: 1.4k阅读时长: 7 min
2020/03/08

源辰76班

第121次课程

2020.03.08

内容

Springboot_websocket_定时任务[廖彦]

项目路径:

1.WebSocket

实时性,全双工,本地浏览器(客户端)连接至服务器后,当有消息时,服务器自动推送至本地。

解决了过去技术,每次都要向服务器发送请求,才能获取最新消息的问题。

WebSocket必要依赖

pom.xml

spring-boot-starter-websocket内部集成了spring-boot-starter-web,因此不需要这个依赖。

1
2
3
4
5
6
7
8
<dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<!-- <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-web</artifactId>
</dependency> -->

C76S3PlySpringBootApplication.java

启动器中加入以下代码  @Bean …

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.yc.C76S3PlySpringBoot;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

@SpringBootApplication
//Mybatis包扫描 - 扫接口
@MapperScan("com.yc.C76S3PlySpringBoot")
public class C76S3PlySpringBootApplication {

    public static void main(String[] args) {
        SpringApplication.run(C76S3PlySpringBootApplication.class, args);
    }
    
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }
}

MyWebSocket.java

@OnOpen:获取到连接时的操作。

@OnClose:关闭连接时操作。

@OnMessage:消息处理操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
package com.yc.C76S3PlySpringBoot;
import java.io.IOException;
import java.util.Hashtable;
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 org.springframework.stereotype.Component;
@ServerEndpoint(value = "/websocket/{id}")
@Component
public class MyWebSocket {
     
     private static Hashtable<String,Session>  webSocketMap = new Hashtable<String,Session>();
     
     @OnOpen
     public void onOpen(@PathParam("id")String id,Session  session) {
          System.out.println(session);
          webSocketMap.put(id,session);
     }
     
     @OnClose
     public void onClose(Session session) {
          //webSocketSet.remove(session);
     }
     
     @OnMessage
     public void onMessage(String message,Session  session) throws IOException {
     //逻辑解释:当收到"武松"的消息,message="张三:你好",服务器根据"张三"找到对应的session,然后向session内写入"你好"并传送给前端。
          String[] strings = message.split(":");
          String id = strings[0];
          message = strings[1];
          Session targetSession = webSocketMap.get(id);
          if(targetSession!=null) {
              targetSession.getBasicRemote().sendText(message);
          } else {
              System.out.println(id + " 不在线!");
          }
     }
}

msg.html

前端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
     <script type="text/javascript">
          var websocket;
          function conn(){
              //创建websocket对象
              websocket = new  WebSocket("ws://localhost/websocket/" + manid.value);
              //连接发生错误回调方法
              websocket.onerror = function(){
                   
              }
              //连接成功建立的回调方法
              websocket.onopen = function(event){
                   console.info(event);
              }
              //接收到消息的回调方法
              websocket.onmessage = function(event){
                   console.info(event);
                   msgtxt.innerHTML += event.data + "\n";
              }
              //连接关闭的回调方法
              websocket.onclose = function(){
                   
              }    
          }
          
          //关闭连接
          function closeWebSocket(){
              websocket.close();
          }
          //发送消息
          function send(msg){
              websocket.send(msg);
          }
     </script>
     聊天人:<input id="manid">
     <button onclick="conn()">连接</button><br/>
     消息区:<textarea id="msgtxt" rows="10"  cols=""></textarea><br/>
     我说:<input id="msgid">
     <button onclick="send(msgid.value)">发送</button>
</body>
</html>

样例:

.png

-1.png

2.定时任务

C76S3PlySpringBootApplication.java

启动器内加入**@EnableScheduling**注解。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package com.yc.C76S3PlySpringBoot;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

@SpringBootApplication
//定时任务启动注解
@EnableScheduling
//Mybatis包扫描 - 扫接口
@MapperScan("com.yc.C76S3PlySpringBoot")
public class C76S3PlySpringBootApplication {

    public static void main(String[] args) {
        SpringApplication.run(C76S3PlySpringBootApplication.class, args);
    }
    
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }
}

MyWebSocket.java

任意一个存在**@Component**注解的类,都可以将定时器方法代码加入其中。

定时器方法注解:**@Scheduled(cron=”/5 * 10-13 * * ?”)*

其中: */5 每五秒执行一次。    10-13当天10:00至13:00内执行。

秒 分 时 日 月 星期 年

-2.png

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
package com.yc.C76S3PlySpringBoot;
import java.io.IOException;
import java.util.Hashtable;
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  org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@ServerEndpoint(value = "/websocket/{id}")
@Component
public class MyWebSocket {
     
     private static Hashtable<String,Session>  webSocketMap = new Hashtable<String,Session>();
     
     @OnOpen
     public void onOpen(@PathParam("id")String id,Session  session) {
          System.out.println(session);
          session.getUserProperties().put("id", id);
          webSocketMap.put(id,session);
     }
     
     @OnClose
     public void onClose(Session session) {
          //webSocketSet.remove(session);
     }
     
     @OnMessage
     public void onMessage(String message,Session  session) throws IOException {
          String[] strings = message.split(":");
          String id = strings[0];
          message = strings[1];
          Session targetSession = webSocketMap.get(id);
          if(targetSession!=null) {
              targetSession.getBasicRemote().sendText(message);
          } else {
              System.out.println(id + " 不在线!");
          }
     }
     
     @Scheduled(cron="*/5 * 10-13 * * ?")
     private void process() throws IOException {
          System.out.println("===============" +  System.currentTimeMillis());
          //消息群发
          for(Session session : webSocketMap.values()) {
              String id = (String)  session.getUserProperties().get("id");
              session.getBasicRemote().sendText(id + ":您好,现在的时间是:" + System.currentTimeMillis());
          }
     }
}

cron表达式实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
cron表达式实例:
  0 0 2 1 * ? *   表示在每月的1日的凌晨2点调整任务
  0 15 10 ? * MON-FRI   表示周一到周五每天上午10:15执行作业
  0 15 10 ? 6L 2002-2006   表示2002-2006年的每个月的最后一个星期五上午10:15执行作
  0 0 10,14,16 * * ?   每天上午10点,下午2点,4点
  0 0/30 9-17 * * ?   朝九晚五工作时间内每半小时
  0 0 12 ? * WED    表示每个星期三中午12点
  0 0 12 * * ?   每天中午12点触发
  0 15 10 ? * *    每天上午10:15触发
  0 15 10 * * ?     每天上午10:15触发
  0 15 10 * * ? *    每天上午10:15触发
  0 15 10 * * ? 2005    2005年的每天上午10:15触发
  0 * 14 * * ?     在每天下午2点到下午2:59期间的每1分钟触发
  0 0/5 14 * * ?    在每天下午2点到下午2:55期间的每5分钟触发
CATALOG