springboot2.0集成websocket发送日志

后台引入websocket

在pom.xml中引入依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
package com.plat.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.*;

import com.plat.common.Constant;

@Configuration
@EnableWebSocket
public class WebSocketConfig extends WebSocketMessageBrokerConfigurationSupport {

   @Override
   public void registerStompEndpoints(StompEndpointRegistry stompEndpointRegistry) {
      // 注册一个Stomp的节点(endpoint),并指定使用SockJS协议。
      stompEndpointRegistry.addEndpoint(Constant.WEBSOCKETPATH).setAllowedOrigins("*").withSockJS();
   }

   @Override
   public void configureMessageBroker(MessageBrokerRegistry registry) {
      // 服务端发送消息给客户端的域,多个用逗号隔开
      registry.enableSimpleBroker(Constant.WEBSOCKETBROADCASTPATH, Constant.P2PPUSHBASEPATH);
      // 定义一对一推送的时候前缀
      registry.setUserDestinationPrefix(Constant.P2PPUSHBASEPATH);
      // 定义websoket前缀
      registry.setApplicationDestinationPrefixes(Constant.WEBSOCKETPATHPERFIX);
   }

}
/**
 * 
 */
package com.plat.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Service;

import com.plat.common.Constant;
import com.plat.common.WiselyResponse;

/**   
 * @ClassName:  WebSocketService   
 * @Description:    
 * @author: lcp
 * @date:   2019年12月4日 下午11:23:49   
 *     
 * @Copyright: 2019 www.ankept.com Inc. All rights reserved. 
 */
@Service
public class WebSocketService {
    @Autowired
    private SimpMessagingTemplate template;
 
    /**
     * 广播
     * 发给所有在线用户
     * @param msg
     */
    public void sendMsg(WiselyResponse msg) {
        template.convertAndSend(Constant.PRODUCERPATH, msg);
    }
 
    /**
     * 发送给指定用户
     * @param users
     * @param msg
     */
    public void send2Users(List<String> users, WiselyResponse msg) {
        users.forEach(userName -> {
            template.convertAndSendToUser(userName, Constant.P2PPUSHPATH, msg);
        });
    }
}
public class Constant {
   //webSocket相关配置
   //链接地址
   public static String WEBSOCKETPATHPERFIX = "/ws-push";
   public static String WEBSOCKETPATH = "/endpointWisely";
   //消息代理路径
   public static String WEBSOCKETBROADCASTPATH = "/topic";
   //前端发送给服务端请求地址
   public static final String FORETOSERVERPATH = "/welcome";
   //服务端生产地址,客户端订阅此地址以接收服务端生产的消息
   public static final String PRODUCERPATH = "/topic/getResponse";
   //点对点消息推送地址前缀
   public static final String P2PPUSHBASEPATH = "/user";
   //点对点消息推送地址后缀,最后的地址为/user/用户识别码/msg
   public static final String P2PPUSHPATH = "/msg";
   public static final String LOGCURRENT = "/logcur";
}
public class WiselyMessage {
   private String name;

   public String getName() {
      return name;
   }

   public void setName(String name) {
      this.name = name;
   }
}
public class WiselyResponse {
   private String responseMessage;
    
   public WiselyResponse(String responseMessage){
       this.responseMessage = responseMessage;
   }
    
   public String getResponseMessage() {
       return responseMessage;
   }
    
   public void setResponseMessage(String responseMessage) {
       this.responseMessage = responseMessage;
   }
}

编写服务端接口,向客户端推送日志

@Controller
public class WebSocketController {
	@Value("${logfile-path}")
	private String path;

	@Resource
	WebSocketService webSocketService;
	final DateTimeFormatter ptn = DateTimeFormatter.ofPattern(DateUtils._sdfPattern);

	/**
	 * 	@MessageMapping和@RequestMapping功能类似,用于设置URL映射地址,浏览器向服务器发起请求,需要通过该地址。
	 * 如果服务器接受到了消息,就会对订阅了@SendTo括号中的地址传送消息。
	 * @throws Exception
	 */
	
