Java基础知识-发送Post请求实例

本文介绍了Java中发送HTTP Post请求的两种方法,主要通过HttpURLConnection和URLConnection实现。重点讲解了请求的四个主要步骤,强调了在使用POST方式时设置参数、调用connect()函数以及处理输入输出流的顺序。在HttpURLConnection中,真正的HTTP请求是在调用getInputStream()时发送的。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

特别好的一个文章解析:

https://blog.youkuaiyun.com/laiyaxing/article/details/51585755

一:发送请求主要有两种方法。

抽象类URLConnection是所有类的超类,他代表应用程序和URL之间的通信连接。个人感觉这两个连接方式除了在一开始的:通过在 URL 上调用 openConnection 方法创建连接对象语法上略有不同之外,其余的差不太多

1.使用HttpURLConnection发送Post和Get请求。

URL url=new URL(posturl);HttpURLConnection conn=(HttpURLConnection) url.openConnection();

2.使用URLConnection发送Post和Get请求。   

URL url=new URL(posturl); URLConnection conn=url.openConnection();

二:主要流程是下面四步:

1.通过在URL上调用openconnetcion方法创建连接

2.设置请求参数,属性,请求正文(即需要提交的数据)

3.使用connect方法简历到远程对象的实际连接(可省略),为啥?

因为:connect()函数,实际上只是建立了一个与服务器的tcp连接,并没有实际发送http请求。

无论是post还是get,http请求实际上直到HttpURLConnection的getInputStream()这个函数里面才正式发送出去。

4.远程对象变为可用,获取response返回的相应信息

三:一个使用HttpURLConnection类实现的post请求实例

 
    public static String sendServicePost(String url, String request, String ContentType) {
        String result = "";

        try {
            /*一 定义相关变量*/
            PrintWriter out = null;//存储请求
            BufferedReader in = null;//存储接口返回的response
            /*二 获取访问地址*/
            //1.1得到网络访问对象java.net.HttpURLConnection
            URL realUrl = new URL(url);
            /*设置请求参数,以流的形式连接*/
            HttpURLConnection conn = (HttpURLConnection) realUrl.openConnection();
            //2.1.设置http的请求头
            conn.setRequestProperty("accept", "*/*");
            //2.2.设置请求的Contenttype
            if (ContentType == null || ContentType.equals("")) {
                if (isJson(request)) {
                    conn.setRequestProperty("Content-Type", "application/json;charset=utf-8");
                } else {
                    if (url.toLowerCase().contains(".asmx")) {
                        conn.setRequestProperty("Content-Type", "text/xml;charset=utf-8");
                    } else {
                        conn.setRequestProperty("Content-Type", "application/xml;charset=utf-8");
                    }
                }
            } else {
                conn.setRequestProperty("Content-Type", ContentType);
            }
            //2.3.特殊处理:如果是1.0的请求则进一步具体设定setRequestProperty,并对xml格式做优化
            if (url.toLowerCase().contains(".asmx")) {
                if (url.toLowerCase().contains("datacomparews")) {
                    conn.setRequestProperty("SOAPAction", "http://tempuri.org/DataTableCompare");
                    String Xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
                            "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">" +
                            "<soap:Body>";
                    Xml += request.replace("<?xml version=\"1.0\" encoding=\"UTF-8\"?>", "");
                    Xml += "</soap:Body></soap:Envelope>";
                    request = Xml;
                } else {
                    String Xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
                            "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">" +
                            "<soap:Body><Request xmlns=\"http://tempuri.org/\"><requestXML>" + "<![CDATA[";
                    Xml += request.replace("<?xml version=\"1.0\" encoding=\"UTF-8\"?>", "");
                    Xml += "]]></requestXML></Request></soap:Body></soap:Envelope>";
                    request = Xml;
                    conn.setRequestProperty("SOAPAction", "http://tempuri.org/Request");
                }
            }
            //2.4.keep-alive 发出的请求建议服务器端保留连接,这样下次向同一个服务器发请求时可以走同一个连接
            conn.setRequestProperty("connection", "Keep-Alive");
            //2.5.设置请求的浏览器相关属性
            conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            //2.6.设定接受的返回流字节码为UTF-8
            conn.setRequestProperty("Accept-Charset", "utf-8");
            conn.setRequestProperty("Charset", "utf-8");
            //2.7.设置超时时间,如果未设置超时时间,但是访问超时了就会一直卡在这里
            conn.setConnectTimeout(50000 * 12);//
            conn.setReadTimeout(50000 * 12);//
            //2.8.设置是否向HttpURLConnection输出,默认为false,发送post请求的不啊必须设置为true
            conn.setDoOutput(true);
            //2.9.设置是否从httpUrlConnection读入,默认为true,不设置也可以
            conn.setDoInput(true);
            /* 三.处理输入请求 ,设置请求正文,即要提交的数据*/
            out = new PrintWriter(new OutputStreamWriter(conn.getOutputStream(), "utf-8"));
            out.print(request);// 写入参数到请求中         
            out.flush(); //flush输出流的缓冲
           /*四:处理输出接口,远程对象变为可用*/
            in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8"));
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
        } catch (Exception e) {

            result = e.getMessage();
            e.printStackTrace();
        }
        return result;
    }

总结:

  1. URLConnection的connect()函数,实际上只是建立了一个与服务器的tcp连接,并没有实际发送http请求。
    无论是post还是get,http请求实际上直到HttpURLConnection的getInputStream()这个函数里面才正式发送出去。

  2. 在用POST方式发送URL请求时,URL请求参数的设定顺序是重中之重, 
    对connection对象的处理设置参数和一般请求属性和写入提交数据都必须要在connect()函数执行之前完成。对outputStream的写提交数据操作,必须要在inputStream的读操作之前。这些顺序实际上是由http请求的格式决定的。

  3. http请求实际上由两部分组成,一个是http头,所有关于此次http请求的配置都在http头里面定义,一个是正文content。connect()函数会根据HttpURLConnection对象的配置值生成http头部信息,因此在调用connect函数之前,就必须把所有的配置准备好。

  4. 在http头后面紧跟着的是http请求的正文,正文的内容是通过outputStream流写入的, 
    实际上outputStream不是一个网络流,充其量是个字符串流,往里面写入的东西不会立即发送到网络,而是存在于内存缓冲区中,待outputStream流关闭时,根据输入的内容生成http正文。至此,http请求的东西已经全部准备就绪。在getInputStream()函数调用的时候,就会把准备好的http请求正式发送到服务器了,然后返回一个输入流,用于读取服务器对于此次http请求的返回信息。由于http请求在getInputStream的时候已经发送出去了(包括http头和正文),因此在getInputStream()函数之后对connection对象进行设置(对http头的信息进行修改)或者写入outputStream(对正文进行修改)都是没有意义的了,执行这些操作会导致异常的发生。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值