1

我在此类中使用 Hastable 时遇到问题:

public class HttpBuilder {
    ...        
    private int ret;
    public Hashtable headers;
    private String content;

    HttpBuilder(int majorv, int minorv, int ret){
        ver[0] = majorv;
        ver[1] = minorv;
        this.ret = ret;
        headers = new Hashtable();
    }

    ...
    public void addHeader(String header, String value){
        headers.put(header, value);
    }

    ...
}

此类从多个输入参数构建一个字符串。我在多个线程中使用它。像这样的东西:

HttpBuilder Get(HttpParser request) {
    HttpBuilder response;
    String doc;
    if (request.getRequestURL().equals("/")) {
        try {
            doc = LoadDoc("main.html");
        } catch (IOException e) {
            response = new HttpBuilder(1, 1, 500);
            return response;
        }
        response = new HttpBuilder(1, 1, 200);
        response.addHeader("content-type", "text/html");
        response.setContent(doc);
    } else {
        response = new HttpBuilder(1, 1, 404);
    }
    return response;
}

addHeader Hashtable 为空后。消费数据:

public String toString() {
        String result;
        int len = 0;
        result = "HTTP/"+Integer.toString(ver[0])+"."+Integer.toString(ver[1])+
                " "+getHttpReply(ret)+"\n";
        if(content!=null){
            len = content.length();
            if(len!=0){
                headers.put("content-length", Integer.toString(len));
            }
        }

        Iterator it = headers.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry pairs = (Map.Entry) it.next();
            result += pairs.getKey() + ": " + pairs.getValue() + "\n";
            it.remove();
        }

        if(len!=0){
            result+="\n"+content;
        }


        return result;
    }

我使用 HttpBuilder 的线程类

class ClientThread implements Runnable {
    private Socket socket;
    private ServerData data;
    static public final String NotImplemented = "HTTP/1.1 501 Not Implemented";
    static public final String NotFound = "HTTP/1.1 404 Not Found";

    ClientThread(Socket socket, ServerData data) {
        this.socket = socket;
        this.data = data;
    }

    @Override
    public void run() {
        try {
            HttpParser request = new HttpParser(socket.getInputStream());
            HttpBuilder response;
            if (request.parseRequest() != 200) {
                response = new HttpBuilder(1, 1, 501);
            } else {
                if (request.getMethod().equals("GET")) {
                    response = Get(request);
                } else if (request.getMethod().equals("POST")) {
                    response = Post(request);
                } else {
                    response = new HttpBuilder(1, 1, 400);
                }
            }
        } catch (IOException e) {
            Server.log.log(Level.SEVERE, e.getLocalizedMessage());
        } finally {
            try {
                socket.close();
                Server.log.log(Level.INFO, "Close connection");
            } catch (IOException e) {
                Server.log.log(Level.SEVERE, e.getLocalizedMessage());
            }
        }
    }

    void send(String response) throws IOException {
        PrintWriter out;
        out = new PrintWriter(socket.getOutputStream(), true);
        out.print(response);

    }

    String LoadDoc(String doc) throws IOException {
        final String Folder = "web" + File.separator;
        String result = null;
        doc = Folder + doc;
        long len;
        File f = new File(doc);
        FileReader fr = new FileReader(f);
        len = f.length();
        char[] buffer = new char[(int) len];
        fr.read(buffer);
        result = new String(buffer);
        fr.close();
        return result;

    }

    HttpBuilder Get(HttpParser request) {
        HttpBuilder response;
        String doc;
        if (request.getRequestURL().equals("/")) {
            try {
                doc = LoadDoc("main.html");
            } catch (IOException e) {
                response = new HttpBuilder(1, 1, 500);
                return response;
            }
            response = new HttpBuilder(1, 1, 200);
            response.addHeader("content-type", "text/html");
            response.setContent(doc);
        } else {
            response = new HttpBuilder(1, 1, 404);
        }
        return response;
    }

    HttpBuilder Post(HttpParser request) {
        HttpBuilder response;
        String str;
        if(request.getRequestURL().equals("/")){
            response = new HttpBuilder(1,1, 200);
            str = request.getContentParam("user");
            response.setContent(str+" added to the base.");
        }else {
            response = new HttpBuilder(1, 1, 404);
        }
        return response;
    }    

}
4

2 回答 2

1

修改你的对象似乎是个坏主意toString()。的目的toString()是返回对象的字符串表示形式。多个后续调用toString()应该返回相同的结果。

当您迭代标题时,toString()您删除标题:

    Iterator it = headers.entrySet().iterator();
    while (it.hasNext()) {
        Map.Entry pairs = (Map.Entry) it.next();
        result += pairs.getKey() + ": " + pairs.getValue() + "\n";
        it.remove();
    }

如果这是所需的行为,我建议您为此逻辑使用具有不同名称的方法。

由于toString()覆盖了 的方法Object,因此可能会在您不希望调用它的地方调用它,并清空您的标头映射。

于 2013-06-28T16:30:34.403 回答
0

您的调试器调用toStringHashtable因此您会看到显示的值。但是调用此方法也会删除值,因此在调试器中查看它实际上会清空表。这是一个坏主意,您的toString方法不应修改对象。

而且您HttpBuilder的不是线程安全的,因为您使用Hashtable. 幸运的是,您不会从多个线程调用它,至少不会在您发布的代码中调用它。

于 2013-06-28T19:02:16.297 回答