【问题标题】:Why is my chat server servlet's doPost method not called?为什么我的聊天服务器 servlet 的 doPost 方法没有被调用?
【发布时间】:2010-03-24 16:56:57
【问题描述】:

我正在用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 Programming 作为参考(观察者接口来自那里)。但我没有得到两个客户之间的任何聊天通信。从日志可以理解,doPOST方法没有被调用。 这是什么原因?

【问题讨论】:

    标签: http servlets applet http-post


    【解决方案1】:

    我通过在小程序端发送消息后接收消息(状态消息)解决了这个问题。在servlet端,在doPost方法中,我发送了状态消息("1"),读取消息后。

    我不知道这究竟是如何解决问题的,但我想既然我有setDoInput(true);,它正在等待阅读一些消息。

    不管怎样,好消息是我至少得到了上述调试过程想要的结果。

    此外,在getNewMessage 方法中必须使用ObjectInputStream 而不是DataInputStream(因为消息是由ObjectOutputStream 发送的)。现在聊天服务器可以正常运行了。

    【讨论】:

    • 忘记添加坏消息了。我可以发送消息,但我收到“null”消息作为回报(GET 方法部分监听其他用户输入消息并显示它们,在这种情况下它显示“null”)。
    • 也修复了这个问题。将 getNewMessage 函数中的“DataInputStream ...”部分替换为 ObjectInputStream ... 这是因为小程序通过 ObjectOutputStream() 发送输入的消息。现在聊天服务器运行顺利
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-12-07
    • 2019-07-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多