	@MessageMapping(Constant.LOGCURRENT)
	@SendTo(Constant.PRODUCERPATH)
	public void say() throws Exception {
		String log = logCreator();
		WiselyResponse msg = new WiselyResponse(log);
		if (!log.isEmpty()) {
			webSocketService.sendMsg(msg);
		}else {
			webSocketService.sendMsg(new WiselyResponse("暂无日志"));
		}
	}

private String logCreator() {
		String res = "";
		BufferedReader reader = null;
		try {
			// 日志文件路径,获取最新的
			String filePath = path;

			// 字符流
			reader = new BufferedReader(new FileReader(filePath));
			Object[] lines = reader.lines().toArray();

			// 只取从上次之后产生的日志
			LocalDateTime timeStart = LocalDateTime.now().minusMinutes(10);
			for (int i=0;i<lines.length;i++) {
				String record = (String) lines[i];
				LocalDateTime time = containTime(record);
				if (time!=null && time.isAfter(timeStart)) {
					Object[] copyOfRange = Arrays.copyOfRange(lines, i, lines.length);
					res = Joiner.on("<br>").join(copyOfRange);
					break;	
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if(reader!=null){
					reader.close();
				}
			} catch (IOException ignored) {
			}
		}
		return res;
	}
	private LocalDateTime containTime(String record) {
		LocalDateTime res = null;
		//匹配时间格式2019-10-11 15:03:16
		String regex = "^\\d{4}-\\d{1,2}-\\d{1,2}\\s\\d{1,2}:\\d{1,2}:\\d{1,2}";
		Pattern pattern = Pattern.compile(regex);
		Matcher matcher = pattern.matcher(record);
		if (matcher.find()) {
			res = LocalDateTime.parse(matcher.group(), ptn);
		}
		return res;
	}
}

前端页面

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8" />
    <title>日志</title>
</head>

<body onload="disconnect()">
    <noscript><h2 style="color: #ff0000">貌似你的浏览器不支持websocket</h2>          </noscript>
    <div>
        <div>
            <button id="connect" onclick="connect();">连接日志服务器</button>
            <button id="disconnect" disabled="disabled" onclick="disconnect();">断开连接</button>
        </div>
        <div id="conversationDiv">
<!--             <label>输入你的名字</label><input type="text" id="name" />
 -->            <button id="sendName" onclick="sendName();">获取日志/刷新</button>
            <p id="response"></p>
            <p id="response1"></p>
        </div>
    </div>
    <script src="https://cdn.bootcss.com/sockjs-client/1.1.4/sockjs.min.js">
    </script>
    <script src="https://cdn.bootcss.com/stomp.js/2.3.3/stomp.min.js"></script>
    <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
    <script type="text/javascript">
        var stompClient = null;
        //此值有服务端传递给前端,实现方式没有要求
        var userId = "123";

        function setConnected(connected) {
            document.getElementById('connect').disabled = connected;
            document.getElementById('disconnect').disabled = !connected;
            document.getElementById('conversationDiv').style.visibility = connected ? 'visible' : 'hidden';
            $('#response').html();
        }

        function connect() {
            var socket = new SockJS('/endpointWisely'); //1连接SockJS的endpoint是“endpointWisely”,与后台代码中注册的endpoint要一样。
            stompClient = Stomp.over(socket); //2创建STOMP协议的webSocket客户端。
            let headers = {
                withCredentials: false
            };
            stompClient.connect(headers, function(frame) { //3连接webSocket的服务端。
                setConnected(true);
                console.log('开始进行连接Connected: ' + frame);
                //4通过stompClient.subscribe()订阅服务器的目标是'/topic/getResponse'发送过来的地址,与@SendTo中的地址对应。
                stompClient.subscribe('/topic/getResponse', function(respnose) {
                    showResponse(JSON.parse(respnose.body).responseMessage);
                });
                //4通过stompClient.subscribe()订阅服务器的目标是'/user/' + userId + '/msg'接收一对一的推送消息,其中userId由服务端传递过来,用于表示唯一的用户,通过此值将消息精确推送给一个用户
                //stompClient.subscribe('/user/' + userId + '/msg', function(respnose) {
                //    console.log(respnose);
                //    showResponse1(JSON.parse(respnose.body).responseMessage);
                //});
            });
        }


        function disconnect() {
            if (stompClient != null) {
                stompClient.disconnect();
            }
            setConnected(false);
            console.log("Disconnected");
        }

        function sendName() {
            var name = $('#name').val();
            //通过stompClient.send()向地址为"/welcome"的服务器地址发起请求,与@MessageMapping里的地址对应。因为我们配置了registry.setApplicationDestinationPrefixes(Constant.WEBSOCKETPATHPERFIX);所以需要增加前缀/ws-push/
            stompClient.send("/ws-push/logcur", {}, JSON.stringify({
                'name': name
            }));
        }

        function showResponse(message) {
            var response = $("#response");
            response.html(message);
        }

