websocket之参数传递和依赖注入

WebSocket协议提供全双工通信,适用于聊天系统和远程日志查看。在使用WebSocket时,面临参数传递和依赖注入的问题。解决方案在于理解OnOpen注解的源码,找到合适的注入方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

背景

 

      WebSocket协议是一种基于TCP的新协议。不同于http仅能实现单向通信,它实现了浏览器与服务器的全双工通信,因此可以被应用在bs架构的聊天系统、远程日志查看等系统中。websocket在建立连线时仅需要进行一次“握手”就能建立“长连接”,也就是浏览器发出websocket连线请求,然后服务器发出回应即可。目前chrome、firefox和IE10+等主流浏览器都支持Websocket. 

 问题

         由于项目需要,最近在做一个如下的自主上线系统。为了便于尽早发现上线过程中的问题,该系统中有一个在web页面上实时显示服务日志的功能,我在通过websocket实现这个功能的过程中遇到了2个问题:websocket建立连接时需要传递参数(例如服务器ip,项目名称,日志文件位置等)进去;需要注入service 层的类,以便在onOpen()方法中进行数据查询和业务处理。百度谷歌一顿搜索后,发现这两个问题还挺有共性的,很多人都在问,但是靠谱的答案却比较少见。通过查看源码和各种折腾,最后还是解决了这些问题,做个总结。
 
      
 

解决方案

