1

我的要求是管理員應該向所有登錄的用戶發送數據。我有一個servlet第一個用戶發送登錄HTTP請求並獲取來自servlet現在會話的登錄成功響應爲此用戶啓動。類似地其他用戶登錄。現在管理員這也是一個用戶可以登錄並看到兩個用戶user1和user2登錄。管理員應該向所有登錄的用戶發送數據。 Servlet應該向沒有用戶HTTP請求的用戶推送數據。請注意會話期間用戶不會發送任何其他HTTP請求。相反,彗星的如何將數據從servlet發送到所有登錄的用戶

我試圖存儲每個響應OBJ的登錄用戶,然後再使用obj是否曾經試圖發佈數據傳回用戶,但沒有奏效。

請檢查下面的代碼:LoginServlet.java

public class LoginServlet extends HttpServlet { 
     private static final long serialVersionUID = 1L; 
     ServletContext sc; 

     protected ArrayList<HttpServletResponse> connections = new ArrayList<HttpServletResponse>(); 

     public LoginServlet() { 
      super(); 

     } 

     public void init() throws ServletException { 
      super.init(); 

      sc = getServletContext(); 

     } 

     protected void doGet(HttpServletRequest request, 
       HttpServletResponse response) throws ServletException, IOException { 

     } 

     protected void doPost(HttpServletRequest request, 
       HttpServletResponse response) throws ServletException, IOException { 


      synchronized (connections) { 
       connections.add(response); 
      } 
      ServletContext sc = getServletContext(); 
      Integer x = (Integer) sc.getAttribute("hit"); 

      if (x == null) 
       x = 1; 
      else 
       x++; 
      sc.setAttribute("hit", x); 

      String username = request.getParameter("username"); 
      String password = request.getParameter("password"); 

      HttpSession session = request.getSession(true); 

      session.setAttribute("username", username); 
      session.setAttribute("password", password); 
      response.setContentType("text/html"); 

      ArrayList<LoggedInUser> loggedInUsers = (ArrayList<LoggedInUser>) sc 
        .getAttribute("users"); 

      if (loggedInUsers == null) { 
       System.out.println("loggedInUsers creates"); 
       loggedInUsers = new ArrayList<LoggedInUser>(); 

      } 
      loggedInUsers.add(new LoggedInUser(username, password)); 

      sc.setAttribute("users", loggedInUsers); 

      PrintWriter out = response.getWriter(); 
      System.out.println("loggedInUsers ==>" + loggedInUsers.size()); 
      if (username != null && username.equals("admin")) { 
       out.println("Admin Login Success"); 
       ServletContext scx = getServletContext(); 
       Integer xx = (Integer) scx.getAttribute("hit"); 

       out.println("<H1>Users visited " + xx + "</h1>"); 
       loggedInUsers = (ArrayList<LoggedInUser>) sc.getAttribute("users"); 

       for (int i = 0; i <= loggedInUsers.size() - 1; i++) { 
        LoggedInUser LoggedInUser = loggedInUsers.get(i); 
        out.println(LoggedInUser.getmUsername()+ "<br>"); 
       } 

       for (int i = 0; i < connections.size(); i++) { 

        try { 

         LoggedInUser LoggedInUser = loggedInUsers.get(i); 
         PrintWriter writer = connections.get(i).getWriter(); 
         System.out.println("inside loope " + i + "\n" + writer); 
         writer.println("MESSAGE FROM ADMIN HERE" + "<br>"); 

         writer.flush(); 
         writer.close(); 
        } catch (IOException e) { 
         log("IOExeption sending message", e); 
        } 

       } 

      } else { 
       out.println("Welcome " + username + " Login Success"); 
      } 
     } 
    } 

只要在ArrayList中存儲的RESP OBJ用戶登錄。

synchronized (connections) { 
    connections.add(response); 
} 

然後使用該obj得到了printwriter obj。

PrintWriter writer = connections.get(i).getWriter(); 

問題:

  1. 如何一個具體的MSG發送給所有已登錄的用戶?
  2. 沒有彗星可以實現嗎?

如果有任何問題,我已經完成並幫助其他建議,請更正代碼。感謝

+0

使用電子郵件:d –

+0

嘿,你用什麼java的演示技術? Java-Server-Faces,Wicket,JSP,Struts,Spring? –

+0

@ peter不能存儲響應obj並使用該obj發送消息嗎? – user1537457

回答

5

的Servlet應該將數據推送到該用戶無用戶的HTTP請求。

這不是技術上是可行的。 HTTP協議根本不允許。如果瀏覽器發送請求,它只能從服務器獲得響應。一旦完成讀取響應,它將不會嘗試從套接字中讀取更多內容......直到它發送下一個請求。

你可以做的是把一些JavaScript到所有定期做一個AJAX請求到服務器,詢問是否有要顯示的管理信息的網頁。

我想你也可以用COMET來做到這一點。

您當前保持最後響應,並試圖將它失敗,因爲它違反了HTTP協議寫入更多的數據的方法,和servlet狀態機。當登錄servlet完成原始請求時,響應的輸出流將刷新到套接字並關閉。它不能重新打開,即使可能,瀏覽器也不知道如何處理你寫的數據。

更新:這可以工作的變化。它涉及WebSockets ...客戶端在請求中發送一些特殊的標頭,並且服務器發送101響應和交換協議;看到https://en.wikipedia.org/wiki/WebSocket

+0

Comet或websockets或即將webRTC dataChannel – 2012-10-28 08:34:46

+0

@ stephen其實我要打來自android應用程序的URL不是來自android瀏覽器或PC網絡瀏覽器。是否有其他替代方案來實現這一目標?通過Android應用程序,用戶將獲得連接,管理員將把數據推送給所有人或者一些選定的用戶。對於Android我們有GCM谷歌雲設備消息服務,但這將是開銷,因爲GCM只是通知android應用程序有關新數據在服務器端可用,所以用戶必須再次命中服務器以獲取數據。所以我想爲什麼不把數據從服務器推送到用戶。讓我知道你的想法。 – user1537457

+0

*「所以我想爲什麼不把數據從服務器推送到用戶,讓我知道你的想法。」* - 我的想法是1)我不知道你會怎麼做。 2)爲什麼要讓自己變得困難? –

相關問題