websocker无法注入依赖

在公司中准备用websocker统计在线人数,在WebSocketServer使用StringRedisTemplate保存数据到redis中去,但是在保存的时候显示

StringRedisTemplate变量为null

详细问题

java 复制代码
2023-08-20 10:37:14.109 ERROR 28240 --- [nio-7125-exec-1] o.a.t.websocket.pojo.PojoEndpointBase    : Failed to call onClose method of POJO end point for POJO of type [com.example.pipayshopapi.component.WebSocketServer]

java.lang.reflect.InvocationTargetException: null
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_382]
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_382]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_382]
	at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_382]
	at org.apache.tomcat.websocket.pojo.PojoEndpointBase.onClose(PojoEndpointBase.java:103) [tomcat-embed-websocket-9.0.41.jar:9.0.41]
	at org.apache.tomcat.websocket.WsSession.fireEndpointOnClose(WsSession.java:556) [tomcat-embed-websocket-9.0.41.jar:9.0.41]
	at org.apache.tomcat.websocket.WsSession.doClose(WsSession.java:502) [tomcat-embed-websocket-9.0.41.jar:9.0.41]
	at org.apache.tomcat.websocket.WsSession.doClose(WsSession.java:460) [tomcat-embed-websocket-9.0.41.jar:9.0.41]
	at org.apache.tomcat.websocket.WsSession.close(WsSession.java:447) [tomcat-embed-websocket-9.0.41.jar:9.0.41]
	at org.apache.tomcat.websocket.WsSession.close(WsSession.java:441) [tomcat-embed-websocket-9.0.41.jar:9.0.41]
	at org.apache.tomcat.websocket.pojo.PojoEndpointBase.handleOnOpenOrCloseError(PojoEndpointBase.java:92) [tomcat-embed-websocket-9.0.41.jar:9.0.41]
	at org.apache.tomcat.websocket.pojo.PojoEndpointBase.doOnOpen(PojoEndpointBase.java:77) [tomcat-embed-websocket-9.0.41.jar:9.0.41]
	at org.apache.tomcat.websocket.pojo.PojoEndpointServer.onOpen(PojoEndpointServer.java:64) [tomcat-embed-websocket-9.0.41.jar:9.0.41]
	at org.apache.tomcat.websocket.server.WsHttpUpgradeHandler.init(WsHttpUpgradeHandler.java:135) [tomcat-embed-websocket-9.0.41.jar:9.0.41]
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:935) [tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1597) [tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-9.0.41.jar:9.0.41]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_382]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_382]
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-9.0.41.jar:9.0.41]
	at java.lang.Thread.run(Thread.java:750) [na:1.8.0_382]
Caused by: java.lang.NullPointerException: null
	at com.example.pipayshopapi.component.WebSocketServer.onClose(WebSocketServer.java:70) ~[classes/:na]
	... 21 common frames omitted

2023-08-20 10:37:14.109 ERROR 28240 --- [nio-7125-exec-1] c.e.p.component.WebSocketServer          : 发生错误
java.lang.NullPointerException
	at com.example.pipayshopapi.component.WebSocketServer.onOpen(WebSocketServer.java:56)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.apache.tomcat.websocket.pojo.PojoEndpointBase.doOnOpen(PojoEndpointBase.java:65)
	at org.apache.tomcat.websocket.pojo.PojoEndpointServer.onOpen(PojoEndpointServer.java:64)
	at org.apache.tomcat.websocket.server.WsHttpUpgradeHandler.init(WsHttpUpgradeHandler.java:135)
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:935)
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1597)
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
	at java.lang.Thread.run(Thread.java:750)
java.lang.reflect.InvocationTargetException
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.apache.tomcat.websocket.pojo.PojoEndpointBase.onClose(PojoEndpointBase.java:103)
	at org.apache.tomcat.websocket.WsSession.fireEndpointOnClose(WsSession.java:556)
	at org.apache.tomcat.websocket.WsSession.doClose(WsSession.java:502)
	at org.apache.tomcat.websocket.WsSession.doClose(WsSession.java:460)
	at org.apache.tomcat.websocket.WsSession.close(WsSession.java:447)
	at org.apache.tomcat.websocket.WsSession.close(WsSession.java:441)
	at org.apache.tomcat.websocket.pojo.PojoEndpointBase.handleOnOpenOrCloseError(PojoEndpointBase.java:92)
	at org.apache.tomcat.websocket.pojo.PojoEndpointBase.doOnOpen(PojoEndpointBase.java:77)
	at org.apache.tomcat.websocket.pojo.PojoEndpointServer.onOpen(PojoEndpointServer.java:64)
	at org.apache.tomcat.websocket.server.WsHttpUpgradeHandler.init(WsHttpUpgradeHandler.java:135)
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:935)
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1597)
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
	at java.lang.Thread.run(Thread.java:750)
