Java Web乱码分析及解决方式(一)——GET请求乱码

Java Web乱码分析及解决方式(一)——GET请求乱码

大家好,又见面了,我是全栈君。

引言:

    在进行Web開始时。乱码是我们最常常遇到也是最主要的问题。有经验的程序员非常easy能解决,刚開始学习的人则easy被泥潭困住。

并且非常多时候。我们即使攻克了乱码问题也是不明就里。往往云里雾里。

    事实上乱码问题非常easy,就是client和server使用了不一样的字符集导致的。也就是我们发送文件时用的字符编码和解析文件的编码不一致。所以仅仅要搞清楚了我们的文件是怎么被编码和解码的解决乱码就非常easy了。分析乱码,我们从请求乱码和响应乱码来分析,请求乱码又须要依据GET和POST来单独分析。

 

请求乱码——GET

    请求的编码是由浏览器发出的。使用GET方法请求server信息时。依据HTTP协议规定,Request包是没有请求体的(也就是Request Body不存在)。所以我们仅仅能把请求參数放在URL中。因此使用GET方式与server通信,编码方面我们关心的重点是浏览器对URL的编码方式,和server对URL的解码过程。

关于URL

    URL是我们常常接触并不是常简单的一种技术,URL技术简单到它事实上就是一个字符串。

实际上URL的结构是非常复杂的,仅仅只是通常上使用方法比較简单而已。关于URL的具体介绍能够參考以下的文章:

我是传送门!。!大笑

Java Web乱码分析及解决方式(一)——GET请求乱码

    URL的规范定义在RFC 1738文档中。通过URL我们能够获得通信协议、主机域名、处理port、应用路径、路径參数、查询參数、页面片段等信息。

比方:

    http://user:pass@example.com/a/b;q=1/c?d=2;sessionid=qewfewrwer#2

    依据上面的URL。我们能够得到例如以下信息:

Part

Data

serverAPI

Scheme

http

用req.getScheme

user

user

囧,不知道

pass

pass

囧,不知道

host address

example.com

req.getServerName

port

80

req.getServerPort

path

/a/b;q=1/c

req.getContextPath

query parameters

d=2;sessionid=qwefewrwer

req.getQueryString

fragement

2

 

 

    开发时,我们经经常使用到的就是path和query parameters。这两个參数,剩下的參数使用的比較少。只是在RESTful API中,像路径參数的信息可能会用到。fragement用来在页面内进行锚点定位。(已经非经常见了)


浏览器对Path部分的编码

    path信息被用来匹配处理路径。一般设计上非常少在path中包含中文參数。RFC文档对于path的编码也没有明白规定。可是据其它文章的介绍。浏览器对Path的编码一般都会採用UTF-8编码,最新的URI标准已经定义了URI的编码採用UTF-8编码。

    定义:简单说path部分就是应用路径部分,就是URL去掉协议、域名、port和查询信息剩下的部分。


server对Path部分的解码:(三种方案)

    通常上,我们的请求都会首先发给Web容器(以下以Tomcat为例),URL也会被Web容器解码,对于Tomcat容器来说,我们能够在conf/server.xml的connector标签中添加URL解码參数,默认容器对URL的使用ISO-8859-1解码。

<Connector port="8080" protocol="HTTP/1.1"
         connectionTimeout="20000"
         redirectPort="8443" />

    上面的是Tomcat的默认设定,能够给标签加入URIEncoding属性来指定URL的解码方案。PS:标签写法是URI不是URL)

    假设不想使用这样的硬解码方案。还能够指定还有一个属性:useBodyEncodingForURI,这个属性用来告诉Web容器。假设request指定了解码方案,则使用request.setCharacterEncoding指定的编码来解码URL。

另外一种方案没有经过測试。假设有须要能够尝试下。

具体资料能够參考以下的Tomcat官方文档:

http://wiki.apache.org/tomcat/FAQ/CharacterEncoding#Q2

    此外。假设不想改动容器的全局配置。毕竟有时候容器里可能不止我们一个应用,那么我们还能够採用以下的做法来提取參数

String path = req.getServerPath();//自己手动提取,不适合配合框架
path = new String(path.getBytes(“ISO8859-1”,”UTF-8”));//又一次拼装


    
上面的做法。我们要确定Web容器对URL的解码用的是ISO8859-1,由于不排除其它人改动了容器配置或容器配置本身比較奇葩的可能。

 

浏览器对QueryParameter的编码

    查询參数和Path是不一样的,缺少查询參数,web容器是能够定位到我们的处理程序的,可是缺少path就不行。

另外,path和查询參数的保留字符是不一样的。

    定义:简单来说查询參数就是path后面紧跟的?后面的部分,用&来连接各个查询參数。

    因为Path和查询參数的不同,有些浏览器对查询參数的编码和path部分的编码是不一致的。

详细使用怎么编码的比較混乱。能够參考下以下的文章:

又一个传送门,啦啦啦!

安静

    依据上面的文章总结的规律:

    (1)Path部分或者说除查询參数外的URL部分。各浏览器用UTF-8编码;

    (2)查询參数,各浏览器依据操作系统编码决定;

    上面的文章比較老了,规律可能不有用了,可是也能说明一定问题。对于某些文章说的,查询參数会依据页面编码来决定,我没有做实验。可是这样的结论肯定是片面的。原因例如以下:

    页面的meta參数是用来向浏览器说明页面编码的,其次。在使用POST Method发送数据的时候,浏览器会依据meta的编码来编码Request Body。而Get方式。我们在没有页面的时候也能够发起。所以浏览器根本找不到Meta标签,也就没法參考页面编码。

    浏览器对查询參数究竟使用哪种方式编码的,我没有找到专业、权威、可信的答案,可是我觉得这个还是详细情况详细分析。做个小实验即可了。

