欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

解決@ServerEndpoint不能注入@Autowired的問題

 更新時間:2024年05月21日 09:44:04   作者:于小袁  
這篇文章主要介紹了解決@ServerEndpoint不能注入@Autowired的問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教

都會報空指針錯誤的原因

本質原因

spring管理的都是單例(singleton)和 websocket (多對象)相沖突。

?因為WebSocket 是一個多例,因為你需要多個對象來保存鏈接,所以就和單例無緣了,然而我們交給Spring管理的是單例的東西,那么我們可以從這里知道,WebSocket的對象是不能交給Spring管理的

此時我們有兩種解決方案;

方案1: 在上下文獲取你需要的對象

package cn.jiabao.util;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.stereotype.Repository;

@Repository
public class SpringUtils implements BeanFactoryPostProcessor {

    //Spring應用上下文環(huán)境
    private static ConfigurableListableBeanFactory beanFactory;

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        SpringUtils.beanFactory = beanFactory;
    }

    public static ConfigurableListableBeanFactory getBeanFactory() {
        return beanFactory;
    }

    @SuppressWarnings("unchecked")
    public static <T> T getBean(String name) throws BeansException {
        return (T) getBeanFactory().getBean(name);
    }

    public static <T> T
    getBean(Class<T> clz) throws BeansException {
        T result = (T) getBeanFactory().getBean(clz);
        return result;
    }
}

--------------------------------------------------------
 private StringRedisTemplate stringRedisTemplate = SpringUtils.getBean(StringRedisTemplate.class);

    @OnOpen
    public void OnOpen(Session session, @PathParam(value = "name") String name,@PathParam(value = "password") String password) {
        stringRedisTemplate.opsForValue().set("1","1");

        this.session = session;
        this.name = name;
        // name是用來表示唯一客戶端,如果需要指定發(fā)送,需要指定發(fā)送通過name來區(qū)分
        webSocketSet.put(name, this);
        log.info("[WebSocket] 連接成功,當前連接人數為:={}", webSocketSet.size());
        //接收用戶傳入的參數,并且進行判斷登錄是否成功 如果登錄成功那    personService.savePersonSql(name,password);么 就保存Sesion 并且  鏈接成功 否職反之

         //    personService.savePersonSql(name,"1"); //多例之后 可以執(zhí)行reids代碼等等
        // 注意: 不能在這里面直接用Reids 即使多例 直接保存也有問題
    }

使用上面的工具類就,可以從上下文獲取到你需要的實例對象

方案2: 既然不給那我就自己搞一個注入進去

private static StringRedisTemplate stringRedisTemplate;
@Autowired
private void setStringRedisTemplate(StringRedisTemplate stringRedisTemplate){
    Link.stringRedisTemplate =stringRedisTemplate;
}

心得

? 這里Link的多對象機制和Spring 的controller注解截止可以同時進行,互相沒有矛盾。

Spring在初始的時候,創(chuàng)建一個Link的對象,該對象在運行期間不會被使用,同時注入的類進行了靜態(tài)的完善,這是Spring在這套代碼里面的唯一作用,當有用戶聊天的時候,java會根據Link類創(chuàng)建對象,每個對象保持對應的用戶鏈接,因為靜態(tài)類已經在啟動的時候被Spring初始化了,所以此時每個對象都可以被正常訪問

注意:

@Component 這個注解需要有,不然就不能被加載到Spring 就不能在啟動服務器的時候進行正常的鏈接

package cn.jiabao.link;
import cn.jiabao.util.SpringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
@ServerEndpoint("/websocket/{name}/{password}")
@Component
@Controller
public class Link {

    private static StringRedisTemplate stringRedisTemplate;
    @Autowired
    private void setStringRedisTemplate(StringRedisTemplate stringRedisTemplate){
        Link.stringRedisTemplate =stringRedisTemplate;
    }

    /**
     * 與某個客戶端的連接對話,需要通過它來給客戶端發(fā)送消息
     */
    private Session session;

    /**
     * 標識當前連接客戶端的用戶名
     */
    private String name;

    /**
     * 用于存所有的連接服務的客戶端,這個對象存儲是安全的
     */
    private static ConcurrentHashMap<String, Link> webSocketSet = new ConcurrentHashMap<>();


 //    private StringRedisTemplate stringRedisTemplate = SpringUtils.getBean(StringRedisTemplate.class);

