javaurl参数编码格式_Java在web页⾯上的编码解码处理及中
⽂URL乱码解决
这篇⽂章主要介绍了Java在web页⾯上的编码解码处理及中⽂URL乱码解决,⽂中所介绍的两种使⽤过滤器解决中⽂链接乱码的⽅法⾮常有效,需要的朋友可以参考下
编码&解码 通过下图我们可以了解在javaWeb中有哪些地⽅有转码:
⽤户想服务器发送⼀个HTTP请求,需要编码的地⽅有url、cookie、parameter,经过编码后服务器接受HTTP请求,解析HTTP请求,然后对url、cookie、parameter进⾏解码。在服务器进⾏业务逻辑处理过程中可能需要读取数据库、本地⽂件或者⽹络中的其他⽂件等等,这些过程都需要进⾏编码解码。当处
理完成后,服务器将数据进⾏编码后发送给客户端,浏览器经过解码后显⽰给⽤户。在这个整个过程中涉及的编码解码的地⽅较多,其中最容易出现乱码的位置就在于服务器与客户端进⾏交互的过程。
上⾯整个过程可以概括成这样,页⾯编码数据传递给服务器,服务器对获得的数据进⾏解码操作,经过⼀番业务逻辑处理后将最终结果编码处理后传递给客户端,客户端解码展⽰给⽤户。所以下⾯我就请求对javaweb的编码&解码进⾏阐述。
请求
客户端想服务器发送请求⽆⾮就通过四中情况:
1、URL⽅式直接访问。
2、页⾯链接。
3、表单get提交
4、表单post提交
URL⽅式
对于URL,如果该URL中全部都是英⽂的那倒是没有什么问题,如果有中⽂就要涉及到编码了。如何编码?根据什么规则来编码?⼜如何来解码呢?下⾯将⼀⼀解答!⾸先看URL的组成部分:
在这URL中浏览器将会对path和parameter进⾏编码操作。为了更好地解释编码过程,使⽤如下URL
将以上地址输⼊到浏览器URL输⼊框中,通过查看http 报⽂头信息我们可以看到浏览器是如何进⾏编码的。下⾯是IE、Firefox、Chrome 三个浏览器的编码情况:
可以看到各⼤浏览器对“我是”的编码情况如下:path部分
Query String
Firefox
E6 88 91 E6 98 AF
E6 88 91 E6 98 AF
Chrome
E6 88 91 E6 98 AF
E6 88 91 E6 98 AF
IE
E6 88 91 E6 98 AF
CE D2 CA C7
查阅上篇博客的编码可知对于path部分Firefox、chrome、IE都是采⽤UTF-8编码格式,对于Query String部分Firefox、chrome采⽤UTF-8,IE采⽤GBK。⾄于为什么会加上%,这是因为URL的编码规范规定浏览器将ASCII字符⾮ ASCII 字符按照某种编码格式编码成 16进制数字然后将每个 16 进制表⽰的字节前加上“%”。
当然对于不同的浏览器,相同浏览器不同版本,不同的操作系统等环境都会导致编码结果不同,上表某⼀种情况,对于URL编码规则下任何结论都是过早的。由于各⼤浏览器、各个操作系统对URL的URI、QueryString编码都可能存在不同,这样对服务器的解码势必会造成很⼤的困扰,下⾯我们将已tomcat,看tomcat是如何对URL进⾏解码操作的。
解析请求的 URL 是在 HTTP11.InternalInputBuffer 的 parseRequestLine ⽅法中,这个⽅法把传过来的 URL 的byte[] 设置到 Request 的相应的属性中。这⾥的 URL 仍然是 byte 格式,转成 char 是在
org.tor.CoyoteAdapter 的 convertURI ⽅法中完成的:
protected void convertURI(MessageBytes uri, Request request)
throws Exception {
ByteChunk bc = ByteChunk();
int length = bc.getLength();
CharChunk cc = CharChunk();
cc.allocate(length, -1);
String enc = URIEncoding(); //获取URI解码集
if (enc != null) {
B2CConverter conv = URIConverter();
try {
if (conv == null) {
conv = new B2CConverter(enc);
在线url网址编码解码
request.setURIConverter(conv);
}
} catch (IOException e) {...}
if (conv != null) {
try {
uri.Buffer(), cc.getStart(), cc.getLength());
return;
} catch (IOException e) {...}
}
}
// Default encoding: fast conversion
byte[] bbuf = bc.getBuffer();
char[] cbuf = cc.getBuffer();
int start = bc.getStart();
for (int i = 0; i < length; i++) {
cbuf[i] = (char) (bbuf[i + start] & 0xff);
}
uri.setChars(cbuf, 0, length);
}
从上⾯的代码可知,对URI的解码操作是⾸先获取Connector的解码集,该配置在l中
如果没有定义则会采⽤默认编码ISO-8859-1来解析。
对于Query String部分,我们知道⽆论我们是通过get⽅式还是POST⽅式提交,所有的参数都是保存在Parameters,然后我们通过Parameter,解码⼯作就是在第⼀次调⽤getParameter⽅法时进⾏的。在getParameter⽅法内部它调⽤
org.tor.Request 的 parseParameters ⽅法,这个⽅法将会对传递的参数进⾏解码。下⾯代码只是parseParameters⽅法的⼀部分:
//获取编码
String enc = getCharacterEncoding();
//获取ContentType 中定义的 Charset
boolean useBodyEncodingForURI = UseBodyEncodingForURI();
if (enc != null) { //如果设置编码不为空,则设置编码为enc
parameters.setEncoding(enc);
if (useBodyEncodingForURI) { //如果设置了Chartset,则设置queryString的解码为ChartSet
parameters.setQueryStringEncoding(enc);
}
} else { //设置默认解码⽅式
parameters.setEncoding(Constants.DEFAULT_CHARACTER_ENCODING);
if (useBodyEncodingForURI) {
parameters.setQueryStringEncoding(Constants.DEFAULT_CHARACTER_ENCODING);
}
}
从上⾯代码可以看出对query String的解码格式要么采⽤设置的ChartSet要么采⽤默认的解码格式ISO-8859-1。注意这个设置的ChartSet是在 http Header中定义的ContentType,同时如果我们需要改指定属性⽣效,还需要进⾏如下配置:
上⾯部分详细介绍了URL⽅式请求的编码解码过程。其实对于我们⽽⾔,我们更多的⽅式是通过表单的形式来提交。
表单GET
我们知道通过URL⽅式提交数据是很容易产⽣乱码问题的,所以我们更加倾向于通过表单形式。当⽤户点击submit提交表单时,浏览器会更加设定的编码来编码数据传递给服务器。通过GET⽅式提交的数据都是拼接在URL后⾯(可以当做query String??)来提交的,所以tomcat服务器在进⾏解码过程中URIEncoding就起到作⽤了。tomcat服务器会根据设置的URIEncoding来进⾏解码,如果没有设置则会使⽤默认的ISO-8859-1来解码。假如我们在页⾯将编码设置为UTF-8,⽽URIEncoding设置的不是或者没有设置,那么服务器进⾏解码时就会产⽣乱码。这个时候我们⼀般可以通过new Parameter("name").getBytes("iso-8859-1"),"utf-8") 的形式来获取正确数据。
表单POST
对于POST⽅式,它采⽤的编码也是由页⾯来决定的即contentType。当我通过点击页⾯的submit按钮来提交表单时,浏览器⾸先会根据ontentType的charset编码格式来对POST表单的参数进⾏编码然后提交给服务器,在服务器端同样也是⽤contentType中设置的字符集来进⾏解码(这⾥与get⽅式就不同了),这就是通过POST表单提交的参数⼀般⽽⾔都不会出现乱码问题。当然这个字符集编码我们是可以⾃⼰设定的:request.setCharacterEncoding(charset) 。
解决URL中⽂乱码问题我们主要通过两种形式提交向服务器发送请求:URL、表单。⽽表单形式⼀般都不会出现乱码问题,乱码问题主要是在URL上⾯。通过前⾯⼏篇博客的介绍我们知道URL向服务器发送请求编码过程实在是实在太混乱了。不同的操作系统、不同的浏览器、不同的⽹页字符集,将导致完全不同的编码结果。如果程序员要把每⼀种结果都考虑进去,是不是太恐怖了?有没有办法,能够保证客户端只⽤⼀种编码⽅法向服务器发出请求?
有!这⾥我主要提供以下⼏种⽅法
javascript 使⽤javascript编码不给浏览器插⼿的机会,编码之后再向服务器发送请求,然后在服务器中解码。在掌握该⽅法的时候,我们需要料及javascript编码的三个⽅法:escape()、encodeURI()、encodeURIComponent()。
escape 采⽤SIO Latin字符集对指定的字符串进⾏编码。所有⾮ASCII字符都会被编码为%xx格式的字
符串,其中xx表⽰该字符在字符集中所对应的16进制数字。例如,格式对应的编码为%20。它对应的解码⽅法为unescape()。
事实上escape()不能直接⽤于URL编码,它的真正作⽤是返回⼀个字符的Unicode编码值。⽐如上⾯“我是cm”的结果
为%u6211%u662Fcm,其中“我”对应的编码为6211,“是”的编码为662F,“cm”编码为cm。
注意,escape()不对"+"编码。但是我们知道,⽹页在提交表单的时候,如果有空格,则会被转化为+字符。服务器处理数据的时候,会把+号处理成空格。所以,使⽤的时候要⼩⼼。
encodeURI 对整个URL进⾏编码,它采⽤的是UTF-8格式输出编码后的字符串。不过encodeURI除了ASCII编码外对于⼀些特殊的字符也不会进⾏编码如:! @ # $& * ( ) = : / ; ? + '。
encodeURIComponent 把URI字符串采⽤UTF-8编码格式转化成escape格式的字符串。相对于encodeURI,encodeURIComponent会更加强⼤,它会对那些在encodeURI()中不被编码的符号(; / ? : @ & = + $ , #)统统会被编码。但是encodeURIComponent只会对URL 的组成部分进⾏个别编码,⽽不⽤于对整个URL进⾏编码。对应解码函数⽅法decodeURIComponent。
当然我们⼀般都是使⽤encodeURI⽅来进⾏编码操作。所谓的javascript两次编码后台两次解码就是使⽤该⽅法。javascript解决该问题有⼀次转码、两次转码两种解决⽅法。
⼀次转码
javascript转码:
var url = '/ShowMoblieQRCode.servlet?name=我是cm';
window.location.href = encodeURI(url);
后台处理:
String name = Parameter("name");
System.out.println("前台传⼊参数:" + name);
name = new Bytes("ISO-8859-1"),"UTF-8");
System.out.println("经过解码后参数:" + name);
输出结果:
前台传⼊参数:cm
经过解码后参数:我是cm
⼆次转码
javascript
var url = '/ShowMoblieQRCode.servlet?name=我是cm';
window.location.href = encodeURI(encodeURI(url));

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。