如何使用Java HttpServer/HttpExchange在GET中获取查询字符串?

如何使用Java HttpServer/HttpExchange在GET中获取查询字符串?,java,get,query-string,httpserver,Java,Get,Query String,Httpserver,我试图用Java创建一个简单的HttpServer来处理GET请求, 但是,当我尝试获取请求的get参数时,我注意到HttpExchange类没有相应的方法 有人知道读取GET参数(查询字符串)的简单方法吗 这是我的处理程序的外观: public class TestHandler{ @Override public void handle(HttpExchange exc) throws IOxception { String response = "This is the r

我试图用Java创建一个简单的HttpServer来处理GET请求, 但是,当我尝试获取请求的get参数时,我注意到HttpExchange类没有相应的方法

有人知道读取GET参数(查询字符串)的简单方法吗

这是我的处理程序的外观:

public class TestHandler{
  @Override
  public void handle(HttpExchange exc) throws IOxception {
    String response = "This is the reponse";
    exc.sendResponseHeaders(200, response.length());

    // need GET params here

    OutputStream os = exc.getResponseBody();
    os.write(response.getBytes());
    os.close();
  } 
}
。。主要方法是:

public static void main(String[] args) throws Exception{
  // create server on port 8000
  InetSocketAddress address = new InetSocketAddress(8000);
  HttpServer server = new HttpServer.create(address, 0);

  // bind handler
  server.createContext("/highscore", new TestHandler());
  server.setExecutor(null);
  server.start();
}

以下内容:
httpExchange.getRequestURI().getQuery()

将以类似以下格式返回字符串:
“field1=value1&field2=value2&field3=value3…”

所以您可以自己简单地解析字符串,这就是解析函数的样子:

public Map<String, String> queryToMap(String query) {
    if(query == null) {
        return null;
    }
    Map<String, String> result = new HashMap<>();
    for (String param : query.split("&")) {
        String[] entry = param.split("=");
        if (entry.length > 1) {
            result.put(entry[0], entry[1]);
        }else{
            result.put(entry[0], "");
        }
    }
    return result;
}
公共地图查询地图(字符串查询){
if(查询==null){
返回null;
}
映射结果=新的HashMap();
for(字符串参数:query.split(&)){
字符串[]项=参数拆分(“”);
如果(entry.length>1){
结果.put(条目[0],条目[1]);
}否则{
result.put(条目[0],“”);
}
}
返回结果;
}
你可以这样使用它:

Map<String, String> params = queryToMap(httpExchange.getRequestURI().getQuery()); 
System.out.println("param A=" + params.get("A"));
Map params=queryToMap(httpExchange.getRequestURI().getQuery());
System.out.println(“参数A=”+params.get(“A”);

基于@anon01的答案,下面是如何在Groovy中实现这一点:

Map<String,String> getQueryParameters( HttpExchange httpExchange )
{
    def query = httpExchange.getRequestURI().getQuery()
    return query.split( '&' )
            .collectEntries {
        String[] pair = it.split( '=' )
        if (pair.length > 1)
        {
            return [(pair[0]): pair[1]]
        }
        else
        {
            return [(pair[0]): ""]
        }
    }
}

与annon01相反,这个答案正确地解码了键和值。它不使用
String.split
,而是使用
indexOf
扫描字符串,速度更快

public static Map<String, String> parseQueryString(String qs) {
    Map<String, String> result = new HashMap<>();
    if (qs == null)
        return result;

    int last = 0, next, l = qs.length();
    while (last < l) {
        next = qs.indexOf('&', last);
        if (next == -1)
            next = l;

        if (next > last) {
            int eqPos = qs.indexOf('=', last);
            try {
                if (eqPos < 0 || eqPos > next)
                    result.put(URLDecoder.decode(qs.substring(last, next), "utf-8"), "");
                else
                    result.put(URLDecoder.decode(qs.substring(last, eqPos), "utf-8"), URLDecoder.decode(qs.substring(eqPos + 1, next), "utf-8"));
            } catch (UnsupportedEncodingException e) {
                throw new RuntimeException(e); // will never happen, utf-8 support is mandatory for java
            }
        }
        last = next + 1;
    }
    return result;
}
公共静态映射parseQueryString(字符串qs){
映射结果=新的HashMap();
如果(qs==null)
返回结果;
int last=0,next,l=qs.length();
while(最后一个最后一个){
int eqPos=qs.indexOf('=',last);
试一试{
如果(eqPos<0 | | eqPos>next)
result.put(urldecover.decode(qs.substring(last,next),“utf-8”),“”);
其他的
结果.put(urldecker.decode(qs.substring(最后一个,eqPos),“utf-8”)、urldecker.decode(qs.substring(eqPos+1,下一个),“utf-8”);
}捕获(不支持的编码异常e){
抛出新的RuntimeException(e);//永远不会发生,java必须支持utf-8
}
}
最后一个=下一个+1;
}
返回结果;
}

偶然发现了这一点,我想在这里抛出一个实现,同时添加一些额外的位(不是在前面的答案中)

Extra 1:我添加了一个过滤器,以避免处理任何空参数。不应该发生的事情,但它允许更干净的实现,而不是不处理问题(并发送空响应)。这方面的一个示例类似于
?param1=value1¶m2=

Extra 2:我已经利用了第二次拆分操作。这允许传递一个查询参数,例如
?param1=it_has=in it&other=something

public static Map<String, String> getParamMap(String query) {
    // query is null if not provided (e.g. localhost/path )
    // query is empty if '?' is supplied (e.g. localhost/path? )
    if (query == null || query.isEmpty()) return Collections.emptyMap();

    return Stream.of(query.split("&"))
            .filter(s -> !s.isEmpty())
            .map(kv -> kv.split("=", 2)) 
            .collect(Collectors.toMap(x -> x[0], x-> x[1]));

}

简单的方法?解析URI;这只是一个get请求。如果您必须处理POST,类似的事情可能会有所帮助。重要的是要知道:查询可以为null。你应该检查一下。谢谢你的回答!但是,对于其值包含符号AND的参数,它将失败。要修复此问题,请使用
getRawQuery()
而不是
getQuery()
,然后在“&”@Evan上拆分后使用
param=java.net.urldecker.decode(param,“UTF-8”)
,我认为解码应该在将值放入映射时发生-这样,如果其中有“=”的话,就不会丢失部分值。这不会正确地对字符串进行编码,应该使用
urldecker
。它应该是
param.split(“=”,2)如果值包含=。(顺便说一句,这个解决方案不支持像x=111&x=222这样的双键)好的,谢谢。但问题是Java,而不是Goovy;)
public static Map<String, String> getParamMap(String query) {
    // query is null if not provided (e.g. localhost/path )
    // query is empty if '?' is supplied (e.g. localhost/path? )
    if (query == null || query.isEmpty()) return Collections.emptyMap();

    return Stream.of(query.split("&"))
            .filter(s -> !s.isEmpty())
            .map(kv -> kv.split("=", 2)) 
            .collect(Collectors.toMap(x -> x[0], x-> x[1]));

}
import java.util.Map;
import java.util.Collections;
import java.util.stream.Stream;
import java.util.stream.Collectors;