    @OnOpen
    public void OnOpen(Session session, @PathParam(value = "name") String name,@PathParam(value = "password") String password) {
        stringRedisTemplate.opsForValue().set("1","1");

        this.session = session;
        this.name = name;
        // name是用來表示唯一客戶端,如果需要指定發(fā)送,需要指定發(fā)送通過name來區(qū)分
        webSocketSet.put(name, this);
        log.info("[WebSocket] 連接成功,當前連接人數為:={}", webSocketSet.size());
        //接收用戶傳入的參數,并且進行判斷登錄是否成功 如果登錄成功那    personService.savePersonSql(name,password);么 就保存Sesion 并且  鏈接成功 否職反之

         //    personService.savePersonSql(name,"1"); //多例之后 可以執(zhí)行reids代碼等等
        // 注意: 不能在這里面直接用Reids 即使多例 直接保存也有問題
    }

    @OnMessage
    public void OnMessage(String message) {
        log.info("[WebSocket] 收到消息:{}", message);
        //判斷是否需要指定發(fā)送,具體規(guī)則自定義
        if (message.indexOf("TOUSER") == 0) {
            String name = message.substring(message.indexOf("TOUSER") + 6, message.indexOf(";"));
            AppointSending(name, message.substring(message.indexOf(";") + 1, message.length()));
        } else {
            GroupSending(message);
        }
    }


    /**
     * 群發(fā)
     *
     * @param message
     */
    public void GroupSending(String message) {
        for (String name : webSocketSet.keySet()) {
            try {
                webSocketSet.get(name).session.getBasicRemote().sendText(message);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }


    /**
     * 指定發(fā)送
     *
     * @param name
     * @param message
     */
    public void AppointSending(String name, String message) {
        try {
            webSocketSet.get(name).session.getBasicRemote().sendText(message);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static Link getPerson(String key) {
        return webSocketSet.get(key);
    }

    public static ConcurrentHashMap<String, cn.jiabao.link.Link> getMap() {
        return webSocketSet;
    }

}

總結

以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關文章

  • Java線程活鎖的實現與死鎖等的區(qū)別

    Java線程活鎖的實現與死鎖等的區(qū)別

    活鎖是一種遞歸情況,其中兩個或更多線程將繼續(xù)重復特定的代碼邏輯,本文主要介紹了Java線程活鎖的實現與死鎖等的區(qū)別,具有一定的參考價值,感興趣的可以了解一下
    2024-04-04
  • 整理Java編程中常用的基本描述符與運算符

    整理Java編程中常用的基本描述符與運算符

    這篇文章主要介紹了Java編程中常用的基本描述符與運算符整理,包括運算符優(yōu)先級等平時經常查看反復記憶的知識點,需要的朋友可以參考下
    2016-02-02
  • Java讀取json數據并存入數據庫的操作代碼

    Java讀取json數據并存入數據庫的操作代碼

    很多朋友問大佬們JAVA怎么把json存入數據庫啊,這一問題就把我難倒了,糾結如何操作呢,下面小編把我的經驗分享給大家,感興趣的朋友一起看看吧
    2021-08-08
  • SpringBoot調用DeepSeek接口的實現

    SpringBoot調用DeepSeek接口的實現

    本文主要介紹了SpringBoot調用DeepSeek接口的實現,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2025-02-02
  • 通過Java帶你了解網絡IO模型

    通過Java帶你了解網絡IO模型

    這篇文章將通過Java帶大家了解網絡IO模型,包括BIO,NoBlockingIO,NIO(NewIO),AIO等做了詳細得介紹,感興趣的小伙伴可以參考閱讀本文
    2023-05-05
  • 淺談JavaAPI 中 <E> 與 <T> 的含義

    淺談JavaAPI 中 <E> 與 <T> 的含義

    下面小編就為大家?guī)硪黄獪\談JavaAPI 中 <E> 與 <T> 的含義。小編覺得挺不錯的,現在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-10-10
  • SpringBoot動態(tài)定時功能實現方案詳解

    SpringBoot動態(tài)定時功能實現方案詳解

    在SpringBoot項目中簡單使用定時任務,不過由于要借助cron表達式且都提前定義好放在配置文件里,不能在項目運行中動態(tài)修改任務執(zhí)行時間,實在不太靈活。現在我們就來實現可以動態(tài)修改cron表達式的定時任務,感興趣的可以了解一下
    2022-11-11
  • Java面向對象之猜拳游戲

    Java面向對象之猜拳游戲

    這篇文章主要為大家詳細介紹了Java面向對象之猜拳游戲,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-05-05
  • java volatile案例講解

    java volatile案例講解

    這篇文章主要介紹了java volatile案例講解,本文通過講解內存可見性,Volatile變量來去詳細分析該項概念,需要的朋友可以參考下
    2021-07-07
  • 使用eclipse創(chuàng)建java項目的方法

    使用eclipse創(chuàng)建java項目的方法

    這篇文章主要為大家詳細介紹了使用eclipse創(chuàng)建java項目的方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-04-04

最新評論