servlets JSR-356 @ServerEndpoint के @OnMessage में ServletContext और HttpSession तक पहुंच




java-ee websocket (3)

स्प्रिंग ApplicationContext @ServerEndpoint और बीन के लिए लुकअप खोजने के लिए @ServerEndpoint को @ServerEndpoint अंदर से प्राप्त करने की आवश्यकता है।

फिलहाल मेरा सबसे अच्छा तरीका जेएनडीआई नामकरण संदर्भ में उस बीन को बांधना है और इसे Endpoint में Endpoint । कोई बेहतर समाधान स्वागत है।

मैं वेबलेट के Session साथ सर्वलेट के HttpSession को सिंक करने का एक उचित तरीका भी ढूंढ रहा हूं।


मैंने टॉमकैट (संस्करण 7.0.56 और 8.0.14) पर बलुस के जवाब की कोशिश की। दोनों कंटेनरों पर, संशोधित हैंडशेक के अनुरोध पैरामीटर में एक HttpSession (और इस प्रकार कोई servletContext) नहीं है। चूंकि मुझे केवल "वैश्विक" चर (वेब-एप्लिकेशन ग्लोबल, यानी) तक पहुंचने के लिए सर्वलेट संदर्भ की आवश्यकता है, इसलिए मैंने इन चरों को धारक वर्ग के सामान्य स्थिर क्षेत्र में संग्रहीत किया है। यह सुरुचिपूर्ण है, लेकिन यह काम किया।

इस विशिष्ट टोमकैट संस्करणों में एक बग की तरह ओक - क्या किसी ने भी इसे देखा है?


सर्वलेट HttpSession जेएसआर -356 में HandshakeRequest#getHttpSession() द्वारा उपलब्ध है जो बदले में उपलब्ध है जब एक हैंडशेक अनुरोध @OnOpen के @OnOpen से पहले किया @OnOpen है। HttpSession#getServletContext() बदले में बस HttpSession#getServletContext() माध्यम से उपलब्ध है। यह एक पत्थर के साथ दो पक्षियों है।

हैंडशेक अनुरोध को कैप्चर करने के लिए, एक ServerEndpointConfig.Configurator लागू करें और modifyHandshake() विधि को ओवरराइड करें। HandshakeRequest विधि विधि के रूप में उपलब्ध है। आप HttpSession को EndpointConfig#getUserProperties() में डाल सकते हैं। EndpointConfig बदले में विधि तर्क @OnOpen रूप में उपलब्ध है।

ServerEndpointConfig.Configurator कार्यान्वयन का एक किकऑफ उदाहरण यहां दिया गया है:

public class ServletAwareConfig extends ServerEndpointConfig.Configurator {

    @Override
    public void modifyHandshake(ServerEndpointConfig config, HandshakeRequest request, HandshakeResponse response) {
        HttpSession httpSession = (HttpSession) request.getHttpSession();
        config.getUserProperties().put("httpSession", httpSession);
    }

}

यहां बताया गया है कि आप इसका उपयोग कैसे कर सकते हैं, @ServerEndpoint की configurator विशेषता को नोट करें:

@ServerEndpoint(value="/your_socket", configurator=ServletAwareConfig.class)
public class YourSocket {

    private EndpointConfig config;

    @OnOpen
    public void onOpen(Session websocketSession, EndpointConfig config) {
        this.config = config;
    }

    @OnMessage
    public void onMessage(String message) {
        HttpSession httpSession = (HttpSession) config.getUserProperties().get("httpSession");
        ServletContext servletContext = httpSession.getServletContext();
        // ...
    }

}

डिज़ाइन संकेत के रूप में, अपने @ServerEndpoint पूरी तरह से सर्वलेट API निर्भरताओं से मुक्त रखना सबसे अच्छा है। आप modifyHandshake() कार्यान्वयन में तुरंत उस जानकारी को तुरंत निकालें (आमतौर पर एक उत्परिवर्तनीय जवाबीन) जिसे आपको सर्वलेट सत्र या संदर्भ से चाहिए और उन्हें इसके बजाय उपयोगकर्ता गुण मानचित्र में डाल दें। यदि आप ऐसा नहीं करते हैं, तो आपको ध्यान रखना चाहिए कि एक वेबसाईट सत्र HTTP सत्र से अधिक समय तक जीवित रह सकता है। तो जब आप अभी भी HttpSession में HttpSession आसपास ले जाते हैं, तो आप समाप्त होने के दौरान इसे एक्सेस करने का प्रयास करते समय IllegalStateException में भाग सकते हैं।

यदि आपके पास हाथों में सीडीआई (और शायद जेएसएफ) होता है, तो आप OmniFaces के स्रोत कोड से प्रेरणा प्राप्त कर सकते हैं <o:socket> (लिंक शोकेस के बहुत नीचे हैं)।

यह भी देखें:


बलुस के उत्तर के लिए अद्यतन कोड, ऑन ओपन विधि को @ ओन ओपन के साथ सजाया जाना चाहिए। फिर एंडपॉइंट क्लास को बढ़ाने के लिए अब और आवश्यकता नहीं है:

@ServerEndpoint(value="/your_socket", configurator=ServletAwareConfig.class)
public class YourSocket {

    private EndpointConfig config;

    @OnOpen
    public void onOpen(Session websocketSession, EndpointConfig config) {
        this.config = config;
    }

    @OnMessage
    public void onMessage(String message) {
        HttpSession httpSession = (HttpSession) config.getUserProperties().get("httpSession");
        ServletContext servletContext = httpSession.getServletContext();
        // ...
    }

}






java-websocket