Caused by: java.lang.NullPointerException
	at com.example.pipayshopapi.component.WebSocketServer.onClose(WebSocketServer.java:70)
	... 21 more

最后在网上搜索之后得出答案:

因为spring对象的创建都是以单例模式创建的,但是每一个用户连接websocker,都会创建一次webscket对象,所以当你启动项目时,你想要注入的对象已经注入进去,但是当用户连接是,新创建的websocket对象没有你要注入的对象,所以会报NullPointerException。

总结:spring管理的都是单例(singleton),和 websocket (多对象)相冲突.

解决方法:

在WebSocketServer中,使用set方法传入上下文

java 复制代码
 private static StringRedisTemplate stringRedisTemplate;

    @Autowired
    public void setChatService(StringRedisTemplate stringRedisTemplate) {
        WebSocketServer.stringRedisTemplate = stringRedisTemplate;
    }

完整代码

java 复制代码
import com.example.pipayshopapi.service.UserInfoService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;


/**
 * @author websocket服务
 */

@Component
@ServerEndpoint(value = "/dailyActive/{userId}")
public class WebSocketServer {

    private static final Logger log = LoggerFactory.getLogger(WebSocketServer.class);
    // 注入查看聊天列表的服务

    /**
     * 记录当前在线连接数
     */
    public static final Map<String, Session> dailyActiveCount = new ConcurrentHashMap<>();


    public static final String dailyActiveName="dailyActiveName";

    private RedisHandler redisHandler=RedisHandler.getInstance();

    private static StringRedisTemplate stringRedisTemplate;

    @Autowired
    public void setChatService(StringRedisTemplate stringRedisTemplate) {
        WebSocketServer.stringRedisTemplate = stringRedisTemplate;
    }

    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("userId") String userId) {
        log.error(userId+"----------------------------------------------进入");
        // 保存当前用户session
        dailyActiveCount.put(userId, session);
        // 存入redis中去
//        redisHandler.savedailyActive(dailyActiveName,dailyActiveCount.size());
        stringRedisTemplate.opsForValue().set(dailyActiveName,String.valueOf(dailyActiveCount.size()));
    }


    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose(Session session, @PathParam("userId") String userId) {
        log.error(userId+"----------------------------------------------关闭");
        // 移除当前用户session
        dailyActiveCount.remove(userId);
        // 存入redis中去
//        redisHandler.savedailyActive(dailyActiveName,dailyActiveCount.size());
        stringRedisTemplate.opsForValue().set(dailyActiveName,String.valueOf(dailyActiveCount.size()));
    }


    /**
     * 收到客户端消息后调用的方法
     * 后台收到客户端发送过来的消息
     * onMessage 是一个消息的中转站
     * 接受 浏览器端 socket.send 发送过来的 json数据
     */
    @OnMessage
    public void onMessage(Session session, String message,@PathParam("userId") String userId) {



    }

    @OnError
    public void onError(Session session, Throwable error) {
        log.error("发生错误");
        error.printStackTrace();
    }


 

 
 
}
相关推荐
苹果醋31 小时前
React源码02 - 基础知识 React API 一览
java·运维·spring boot·mysql·nginx
Hello.Reader1 小时前
深入解析 Apache APISIX
java·apache
菠萝蚊鸭2 小时前
Dhatim FastExcel 读写 Excel 文件
java·excel·fastexcel
旭东怪2 小时前
EasyPoi 使用$fe:模板语法生成Word动态行
java·前端·word
007php0072 小时前
Go语言zero项目部署后启动失败问题分析与解决
java·服务器·网络·python·golang·php·ai编程
∝请叫*我简单先生2 小时前
java如何使用poi-tl在word模板里渲染多张图片
java·后端·poi-tl
ssr——ssss2 小时前
SSM-期末项目 - 基于SSM的宠物信息管理系统
java·ssm
一棵星2 小时前
Java模拟Mqtt客户端连接Mqtt Broker
java·开发语言
鲤籽鲲3 小时前
C# Random 随机数 全面解析
android·java·c#
荆州克莱3 小时前
mysql中局部变量_MySQL中变量的总结
spring boot·spring·spring cloud·css3·技术