2016-03-15 39 views
4

我正在開發和春天有個Java的Web應用中的主要框架(彈簧芯,Spring MVC的,春天的安全性,數據春,春天的WebSocket也有明顯的使用)。調度-的servlet不能映射到的WebSocket請求

聲明在Spring上下文的消息,經紀人這樣提供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中),另有聲明的服務根上下文無法通過websocket發送通知給用戶(因爲他們需要SimpMessagingTemplate)。

的事情是,如果我把這個標籤在根上下文,客戶收到了404當他們訂閱的WebSocket。如果我把標籤在調度員的servlet,然後在根上下文服務無法發送通知,因爲他們需要的SimpMessagingTemplate(但它僅適用於子調度員servlet上下文)。

有沒有辦法「綁定」的調度員的servlet的經紀人?兩次聲明這個bean不是一個正確的解決方案。

此問題是相同的,但Spring : how to expose SimpMessagingTemplate bean to root context ?從另一個角度看(在根上下文,而不是在調度員的servlet聲明的WebSocket)

回答

1

我發現了一個髒溶液。我不喜歡它,但由於缺乏SO以及現任和前任同事的答案,我不得不繼續進行該項目並實施了一個骯髒的修復程序。

骯髒的解決方法是在AutowireSimpMessagingTemplate控制器和預定類(全部由dispatcher-servlet,其中websocket tag聲明掃描),以及傳遞SimpMessagingTemplate作爲參數傳遞給服務方法(在root context聲明)。

此解決方案不透明(SimpMessagingTemplate應直接在服務中直接自動佈線),但它絕對可以解決問題。

0

我已經寫了豆inited servlet的應用程序上下文後做注射。

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

PostInjectSimpMessageTemplateBean:它會通過父應用程序上下文以注入SimpMessageTemplate

無論豆需要模板搜索

將這個bean的servlet應用程序上下文(即websocket所在的同一個xml文件)

將「YOUR.P ACKAGE.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(); 
    } 
} 
} 
相關問題