【java】实现Get请求传body参数

先看curl

curl --location --request GET 'http://127.0.0.1:8080/complaint/queryLineTeams' \
--header 'Content-Type: application/json' \
--data-raw '{
    "sheetNo":"123456",
    "productCodes":"2094145031"
}'

对的,你没有看错,get带请求体,长这么大,第一次看见。第一反应,这么调用接口肯定报错,没想到接口居然返回数据了。既然这样,那只能开搞了。

打开百度,搜索一番,毛也没有。然后可以自己尝试各种工具类,最终找到了hutool这个工具类,居然支持get请求带请求体。本着用就可以了,但是这个工具包太大了,想着得看看他怎么解决的。终于找到了核心代码

// 解决在Rest请求中,GET请求附带body导致GET请求被强制转换为POST
		// 在sun.net.www.protocol.http.HttpURLConnection.getOutputStream0方法中,会把GET方法
		// 修改为POST,而且无法调用setRequestMethod方法修改,因此此处使用反射强制修改字段属性值
		// https://stackoverflow.com/questions/978061/http-get-with-request-body/983458
		if(method == Method.GET && method != getMethod()){
			ReflectUtil.setFieldValue(this.conn, "method", Method.GET.name());
		}

看着核心代码,翻开jdk源码一看,果然自己的问题,自己自动转换了,不知道说好还是坏。只能反射搞一搞了

//HttpURLConnection
 private synchronized OutputStream getOutputStream0() throws IOException {
        try {
            if (!this.doOutput) {
                throw new ProtocolException("cannot write to a URLConnection if doOutput=false - call setDoOutput(true)");
            } else {
                if (this.method.equals("GET")) {
                    this.method = "POST"; //重点这这块
                }

                if ("TRACE".equals(this.method) && "http".equals(this.url.getProtocol())) {
                    throw new ProtocolException("HTTP method TRACE doesn't support output");
                } else if (this.inputStream != null) {
                    throw new ProtocolException("Cannot write output after reading input.");
                } else {
                    if (!this.checkReuseConnection()) {
                        this.connect();
                    }

                    boolean var1 = false;
                    String var8 = this.requests.findValue("Expect");
                    if ("100-Continue".equalsIgnoreCase(var8) && this.streaming()) {
                        this.http.setIgnoreContinue(false);
                        var1 = true;
                    }

                    if (this.streaming() && this.strOutputStream == null) {
                        this.writeRequests();
                    }

                    if (var1) {
                        this.expect100Continue();
                    }

                    this.ps = (PrintStream)this.http.getOutputStream();
                    if (this.streaming()) {
                        if (this.strOutputStream == null) {
                            if (this.chunkLength != -1) {
                                this.strOutputStream = new HttpURLConnection.StreamingOutputStream(new ChunkedOutputStream(this.ps, this.chunkLength), -1L);
                            } else {
                                long var3 = 0L;
                                if (this.fixedContentLengthLong != -1L) {
                                    var3 = this.fixedContentLengthLong;
                                } else if (this.fixedContentLength != -1) {
                                    var3 = (long)this.fixedContentLength;
                                }

                                this.strOutputStream = new HttpURLConnection.StreamingOutputStream(this.ps, var3);
                            }
                        }

                        return this.strOutputStream;
                    } else {
                        if (this.poster == null) {
                            this.poster = new PosterOutputStream();
                        }

                        return this.poster;
                    }
                }
            }
        } catch (RuntimeException var5) {
            this.disconnectInternal();
            throw var5;
        } catch (ProtocolException var6) {
            int var2 = this.responseCode;
            this.disconnectInternal();
            this.responseCode = var2;
            throw var6;
        } catch (IOException var7) {
            this.disconnectInternal();
            throw var7;
        }
    }

把这个改成get就好了。

最后附上我东拼西凑的方法

public static String sendGetJson2(String url, String params, Map headermap) {
        PrintWriter out = null;
        BufferedReader in = null;
        String result = "";
        log.info("==sendGetson2发送的地址:"+ url);
        log.info("==sendGetson2发送的请求参数:"+ JSON.toJSONString(params));
        log.info("==sendGetson2头参数:"+JSON.toJSONString(headermap));
        try {
            //组装查询参数
            String urlNameString = url;
            URL realUrl = new URL(urlNameString);
            // 打开和URL之间的连接
            URLConnection conn = realUrl.openConnection();
            // 设置通用的请求属性
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("user-agent","Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            conn.setRequestProperty("Content-Type","application/json; charset=UTF-8");
            for(Object key : headermap.keySet()){
                conn.setRequestProperty(key.toString(), headermap.get(key).toString());
            }
            // 发送POST请求必须设置如下两行
            conn.setDoOutput(true);
            conn.setDoInput(true);
            // 获取URLConnection对象对应的输出流
            out = new PrintWriter(new OutputStreamWriter(conn.getOutputStream(),"UTF-8"));
            //将post请求转为get请求(通过反射)
            // 解决在Rest请求中,GET请求附带body导致GET请求被强制转换为POST
            // 在sun.net.www.protocol.http.HttpURLConnection.getOutputStream0方法中,会把GET方法
            // 修改为POST,而且无法调用setRequestMethod方法修改,因此此处使用反射强制修改字段属性值
            // https://stackoverflow.com/questions/978061/http-get-with-request-body/983458
            List fields = new ArrayList<>() ;
            Class tempClass = conn.getClass();
            while (tempClass != null) {//当父类为null的时候说明到达了最上层的父类(Object类).
                fields.addAll(Arrays.asList(tempClass.getDeclaredFields()));
                tempClass = tempClass.getSuperclass(); //得到父类,然后赋给自己
            }
            for (Field field : fields) {
                if ("method".equals(field.getName())){
                    field.setAccessible(true);
                    field.set(conn,"GET");
                }
            }
            // 发送请求参数
            out.print(params);
            // flush输出流的缓冲
            out.flush();
            // 定义BufferedReader输入流来读取URL的响应
            in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
            log.info(" ==sendGetson2的result结果:"+result);
        } catch (Exception e) {
            log.info("==sendGetson2发送 POST 请求出现异常!"+e);
            e.printStackTrace();
            if(e.getMessage().length() > 500){
                result = "==sendGetson2发送 POST 请求出现异常!"+ e.getMessage().substring(0,500);
            } else {
                result = "==sendGetson2发送 POST 请求出现异常!"+ e.getMessage();
            }

        }finally{//使用finally块来关闭输出流、输入流
            try{
                if(out!=null){
                    out.close();
                }
                if(in!=null){
                    in.close();
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }

        }
        log.info("==sendGetson2的请求结果:"+result);
        return result;

    }

其实还没完,还有一种实现,利用httpclient发包,参考我是如何!-爱代码爱编程

你可能感兴趣的:(restful,java,http)