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();
    }


 

 
 
}
相关推荐
Seven971 分钟前
Tomcat的架构设计和启动过程详解
java
Mr-Wanter2 分钟前
踩坑记录:IDEA 启动服务连续三次 OOM 内存溢出完整解决
java·ide·intellij-idea·oom
阿巴斯甜6 分钟前
User::getName含义?
java
2601_9498180913 分钟前
SpringBoot项目集成ONLYOFFICE
java·spring boot·后端
阿巴斯甜18 分钟前
int sum = list.stream().reduce(0, Integer::sum); 含义?
java
阿巴斯甜19 分钟前
Stream 的使用:
java
Foreer黑爷22 分钟前
Java并发工具箱:CountDownLatch与CyclicBarrier使用指南
java·开发语言·jvm
亦暖筑序29 分钟前
Spring AI Alibaba + RAG 实战:知识库检索模块从设计到落地
java·开源
MeAT ITEM35 分钟前
ShardingSphere-jdbc 5.5.0 + spring boot 基础配置 - 实战篇
java·spring boot·后端
ekuoleung37 分钟前
Spring Boot 3.4 + Java 21 在量化平台中的架构实践
java·架构