毕竟时代在进步。厂商们统一使用UTF-8编码的可能性比較大。并且后面有不依赖浏览器编码的解决方式。

 

server对QueryParameter的解码

    查询參数也是URL的一部分。所以Web容器对查询參数的解码比較明智,解码和path使用的是一样的方案的编码,所以解决方式也是一样的。


出现乱码:

    在处理查询參数时,我们经常使用req.getParameters();来获取某个參数。这种方法背后非常少有人关心它的工作原理。并且也不是必需。

这一部分是最easy出现乱码的,毕竟它里面的參数可能是用户输入的,并非我们设计的。

在GET方式下,出现这样的乱码不要慌张,首先我们要分析出,浏览器对查询參数究竟採用了哪种编码。

方法简单(也复杂),chrome下F12打开开发人员工具

Java Web乱码分析及解决方式(一)——GET请求乱码

Java Web乱码分析及解决方式(一)——GET请求乱码

   找到network标签,能够看到Request URL中显示的是k= %E4%B8%AD%E5%9B%BD,把%去掉,能够得到6个16进制数,百度下unicode码表。能够看到他们正好是“中”和“国”的unicode编码。所以能够推測浏览器使用的是UTF-8编码。这样的推断方式须要对字符编码比較熟悉。只是也不算非常难,找点字符编码的文章学学非常easy就能看出规律来。

    PS:不要通过浏览器的地址栏看URL编码,非常多浏览器的地址栏会对URL解码显示。

    之后,server端,首先确定下。你的Web容器对URL使用的解码方案,然后对应的选择String(param.getBytes(“ISO8895-1”,”UTF-8”))或者是useBodyEncodingForURI、URIEncoding方案就好了。


总结:

       使用GET方式出现乱码时,最基本的是找出浏览器对URL的编码方式,假设使用JS编程时。在浏览器能够使用encodeURIComponent函数对中文參数进行编码后再拼装參数。Java端使用URLDecoder.decode方法解码。JS端要进行两次编码,否则第一次的URL编码会被Web容器解码,获取的參数仍有可能是乱码。能够參考:

传送。!!!!

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/115225.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 15种手机游戏引擎和开发工具介绍

    15种手机游戏引擎和开发工具介绍工欲善其事,必先利其器。对移动游戏开发者来说,高效实用的开发工具必不可少。近日,英国著名产业杂志《Develop》刊出了一篇文章,作者艾伦·李在文中推荐了15种移动游戏开发工具,从游戏引擎,到音效制作、推广等工具都有涉及。以下为原文主要内容编译。引擎和移动开发工具包Marmalade简介:Marmalade被很多人认为是跨平台制作C++游戏的最佳平台。通过MarmaladeSDK,开发者可以在单一的Marmalade项目文件夹中打开Xcode或VisualStudio,将

    2022年5月22日
    138
  • windebug调试方法_java怎么远程调试

    windebug调试方法_java怎么远程调试关于WCF的调试,MSDN给出如下说明,可能是由于我的水平问题,个人无法完全看懂,所以自己总结了一点WCF的调试技巧。仅供参考。如何开始调试WCF服务: 通常WCF可以部署成Windowsservice和Webservice。1.对于WebService通常后缀都是*.svc对于这类我通常有2种方式对其调试a.      新建一个控制台程序,通过AddwebR

    2025年6月20日
    5
  • varchar2 类型「建议收藏」

    varchar2 类型「建议收藏」1、varchar2在数据库表中的最大长度是4000bytesorcharacter,在oracleplsqlvarchar2最大支持长度为32767个字节SQL>declare 2       v_varvarchar2(32767); 3     begin 4       null; 5     end; 6     /

    2022年6月24日
    33
  • NSSM使用说明

    NSSM使用说明1、说明NSSM是一个服务封装程序,它可以将普通exe程序封装成服务,使之像windows服务一样运行。同类型的工具还有微软自己的srvany,不过nssm更加简单易用,并且功能强大。它的特点如下:支持普通exe程序(控制台程序或者带界面的Windows程序都可以)安装简单,修改方便可以重定向输出(并且支持Rotation)可以自动守护封装了的…

    2025年8月14日
    3
  • SSDP协议_固态硬盘两种协议

    SSDP协议_固态硬盘两种协议SSDP,即简单服务发现协议(SSDP,SimpleServiceDiscoveryProtocol),是一种应用层协议,是构成通用即插即用(UPnP)技术的核心协议之一。 实现简单服务发现协议是在HTTPU和HTTPMU的基础上实现的协议。按照协议的规定,当一个控制点(客户端)接入网络的时候,它可以向一个特定的多播地址的SSDP端口使用M-SEARCH方法发送“ssdp:…

    2022年10月11日
    2
  • 如何创建HTML表单?html表单代码怎么写[通俗易懂]

    如何创建HTML表单?html表单代码怎么写[通俗易懂]html表单代码是什么?如何创建HTML表单?这些对于新手会感到陌生,下面我们为你总结一下html表单代码怎么写?以及html表单的创建?一:构建表单标签在文本编辑器中打开HTML文档,必须在<form>和</form>标签中键入HTML表单的内容。这些标签充当表单的容器,就像<div></div>容器标签一样。您可以在<form></form>标签内使用CSS或js,使您的表单看起来比较美观。2.打开<form&gt

    2022年8月11日
    5

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号