        function showResponse1(message) {
            var response = $("#response1");
            response.html(message);
        }
    </script>
</body>

</html>

测试

在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
### 回答1: Spring Boot 2.0 是一套快速开发框架,其中包含了 WebSocket 模块,能够轻松地集成 WebSocket,实现服务端主动向前端推送数据。 首先,在pom.xml文件中引入Spring Boot的Starter Websocket依赖: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency> 然后,在Spring Boot的启动类上使用@EnableWebSocket注解开启 WebSocket: @SpringBootApplication @EnableWebSocket public class MyApp { public static void main(String[] args) { SpringApplication.run(MyApp.class, args); } } 接着,编写一个 WebSocketEndpoint 类用于处理 WebSocket 连接和消息的收发: @Component public class WebSocketEndpoint implements WebSocketHandler { private static final List<WebSocketSession> SESSIONS = new CopyOnWriteArrayList<>(); @Override public void afterConnectionEstablished(WebSocketSession session) throws Exception { SESSIONS.add(session); } @Override public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception { // 接收到消息 } @Override public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception { SESSIONS.remove(session); } @Override public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception { SESSIONS.remove(session); } @Override public boolean supportsPartialMessages() { return false; } // 服务器向前端推送消息 public static void sendMessage(String message) throws IOException { for (WebSocketSession session : SESSIONS) { if (session.isOpen()) { session.sendMessage(new TextMessage(message)); } } } } 最后,当服务端需要向前端推送数据时,可以调用 WebSocketEndpoint 中的 sendMessage 方法: WebSocketEndpoint.sendMessage("Hello, websocket!"); 前端则需要开启 WebSocket 连接,并在 onmessage 方法中接收服务端推送的数据: var socket = new WebSocket("ws://localhost:8080/websocket"); socket.onmessage = function(event) { var data = event.data; // 处理服务端推送的数据 }; 总之,Spring Boot 2.0 整合 WebSocket 实现服务端主动向前端推送数据非常简单,只需要几行代码即可实现。 ### 回答2: Spring Boot 2.0 提供了与 WebSocket 相关的依赖和注解,可以方便地实现与前端的实时通信。下面介绍如何使用 Spring Boot 2.0 整合 WebSocket 实现服务器主动推送数据到前端。 首先,在 pom.xml 文件中添加以下依赖: ``` <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency> ``` 然后,创建一个 WebSocket 配置类,使用 `@EnableWebSocket` 注解启用 WebSocket: ``` @Configuration @EnableWebSocket public class WebSocketConfig implements WebSocketConfigurer { @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { registry.addHandler(myWebSocketHandler(), "/websocket").setAllowedOrigins("*"); } @Bean public WebSocketHandler myWebSocketHandler() { return new MyWebSocketHandler(); } } ``` 其中 `MyWebSocketHandler` 是自己实现的 WebSocket 消息处理类,可以在其中实现处理客户端发送过来的消息以及向客户端发送消息的逻辑。 下面是 `MyWebSocketHandler` 的一个示例: ``` public class MyWebSocketHandler extends TextWebSocketHandler { private Set<WebSocketSession> sessions = new CopyOnWriteArraySet<>(); @Override public void afterConnectionEstablished(WebSocketSession session) { sessions.add(session); } @Override public void afterConnectionClosed(WebSocketSession session, CloseStatus status) { sessions.remove(session); } @Override protected void handleTextMessage(WebSocketSession session, TextMessage message) { // 处理客户端发送过来的消息 } public void pushMessage(String message) { for (WebSocketSession session : sessions) { try { session.sendMessage(new TextMessage(message)); } catch (IOException e) { // 发送消息失败 } } } } ``` 在 `pushMessage` 方法中,可以遍历所有连接的客户端会话,向它们发送消息。 最后,在需要推送数据的地方,注入 `MyWebSocketHandler`,调用 `pushMessage` 方法即可: ``` @Autowired private MyWebSocketHandler webSocketHandler; public void sendData() { // 处理数据 webSocketHandler.pushMessage(data); } ``` 至此,我们就成功地在 Spring Boot 2.0 中整合了 WebSocket,并实现了服务器主动向前端推送数据的功能。 ### 回答3: 随着现代web应用的流行,实时数据交换变得越来越重要,而websocket作为实时双向通信的技术,成为了重要的实时数据传输协议。Spring Boot2.0整合websocket可以让我们通过服务器主动向前端推送数据,实现实时数据交换,满足现代web应用的高实时性需求。 WebSocket是一种基于HTTP协议的双向通信协议,在通信过程中,浏览器和服务器相互发送数据,实现实时数据交互。Spring Boot2.0已经内置了对WebSocket协议的支持,通过使用Spring WebSocket API可以很容易地配置WebSocket端点和处理程序。 服务器端可通过定义一个WebSocketConfig的配置类,配置WebSocket的Endpoint和Handler,并注册到拦截器链中,如下所示: @Configuration @EnableWebSocket public class WebSocketConfig implements WebSocketConfigurer { @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { registry.addHandler(webSocketHandler(), "/ws").addInterceptors(new HttpSessionHandshakeInterceptor()); } @Bean public WebSocketHandler webSocketHandler() { return new MyWebSocketHandler(); } } 在MyWebSocketHandler中,通过实现WebSocketHandler接口的handleMessage方法,可以处理客户端发送来的消息。如下所示: public class MyWebSocketHandler implements WebSocketHandler { @Override public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception { //处理客户端发送来的消息 } } 服务器端推送消息到前端,可以通过WebSocketSession的sendMessage方法实现,如下所示: session.sendMessage(new TextMessage("Hello,World!")); 客户端需要使用WebSocket API接收服务器推送来的数据,并处理数据,如下所示: var socket = new WebSocket("ws://localhost:8080/ws"); socket.onmessage = function(event) { //处理服务器推送过来的数据 }; 综上所述,Spring Boot2.0整合websocket可以通过配置WebSocket的Endpoint和Handler,在服务器端主动向前端推送数据,实现实时数据交换。对于现代web应用的高实时性需求,该技术具有重要意义。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

NewTech精选

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值