为什么我的聊天服务器 servlet 的 doPost 方法没有被调用?
我正在用java设计一个聊天服务器。通信是基于 Http 的,而不是基于套接字的。在客户端我有一个小程序。在服务器端我有一个servlet。
Applet:我创建一个新线程来侦听传入消息(GET 方法)。主线程用于发送消息(POST消息)。
部分代码是:
public void start() {
System.out.println("Creating new thread");
Thread thread = new Thread(this);
thread.start();
}
private String getNewMessage() {
System.out.println("Inside getNewMessage");
String msg = null;
try {
while(msg == null) {
System.out.println("Trying to listen to servlet");
URL servlet = new URL(getCodeBase(), "NewServlet?mode=msg");
URLConnection con = servlet.openConnection();
con.setUseCaches(false);
DataInputStream din = new DataInputStream(new BufferedInputStream(con.getInputStream()));
msg = din.readUTF();
System.out.println("message read :" + msg);
}
} catch (Exception e) {
e.printStackTrace();
}
return msg + "\n";
}
public void run() {
System.out.println("Inside new thread");
while(true) {
System.out.println("inside first while");
String newMsg = getNewMessage();
chatOutput.append(newMsg);
System.out.println("Appended!!");
}
}
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
String message = chatInput.getText();
chatInput.setText("");
chatOutput.append(message + "\n");
try {
System.out.println("Trying to send msg :" + message);
URL url = new URL(getCodeBase(), "NewServlet");
URLConnection servletConnection = url.openConnection();
servletConnection.setDoInput(true);
servletConnection.setDoOutput(true);
servletConnection.setUseCaches(false);
servletConnection.setRequestProperty("Content-Type", "application/octet-stream");
ObjectOutputStream out = new ObjectOutputStream(servletConnection.getOutputStream());
out.writeObject(message);
out.flush();
out.close();
System.out.println("Message sent!");
} catch (Exception e) {
e.printStackTrace();
}
}
下一个代码来自 servlet 端。它使用 Observable 接口来识别并向客户端发送消息。
public class NewServlet extends HttpServlet {
// getNextMessage() returns the next new message. // It blocks until there is one.
public String getNextMessage() {
// Create a message sink to wait for a new message from the
// message source.
System.out.println("inside getNextMessage");
return new MessageSink().getNextMessage(source);}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("Inside Doget");
response.setContentType("text/plain");
PrintWriter out = response.getWriter();
out.println(getNextMessage());
}
// broadcastMessage() informs all currently listening clients that there
// is a new message. Causes all calls to getNextMessage() to unblock.
public void broadcastMessage(String message) {
// Send the message to all the HTTP-connected clients by giving the
// message to the message source
source.sendMessage(message); }
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("Inside DoPost");
try {
ObjectInputStream din= new ObjectInputStream(request.getInputStream());
String message = (String)din.readObject();
System.out.println("received msg");
if (message != null) broadcastMessage(message);
System.out.println("Called broadcast");
// Set the status code to indicate there will be no response
response.setStatus(response.SC_NO_CONTENT);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Returns a short description of the servlet.
* @return a String containing servlet description
*/
@Override
public String getServletInfo() {
return "Short description";
}
MessageSource source = new MessageSource();}
class MessageSource extends Observable {
public void sendMessage(String message) {
System.out.println("inside sendMsg");
setChanged();
notifyObservers(message);
}
}
class MessageSink implements Observer {
String message = null; // set by update() and read by getNextMessage()
// Called by the message source when it gets a new message
synchronized public void update(Observable o, Object arg) {
// Get the new message
message = (String)arg;
// Wake up our waiting thread
notify();
}
// Gets the next message sent out from the message source
synchronized public String getNextMessage(MessageSource source) {
// Tell source we want to be told about new messages
source.addObserver(this);
System.out.println("AddedObserver");
// Wait until our update() method receives a message
while (message == null) {
try { wait(); } catch (Exception ignored) { }
}
// Tell source to stop telling us about new messages
source.deleteObserver(this);
// Now return the message we received
// But first set the message instance variable to null
// so update() and getNextMessage() can be called again.
String messageCopy = message;
message = null;
System.out.println("Returning msg");
return messageCopy;
}
}
正如你所看到的,我已经包含了 System.out.println("Some message");在某些地方。这只是为了调试目的。 在 Java 控制台中,我得到以下输出:
创建新线程
在新线程内。
首先在里面。
在 getNewMessage 内部。
尝试监听 servlet。
在 servlet 方面,我在 tomcat 日志中得到以下输出:
Doget 内部。
在 getNextMessage 中。
添加了观察者。
在小程序中输入消息并发送后,我在 Java 控制台中得到以下输出:
正在尝试发送消息:you deR??
消息已发送!
但在 servlet 方面,我在日志中没有得到任何内容。 我使用 O'Reily Java Servlet 编程作为参考(观察者接口来自那里)。但我没有收到两个客户之间的任何聊天通信。从日志中可以看出,doPOST
方法没有被调用。 这是什么原因?
I am designing a chat server in java. The communication is Http based and not socket based. In the client side I have an applet. In the server side I have a servlet.
Applet: I create a new thread to listen for incoming messages(GET method). The main thread is used to send messages(POST messages).
The partial code is :
public void start() {
System.out.println("Creating new thread");
Thread thread = new Thread(this);
thread.start();
}
private String getNewMessage() {
System.out.println("Inside getNewMessage");
String msg = null;
try {
while(msg == null) {
System.out.println("Trying to listen to servlet");
URL servlet = new URL(getCodeBase(), "NewServlet?mode=msg");
URLConnection con = servlet.openConnection();
con.setUseCaches(false);
DataInputStream din = new DataInputStream(new BufferedInputStream(con.getInputStream()));
msg = din.readUTF();
System.out.println("message read :" + msg);
}
} catch (Exception e) {
e.printStackTrace();
}
return msg + "\n";
}
public void run() {
System.out.println("Inside new thread");
while(true) {
System.out.println("inside first while");
String newMsg = getNewMessage();
chatOutput.append(newMsg);
System.out.println("Appended!!");
}
}
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
String message = chatInput.getText();
chatInput.setText("");
chatOutput.append(message + "\n");
try {
System.out.println("Trying to send msg :" + message);
URL url = new URL(getCodeBase(), "NewServlet");
URLConnection servletConnection = url.openConnection();
servletConnection.setDoInput(true);
servletConnection.setDoOutput(true);
servletConnection.setUseCaches(false);
servletConnection.setRequestProperty("Content-Type", "application/octet-stream");
ObjectOutputStream out = new ObjectOutputStream(servletConnection.getOutputStream());
out.writeObject(message);
out.flush();
out.close();
System.out.println("Message sent!");
} catch (Exception e) {
e.printStackTrace();
}
}
This next code is from the servlet side. it uses the Observable interface to identify and send messages to clients.
public class NewServlet extends HttpServlet {
// getNextMessage() returns the next new message. // It blocks until there is one.
public String getNextMessage() {
// Create a message sink to wait for a new message from the
// message source.
System.out.println("inside getNextMessage");
return new MessageSink().getNextMessage(source);}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("Inside Doget");
response.setContentType("text/plain");
PrintWriter out = response.getWriter();
out.println(getNextMessage());
}
// broadcastMessage() informs all currently listening clients that there
// is a new message. Causes all calls to getNextMessage() to unblock.
public void broadcastMessage(String message) {
// Send the message to all the HTTP-connected clients by giving the
// message to the message source
source.sendMessage(message); }
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("Inside DoPost");
try {
ObjectInputStream din= new ObjectInputStream(request.getInputStream());
String message = (String)din.readObject();
System.out.println("received msg");
if (message != null) broadcastMessage(message);
System.out.println("Called broadcast");
// Set the status code to indicate there will be no response
response.setStatus(response.SC_NO_CONTENT);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Returns a short description of the servlet.
* @return a String containing servlet description
*/
@Override
public String getServletInfo() {
return "Short description";
}
MessageSource source = new MessageSource();}
class MessageSource extends Observable {
public void sendMessage(String message) {
System.out.println("inside sendMsg");
setChanged();
notifyObservers(message);
}
}
class MessageSink implements Observer {
String message = null; // set by update() and read by getNextMessage()
// Called by the message source when it gets a new message
synchronized public void update(Observable o, Object arg) {
// Get the new message
message = (String)arg;
// Wake up our waiting thread
notify();
}
// Gets the next message sent out from the message source
synchronized public String getNextMessage(MessageSource source) {
// Tell source we want to be told about new messages
source.addObserver(this);
System.out.println("AddedObserver");
// Wait until our update() method receives a message
while (message == null) {
try { wait(); } catch (Exception ignored) { }
}
// Tell source to stop telling us about new messages
source.deleteObserver(this);
// Now return the message we received
// But first set the message instance variable to null
// so update() and getNextMessage() can be called again.
String messageCopy = message;
message = null;
System.out.println("Returning msg");
return messageCopy;
}
}
As you can see I have included System.out.println("Some message"); in some places. this was just for debugging purposes.
In the Java console, I get the following output:
Creating new thread
Inside new thread.
inside first while.
Inside getNewMessage.
Trying to listen to servlet.
On the servlet side, I get the following output in the tomcat logs:
Inside Doget.
inside getNextMessage.
AddedObserver.
After I type a message in the applet, and send it, I get the following output in the Java console:
Trying to send msg :you deR??
Message sent!
But on the servlet side, I dont get anything in the logs.
I used the O'Reily Java Servlet Programming as reference (The observer interface comes from there). But I am not getting any chat communication between two clients. As can be understood from the logs, the doPOST
method is not called. What is the reason for this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我通过在小程序端发送消息后接收消息(状态消息)解决了该问题。在 servlet 端,在
doPost
方法中,我在读取消息后发送了状态消息 ("1"
)。我不知道这到底是如何解决问题的,但我猜想因为我有
setDoInput(true);
,所以它正在等待读取一些消息。不管怎样,好消息是我至少得到了上述调试过程想要的结果。
另外,在
getNewMessage
方法中需要使用ObjectInputStream
而不是DataInputStream
(因为消息是通过 ObjectOutputStream 发送的)。现在聊天服务器可以正常运行了。I fixed the problem by receiving message (a status message) after sending the message in the applet side. In the servlet side, in the
doPost
method, I sent the status message ("1"
), after reading the message.I don't know how exactly this fixed the problem, but I guess that since I had
setDoInput(true);
, it was waiting for some message to read.Anyway, the good news is that I have at least got the desired result of the above debugging process.
Also, it was necessary to use
ObjectInputStream
instead ofDataInputStream
in thegetNewMessage
method (since the message was sent by ObjectOutputStream). Now the chat server works smoothly.