先上解决方案:
        @ServerEndpoint("/websocket/{moduleName}/{serverIp}")
	public class LogSocket {
	// 与某个客户端的连接会话,需要通过它来给客户端发送数据
	private Session session;
	private Process process;
	private InputStream inputStream;
	private static Logger logger = Logger.getLogger(LogSocket.class);
	private final int DEFAULT_SSH_PORT = 22;
	//websocket中不能使用注解进行依赖注入
	//Resource
	//private OnlineService onlineService;
	private OnlineService onlineService = (OnlineService) ContextLoader.getCurrentWebApplicationContext().getBean("onlineService");

	/**
	 * 连接建立成功调用的方法
	 * 
	 * @param session
	 *            可选的参数。session为与某个客户端的连接会话,需要通过它来给客户端发送数据
	 */
	@OnOpen
	public void onOpen(@PathParam("moduleName") String moduleName,
			@PathParam("serverIp") String serverIp, Session session) {
		this.session = session;
		webSocketSet.add(this); // 加入set中
		logger.info("日志开始");
		logger.info("websocket:" + moduleName);
		System.out.println("websocket:" + moduleName);

		String command = "tail -100f " + onlineService.getLogpathByModuleName(
				moduleName.trim(), serverIp.trim());  @ServerEndpoint("/websocket/{moduleName}/{serverIp}")
	public class LogSocket {
	// 与某个客户端的连接会话,需要通过它来给客户端发送数据
	private Session session;
	private Process process;
	private InputStream inputStream;
	private static Logger logger = Logger.getLogger(LogSocket.class);
	private final int DEFAULT_SSH_PORT = 22;
	//websocket中不能使用注解进行依赖注入
	//Resource
	//private OnlineService onlineService;
	private OnlineService onlineService = (OnlineService) ContextLoader.getCurrentWebApplicationContext().getBean("onlineService");

	/**
	 * 连接建立成功调用的方法
	 * 
	 * @param session
	 *            可选的参数。session为与某个客户端的连接会话,需要通过它来给客户端发送数据
	 */
	@OnOpen
	public void onOpen(@PathParam("moduleName") String moduleName,
			@PathParam("serverIp") String serverIp, Session session) {
		this.session = session;
		webSocketSet.add(this); // 加入set中
		logger.info("日志开始");
		logger.info("websocket:" + moduleName);
		System.out.println("websocket:" + moduleName);

		String command = "tail -100f " + onlineService.getLogpathByModuleName(
				moduleName.trim(), serverIp.trim());

 

参数传递

其实这个问题不难,主要是websocket的应用比较少,自己平时也少有看源码的习惯。先来看看websocket的OnOpen注解的源码,突破点已用粗体标出了。

 

package javax.websocket;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * This method level annotation can be used to decorate a Java method that wishes to be called when a new
 * web socket session is open.
 *
 * <p>The method may only take the following parameters:-
 * <ul>
 * <li>optional {@link Session} parameter</li>
 * <li>optional {@link EndpointConfig} parameter</li>
 * <li>Zero to n String parameters annotated with the {@link javax.websocket.server.PathParam} annotation.</li>
 * </ul>
 *
 * <p>The parameters may appear in any order.
 *
 * @author dannycoward
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface OnOpen {

}Zero to n String parameters annotated with the {@link javax.websocket.server.PathParam} annotation.</li>
 * </ul>
 *
 * <p>The parameters may appear in any order.
 *
 * @author dannycoward
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface OnOpen {

}

 

 

使用@ServerEndpoint注解将参数拼接在建立连接的url上(@ServerEndpoint("/websocket/{moduleName}/{serverIp}")),使用@PathParam 注解进行参数获取( onOpen(@PathParam("moduleName") String moduleName,@PathParam("serverIp") String serverIp, Session session))。
 

 

依赖注入

起初是通过注解的方式注入的依赖,运行时报空指针,没有注入进去。一番折腾之后,发现虽然使用注解无法注入,但是使用显示的方式加载bean(ContextLoader.getCurrentWebApplicationContext().getBean)还是可以的。显示加载时,同时需要在spring的配置文件中显示地配置ben: <bean id="onlineService" class="com.wangyin.ebl.service.impl.OnlineServiceImpl"></bean>  。问题总算是解决了,但是还是没搞明白原因,等过段时间有空了再慢慢思考吧。

 

 

 

### 如何在 Vue2 中通过 WebSocket 传递参数 为了实现基于 WebSocket 的通信并传递参数,在 Vue2 应用程序中通常会使用 MQTT 或原生 WebSocket API 来建立连接。下面介绍一种利用 `mqtt` 客户端库的方式来完成这一目标。 #### 使用 Mqtt 进行消息发送与接收 首先,确保已经在项目里安装了必要的依赖项,并按照如下方式配置: ```javascript // main.js 配置文件片段 import Vue from 'vue' import App from './App.vue' import '@/assets/styles/index.css' // 全局样式表 import mqtt from 'mqtt' Vue.prototype.$mqtt = mqtt // 将 mqtt 注入到 Vue 实例上以便全局访问 ``` 当需要向服务器发送带有特定参数的消息时,可以在组件内部定义相应的方法来进行操作: ```javascript export default { name: 'MyComponent', methods: { sendMessageWithParams(topic, params) { const client = this.$mqtt.connect('wss://broker.hivemq.com:8080/mqtt') // 建立安全 Websocket 连接 client.on('connect', () => { console.log('Connected') let messageContent = JSON.stringify(params); // 参数序列化 client.publish(topic, messageContent, { qos: 1 }, (err) => { if (!err){ console.log(`Message published successfully on topic ${topic}`) } else{ console.error(err); } client.end(); // 发送完成后断开连接 }); }); client.on('error', function(error){ console.error("Connection error: ", error); client.end(); }) client.on('close', ()=>{ console.log('Disconnected'); }) }, receiveMessages(){ const client = this.$mqtt.connect('wss://broker.hivemq.com:8080/mqtt') client.subscribe('/my/topic/response', (err) => { if(!err){ console.log('Subscribed to /my/topic/response') } }) client.on('message', (receivedTopic, message)=>{ try { let parsedData = JSON.parse(message.toString()); console.log(parsedData); // 处理收到的数据... } catch(e){ console.warn('Failed parsing incoming data:', e.message) } client.unsubscribe(receivedTopic) setTimeout(() => { client.end() }, 5000) }) } } } ``` 上述代码展示了如何创建一个简单的发布/订阅模式下的客户端实例[^3]。这里的关键在于将要传输的信息作为字符串形式传给 `publish()` 方法中的第二个参数;而在另一侧,则可以通过监听 `message` 事件获取这些数据,并对其进行解析处理。 对于更复杂的场景,建议考虑采用 Vuex 存储状态管理工具配合使用,这样可以更好地管理共享应用内的各种资源逻辑[^1]。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

拥春飞翔

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

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

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

打赏作者

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

抵扣说明:

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

余额充值