亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

解決@ServerEndpoint不能注入@Autowired的問(wèn)題

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

都會(huì)報(bào)空指針錯(cuò)誤的原因

本質(zhì)原因

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

?因?yàn)閃ebSocket 是一個(gè)多例,因?yàn)槟阈枰鄠€(gè)對(duì)象來(lái)保存鏈接,所以就和單例無(wú)緣了,然而我們交給Spring管理的是單例的東西,那么我們可以從這里知道,WebSocket的對(duì)象是不能交給Spring管理的

此時(shí)我們有兩種解決方案;

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

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應(yīng)用上下文環(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是用來(lái)表示唯一客戶(hù)端,如果需要指定發(fā)送,需要指定發(fā)送通過(guò)name來(lái)區(qū)分
        webSocketSet.put(name, this);
        log.info("[WebSocket] 連接成功,當(dāng)前連接人數(shù)為:={}", webSocketSet.size());
        //接收用戶(hù)傳入的參數(shù),并且進(jìn)行判斷登錄是否成功 如果登錄成功那    personService.savePersonSql(name,password);么 就保存Sesion 并且  鏈接成功 否職反之

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

使用上面的工具類(lèi)就,可以從上下文獲取到你需要的實(shí)例對(duì)象

方案2: 既然不給那我就自己搞一個(gè)注入進(jìn)去

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

心得

? 這里L(fēng)ink的多對(duì)象機(jī)制和Spring 的controller注解截止可以同時(shí)進(jìn)行,互相沒(méi)有矛盾。

Spring在初始的時(shí)候,創(chuàng)建一個(gè)Link的對(duì)象,該對(duì)象在運(yùn)行期間不會(huì)被使用,同時(shí)注入的類(lèi)進(jìn)行了靜態(tài)的完善,這是Spring在這套代碼里面的唯一作用,當(dāng)有用戶(hù)聊天的時(shí)候,java會(huì)根據(jù)Link類(lèi)創(chuàng)建對(duì)象,每個(gè)對(duì)象保持對(duì)應(yīng)的用戶(hù)鏈接,因?yàn)殪o態(tài)類(lèi)已經(jīng)在啟動(dòng)的時(shí)候被Spring初始化了,所以此時(shí)每個(gè)對(duì)象都可以被正常訪問(wèn)

注意:

@Component 這個(gè)注解需要有,不然就不能被加載到Spring 就不能在啟動(dòng)服務(wù)器的時(shí)候進(jìn)行正常的鏈接

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

    /**
     * 與某個(gè)客戶(hù)端的連接對(duì)話,需要通過(guò)它來(lái)給客戶(hù)端發(fā)送消息
     */
    private Session session;

    /**
     * 標(biāo)識(shí)當(dāng)前連接客戶(hù)端的用戶(hù)名
     */
    private String name;

    /**
     * 用于存所有的連接服務(wù)的客戶(hù)端,這個(gè)對(duì)象存儲(chǔ)是安全的
     */
    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是用來(lái)表示唯一客戶(hù)端,如果需要指定發(fā)送,需要指定發(fā)送通過(guò)name來(lái)區(qū)分
        webSocketSet.put(name, this);
        log.info("[WebSocket] 連接成功,當(dāng)前連接人數(shù)為:={}", webSocketSet.size());
        //接收用戶(hù)傳入的參數(shù),并且進(jìn)行判斷登錄是否成功 如果登錄成功那    personService.savePersonSql(name,password);么 就保存Sesion 并且  鏈接成功 否職反之

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

    @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;
    }

}

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • java volatile案例講解

    java volatile案例講解

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

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

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