use*_*457 1 java servlets servlet-3.0 servlet-filters servlet-listeners
我的要求是管理员应该向所有登录用户发送数据.我有一个servlet,第一个用户发送登录HTTP req并从servlet获取登录成功响应现在该用户的会话已启动.同样其他用户登录.现在管理员也是一个用户可以登录并看到两个用户user1和user2登录管理员应该向所有登录用户发送数据.Servlet应该在没有用户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");
}
}
}
Run Code Online (Sandbox Code Playgroud)
一旦用户在arraylist中登录存储的resp obj.
synchronized (connections) {
connections.add(response);
}
Run Code Online (Sandbox Code Playgroud)
后来使用那个obj得到了printwriter obj.
PrintWriter writer = connections.get(i).getWriter();
Run Code Online (Sandbox Code Playgroud)
问题:
如果我做了任何错误,请更正代码并帮助其他建议.谢谢
Servlet应该在没有用户HTTP请求的情况下将数据推送给该用户.
这在技术上是不可能的.HTTP协议根本不允许它.浏览器只有在发送请求时才能从服务器获得响应.一旦完成读取响应,它将不会尝试从其套接字中读取任何内容......直到它发送下一个请求.
您可以做的是将一些javascript放入所有页面中,这些页面定期向服务器发出AJAX请求,询问是否有要显示的管理消息.
我想你也可以使用COMET做到这一点.
您当前保留最后一个响应并尝试向其写入更多数据的方法失败,因为它违反了HTTP协议和servlet状态机.当登录servlet完成原始请求时,响应的输出流将刷新到套接字并关闭.它无法重新打开,即使可以,浏览器也不知道如何处理您编写的数据.
更新:有一个变化可以工作.它涉及WebSockets ...其中客户端在请求中发送一些特殊标头,服务器发送101响应并切换协议 ; 请参阅https://en.wikipedia.org/wiki/WebSocket
| 归档时间: |
|
| 查看次数: |
1886 次 |
| 最近记录: |