URL编码及Java发起URL请求的问题详解

前言

今天我们来讲一下URL编码(同时被称为Percent-encode,百分比编码)。虽然它相对简单,但是非常的重要,至于为什么,通过我后面的介绍也许你就会明白。
虽然叫做URLEncode,但是它普遍用于“统一资源标识符(URI)”中,熟悉HTTP协议的同学应该知道,URL是URI的一部分。同时,URL编码还被用在html页面的表单提交上,通常HTTP协议会先将表单数据进行编码,然后再执行POST或者GET请求。
实际上我们每天都能够看到URL编码和解码,可能你没有发现而已。最简单的一个例子,我们知道表单在传输数据的时候是采用键值对的方式,即key-value,拼装参数的时候就是key1=value1&key2=value2。如果我们的key1=1&value(这是一个整体),然后key2=value2,如果不进行编码,传递的时候就成了key1=1&value&key2=value2,看到了吧,这就会造成语义上的歧义,我们在接收表单数据的时候就无法正常接收。当然,作为普通用户来说,一般不会遇到这个问题,那是因为开发人员已经处理过了,但是我们就是这些开发人员,所以必须了解。
为了避免出现这种歧义,我们应该怎么做呢?

URL字符类型

我们在说解决方案之前,还是先来看看W3C是如何规定URL的格式的。
像“&”这种字符,在URL中被作为保留的编码,和java中的关键字保留是一样的,这些我们都是不能直接使用的,想要使用必须转义。这种保留符号还有很多,下表中列出的就是这些保留字符。

在这里插入图片描述

如果需要在值中用到这些保留字符,则需要将这些值进行百分转换,这也是百分比编码的由来。除去保留字符,还有空格字符也需要转义,转义后为“%20”。

在这里插入图片描述

当然,在一些特定的场合,比如后端需要解析前端经过编码后的值时,如果传递中文,就需要将中文编码。关于这一点,我会在代码中说明。

代码转义

首先,我们肯定不能在传值的时候去看转义后的字符,这简直太麻烦了,好在JDK给我们提供了一个URLEncoder类,让我们用来URL编码。
正常的后端代码是不会用到URL编码的,直接接收参数操作就好了,但是特殊的情况,如发起网络连接的时候,添加参数,就需要用到编码。多用于网络爬虫一类的应用程序(想起了当年用网络爬虫爬取内涵图的经历,但是那个网站做了反爬虫,现在没法用了。。)

最后,我给出一个URLConnection类,拼装参数,然后发起连接即可。

/**
 * 发起url连接工具类
 *
 * @author 言立慧
 * @date 2018/9/9 10:43
 */
public class UrlConnectionUtil {
    public static void getConnection(String domain, String lastUrl, HashMap<String, Object> params) {
        StringBuffer bufferUrl = new StringBuffer();
        // 拼装ip地址
        bufferUrl.append(domain);
        bufferUrl.append("/");
        bufferUrl.append(lastUrl);
        bufferUrl.append("?");
        // 拼装各种参数,使用迭代器进行遍历
        Iterator it = params.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry entry = (Map.Entry) it.next();
            String key = entry.getKey().toString();
            String value = entry.getValue().toString();
            bufferUrl.append(key);
            bufferUrl.append("=");
            // 如果需要对中文进行转义的话,只需要写成:
            // bufferUrl.append(URLEncoder.encode(value,"UTF-8"));
            bufferUrl.append(value);
            bufferUrl.append("&");
        }
        bufferUrl.delete(bufferUrl.length() - 1, bufferUrl.length());
        System.out.println(bufferUrl.toString());
        // 尝试建立连接
        try {
            URL url = new URL(bufferUrl.toString());
            //打开连接
            URLConnection urlConnection = url.openConnection();
            //发送连接请求
            urlConnection.connect();
            //获取服务器响应
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream(),
                    "utf-8"));
            String lineData = bufferedReader.readLine();
            System.out.println(lineData);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    public static void main(String[] args) {
        HashMap<String, Object> params = new HashMap<>();
        params.put("gender",1);
        getConnection("http://192.168.43.170", "history", params);
    }
}

这个类其实非常简单,getConnection方法用于拼装参数并发起连接,main函数中是测试代码。这个代码是我做接口测试用的,仅供参考。
至于参数拼装的问题,我使用了一个HashMap<String, Object> params = new HashMap<>();,有了这个东西,封装参数还不是小意思。

结语

感谢您的阅读,如果你喜欢我的文章,欢迎留言、点赞。也欢迎你关注我的微信公众号,最高权限比特流,回复java领取学习礼包、视频资料。

发表评论

电子邮件地址不会被公开。 必填项已用*标注