在网络请求中如果URL中存在特殊字符会报语法错误,比如“java.net.URISyntaxException: Malformed escape pair at index”。这是因为在你的URL中包含了特殊字符,因为只有字母和数字[0-9a-zA-Z]、一些特殊符号“$-_.+!*’(),”[不包括双引号]、以及某些保留字,才可以不经过编码直接用于URL。

url中的特殊字符

在URL参数中的特殊字符需要进行编码后传递,编码规则是“%+字符的ASCII码十六进制”,对应下表

特殊字符 编码
空格 %20
" %22
# %23
% %25
& %26
( %28
) %29
+ %2B
, %2C
/ %2F
: %3A
; %3B
< %3C
= %3D
> %3E
? %3F
@ %40
\ %5C
竖线 %7C

java中对含有特殊字符的URL参数编码方法

在java中提供了api对URL中的特殊字符编码
URLEncoder.encode(paramString, “utf-8”)
如果需求是存在一个URL,并且URL参数中存在特殊字符,需要对该URL发送get请求,那么就需要先将这个URL的参数部分进行编码,那么URL的参数部分应该如何拆分出来,我们先来了解一下URL的结构。

protocol(协议)

指定使用的传输协议,下表列出 protocol 属性的有效方案名称。 最常用的是HTTP协议,它也是目前WWW中应用最广的协议。
file 资源是本地计算机上的文件。格式file:///,注意后边应是三个斜杠。
ftp 通过 FTP访问资源。格式 FTP://
gopher 通过 Gopher 协议访问该资源。
http 通过 HTTP 访问该资源。 格式 HTTP://
https 通过安全的 HTTPS 访问该资源。 格式 HTTPS://
mailto 资源为电子邮件地址,通过 SMTP 访问。 格式 mailto:
MMS 通过 支持MMS(流媒体)协议的播放该资源。(代表软件:Windows Media Player)格式 MMS://
ed2k 通过 支持ed2k(专用下载链接)协议的P2P软件访问该资源。(代表软件:电驴) 格式 ed2k://
Flashget 通过 支持Flashget:(专用下载链接)协议的P2P软件访问该资源。(代表软件:快车) 格式 Flashget://
thunder 通过 支持thunder(专用下载链接)协议的P2P软件访问该资源。(代表软件:迅雷) 格式 thunder://
news 通过 NNTP 访问该资源。

hostname(主机名)

是指存放资源的服务器的域名系统(DNS) 主机名或 IP 地址。有时,在主机名前也可以包含连接到服务器所需的用户名和密码(格式:username:password@hostname)。

port(端口号)

整数,可选,省略时使用方案的默认端口,各种传输协议都有默认的端口号,如http的默认端口为80。如果输入时省略,则使用默认端口号。有时候出于安全或其他考虑,可以在服务器上对端口进行重定义,即采用非标准端口号,此时,URL中就不能省略端口号这一项。

path(路径)

由零或多个“/”符号隔开的字符串,一般用来表示主机上的一个目录或文件地址。

parameters(参数)

这是用于指定特殊参数的可选项。

query(查询)

可选,用于给动态网页(如使用CGI、ISAPI、PHP/JSP/ASP/ASP。NET等技术制作的网页)传递参数,可有多个参数,用“&”符号隔开,每个参数的名和值用“=”符号隔开。

fragment(信息片断)

字符串,用于指定网络资源中的片断。例如一个网页中有多个名词解释,可使用fragment直接定位到某一名词解释。(from 百度百科)
举个栗子
http: // 192.2.111.33:80/app/index?type=1&name=%%admin

protocol hostname port path query
http:// 192.2.111.33 80 /app/index type=1&name=%%admin

java中如果请求参数部分存在特殊字符,那么应该怎么处理:
拆分参数部分–>转义编码–>组装URL
1.将请求参数分割

  int index = url.indexOf("?");  if (index < 0) return url;  String query = url.substring(0, index);  String params = url.substring(index + 1);

2.将params转化成数组

  String[] param_pairs = params.split("&");

param_pairs 数组是这样的[“type=1”,“name=%%admin”]我们需要得到参数的value部分进行编码,所以还要继续把value拆分出来

  int length = param_pairs.length;  for (int i = 0; i < length; i++) {          int pos = param_pairs[i].indexOf("=");          if (pos == -1) continue;          String name = param_pairs[i].substring(0, pos);          String value = param_pairs[i].substring(pos + 1);      }

3.用URLEncoder.encode()函数进行参数部分的编码

  int length = param_pairs.length;  for (int i = 0; i < length; i++) {          int pos = param_pairs[i].indexOf("=");          if (pos == -1) continue;          String name = param_pairs[i].substring(0, pos);          String value = param_pairs[i].substring(pos + 1);          value = URLEncoder.encode(value, "utf-8");          map.put(name, value);      }

4.URL的重新组装
以上已经将参数部分转化称map形式,那么重组只需要便利map取出name和value并以“=”连接,每组间以“&”连接就得到了参数部分,再以“?”连接上面的query和新的参数部分。
完整代码:

public static String getUrl(String url) {     int index = url.indexOf("?");     if (index < 0)         return url;     String query = url.substring(0, index);     String params = url.substring(index + 1);     Map map = new HashMap();     String[] param_pairs = params.split("&");     try {         for (int i = 0; i < param_pairs.length; i++) {             int pos = param_pairs[i].indexOf("=");             if (pos == -1)                 continue;             String name = param_pairs[i].substring(0, pos);             String value = param_pairs[i].substring(pos + 1);             value = URLEncoder.encode(value, "utf-8");             map.put(name, value);         }     } catch (UnsupportedEncodingException e) {         e.printStackTrace();     }     StringBuilder encodeParams = new StringBuilder();     java.util.Map.Entry entry;     for (Iterator iterator = map.entrySet().iterator(); iterator.hasNext(); ) {         entry = (java.util.Map.Entry) iterator.next();         encodeParams.append(entry.getKey().toString()).append("=")                 .append(null == entry.getValue() ? "" : entry.getValue().toString())                 .append(iterator.hasNext() ? "&" : "");     }     return query + "?" + encodeParams.toString(); }

转化结果
http:// 192.2.111.33:80/app/index?type=1&name=%25%25admin

如有不对,欢迎指正。

更多相关文章

  1. Android(安卓)注解
  2. Android(安卓)自定义View 性能分析学习
  3. Android(安卓)JNI打印Log
  4. Android定时器Timer.schedule
  5. AndroidStudio中的图片资源存放位置以及drawable文件夹的创建方
  6. Android(安卓)国际化以及屏幕适配
  7. vitamio简介.java
  8. Android资源优化
  9. 发邮件

随机推荐

  1. android 图片拖动简单例子
  2. Android(安卓)add external jar
  3. android修改默认桌面
  4. Android(安卓)开机启动程序
  5. Android(安卓)通知提示功能
  6. Android(安卓)UI界面之TableLayout
  7. Android_notification通知
  8. 关于iOS项目开发控制
  9. android.graphics.Canvas类详解
  10. Facebook Fresco体验 (一)