java - Dispatcher-servlet websocket अनुरोधों में मैप नहीं कर सकता




xml spring (2)

मुझे एक गंदा समाधान मिला मुझे यह पसंद नहीं है, लेकिन उत्तर के अभाव के साथ-साथ वर्तमान और पूर्व सहयोगियों से भी, मुझे परियोजना के साथ आगे बढ़ना पड़ा और गंदे सुधार लागू करना था।

गंदे फिक्स नियंत्रक और अनुसूचित वर्गों (सभी dispatcher-servlet द्वारा स्कैन किया गया, जहां websocket tag घोषित किया गया है) में SimpMessagingTemplate और सेवा तरीकों ( root context में घोषित) के लिए एक पैरामीटर के रूप में SimpMessagingTemplate को पारित करने के लिए है।

यह समाधान पारदर्शी नहीं है ( SimpMessagingTemplate को आदर्श रूप से सेवा में सीधे SimpMessagingTemplate होना चाहिए) लेकिन यह निश्चित रूप से समस्या को हल करता है।

मैं मुख्य फ्रेमवर्क (स्प्रिंग कोर, स्प्रिंग एमवीसी, स्प्रिंग सिक्योरिटी, स्प्रिंग डेटा, स्प्रिंग वेबकॉकेट का इस्तेमाल किया जाता है) के रूप में स्प्रिंग के साथ जावा वेबएप विकसित कर रहा हूं।

एक स्प्रिंग संदर्भ में एक संदेश-दलाल घोषित करते हुए इस संदर्भ में एक SimpMessagingTemplate बीन प्रदान करता है:

<websocket:message-broker>
    <websocket:stomp-endpoint path="/stomp">
        <websocket:sockjs/>
    </websocket:stomp-endpoint>
    <websocket:simple-broker prefix="/topic,/queue"/>
</websocket:message-broker>

मुझे यह टैग मेरे मूल संदर्भ (applicationContext.xml) में डाल दिया है, अन्यथा रूट संदर्भ में घोषित सेवाओं को वेबकॉट्स द्वारा उपयोगकर्ताओं को सूचनाएं नहीं भेज सकती (क्योंकि उन्हें सिंपमसेजिंग टेम्पलेट की आवश्यकता है)।

बात यह है, अगर मैं मूल टैग में इस टैग को डालता हूं, तो क्लाइंट को वेबसाईट की सदस्यता लेने पर 404 प्राप्त होते हैं। और अगर मैं डिस्पैचर-सर्वलेट में टैग डालता हूं, तो रूट संदर्भ में सेवाएं सूचनाएं नहीं भेज सकते हैं क्योंकि उन्हें सिम्प मेसेजिंग टेम्पलेट की आवश्यकता होगी (लेकिन यह केवल बाल डिस्पैचर-सर्वलेट प्रसंग में उपलब्ध है)।

ब्रोकर को डिस्पैचर-सर्वलेट "बाँध" करने का कोई तरीका क्या है? बीन को दो बार घोषित करना सही समाधान नहीं है।

यह समस्या स्प्रिंग के समान है : सरल संदर्भ को SimpMessagingTemplate बीन को कैसे उजागर करें? लेकिन किसी दूसरे कोण की ओर देख रहे हैं (डिस्पेचर-सर्वलेट के बजाय रूट संदर्भ को खोलने के लिए websocket)


मैंने सर्वलेट अनुप्रयोग संदर्भ में प्रायोजित होने के बाद इंजेक्शन करने के लिए एक बीन लिखा है। SimpMessageTemplate इंजेक्ट करने के लिए यह माता-पिता आवेदन संदर्भों के माध्यम से खोज करेगा

जो भी बीम को टेम्पलेट की आवश्यकता है:

@Autowired(required=false) //required=false so that it won't throw Exception when startup
private SimpMessagingTemplate messagingTemplate;

PostInjectSimpMessageTemplateBean:

इस बीन को सर्वलेट एप्लिकेशन संदर्भ में रखें (यानी उसी एक्सएमएल फाइल जो वेबसाईट स्थित है)

( "YOUR.PACKAGE.NAME" को बदलें )

public class PostInjectSimpMessageTemplateBean implements ApplicationListener<ContextRefreshedEvent> {

@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
    ApplicationContext servletContext = event.getApplicationContext();
    ApplicationContext context = servletContext.getParent();

    SimpMessagingTemplate template = servletContext.getBean(SimpMessagingTemplate.class);

    while(context != null){
        for(String beanName : context.getBeanDefinitionNames()){
            Object bean = context.getBean(beanName);
            Class<?> clazz = bean.getClass();
            if(!clazz.getName().startsWith("YOUR.PACKAGE.NAME")) continue;

            List<FieldWithAnnotation<Autowired>> fields = ReflectionUtils.findFieldsWithAnnotation(clazz, Autowired.class);
            for (FieldWithAnnotation<Autowired> fieldWithAnno : fields) {
                Field field = fieldWithAnno.getField();
                if(field.getType() == SimpMessagingTemplate.class){
                    field.setAccessible(true);
                    try {
                        field.set(bean, template);
                    } catch (Exception e) {}
                }
            }

            List<Method> methods = ReflectionUtils.findMethodsWithAnnotation(clazz, Autowired.class);
            for (Method method : methods) {
                Class<?>[] paramtypes = method.getParameterTypes();
                if(paramtypes.length == 1){
                    if(paramtypes[0] == SimpMessagingTemplate.class){
                        method.setAccessible(true);
                        try {
                            method.invoke(bean, template);
                        } catch (Exception e) {}
                    }
                }
            }
        }

        context = context.getParent();
    }
}
}




applicationcontext