1

私の要件は、管理者がログインしているすべてのユーザーにデータを送信する必要があることです。最初に 1 つのサーブレットがあり、1 人のユーザーがログイン HTTP 要求を送信し、サーブレットからログイン成功の応答を取得します。このユーザーのセッションが開始されます。同様に、他のユーザーがログインします。これで、1 人のユーザーでもある管理者がログインして、user1 と user2 の 2 人のユーザーがログインしていることを確認できます。 . 管理者は、ログインしているすべてのユーザーにデータを送信する必要があります。サーブレットは、ユーザーの HTTP 要求なしでそのユーザーにデータをプッシュする必要があります。セッション中、ユーザーは他の HTTP リクエストを送信しないことに注意してください。

コメットの代わりに、ログインしている各ユーザーの応答 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. ログインしているすべてのユーザーに 1 つの特定のメッセージを送信する方法は?
  2. コメットなしでこれを達成できますか?

何か問題があった場合はコードを修正し、他の提案を手伝ってください。ありがとう

4

1 に答える 1

5

サーブレットは、ユーザーの HTTP 要求なしでそのユーザーにデータをプッシュする必要があります。

それは技術的に不可能です。HTTP プロトコルは単純にそれを許可しません。ブラウザは、リクエストを送信した場合にのみ、サーバーからのレスポンスを取得できます。応答の読み取りが完了すると、次の要求を送信するまで、ソケットからそれ以上何も読み取ろうとしません。

あなたができることは、表示される管理メッセージがあるかどうかを尋ねるAJAXリクエストをサーバーに定期的に行うすべてのページにjavascriptを入れることです。

COMET を使用してこれを行うこともできると思います。

最後の応答を保持し、それにさらにデータを書き込もうとする現在のアプローチは、HTTP プロトコルとサーブレット ステート マシンに違反しているため失敗します。ログイン サーブレットが元の要求を完了すると、応答の出力ストリームがソケットにフラッシュされ、閉じられます。再度開くことはできません。また、できたとしても、ブラウザーはユーザーが書き込んだデータをどう処理すればよいかわかりません。

更新:これには、機能する可能性のあるバリエーションがあります。これには WebSockets が含まれます...クライアントがリクエストでいくつかの特別なヘッダーを送信し、サーバーが 101 応答を送信してプロトコルを切り替えますhttps://en.wikipedia.org/wiki/WebSocketを参照

于 2012-10-28T07:35:10.690 に答える