`
别惹Java
  • 浏览: 45685 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

关于javaWeb的编码问题

 
阅读更多

        用户从浏览器端发起一个 HTTP 请求,需要存在编码的地方是 URL、Cookie、Parameter。服务器端接受到 HTTP 请求后要解析 HTTP 协议,其中 URI、Cookie 和 POST 表单参数需要解码,服务器端可能还需要读取数据库中的数据,本地或网络中其它地方的文本文件,这些数据都可能存在编码问题,当 Servlet 处理完所有请求的数据后,需要将这些数据再编码通过 Socket 发送到用户请求的浏览器里,再经过浏览器解码成为文本。

一次 HTTP 请求的编码示例


URL 的几个组成部分


以下测试指定web服务器为Tomcat6.X,浏览器为IE8.X和chrome15.X

准备:
1.下面的汉字以“中”为例,分别对应的各种字符集的十六进制编码如下:

ISO-8859-1: 3f   (ISO-8859-1表示的西欧字母,其中并不包含汉字,这里的3f表示不存在的字符)
GB2312: d6d0
GBK: d6d0
UTF-16: feff4e2d
UTF-8: e4b8ad

2.关于Http请求头的查看
三大主流浏览器都有相应的工具
(1).IE下可以使用ieHTTPHeaders
    下载地址:http://www.blunck.info/iehttpheaders.html
(2).Firefox可以使用livehttpheaders
(3).chrome本身就自带开发人员工具,可以很方便的查看

3. 开发人员必须清楚的servlet规范:
(1) HttpServletRequest.setCharacterEncoding()方法 仅仅只适用于设置post提交的request body的编码而不是设置get方法提交的queryString的编码。该方法告诉应用服务器应该采用什么编码解析post传过来的内容。
(2) HttpServletRequest.getPathInfo()返回的结果是由Servlet服务器解码(decode)过的。
(3) HttpServletRequest.getRequestURI()返回的字符串没有被Servlet服务器decoded过。
(4) POST提交的数据是作为request body的一部分。
(5) 网页的Http头中ContentType("text/html; charset=GBK")的作用:
   (a) 告诉浏览器网页中数据是什么编码;
   (b) 表单提交时,通常浏览器会根据ContentType指定的charset对表单中的数据编码,然后发送给服务器的。

这里需要注意的是:这里所说的ContentType是指http头的ContentType,而不是在网页中meta中的ContentType。

1.在浏览器地址栏里输入:
http://localhost:8080/FileUpload/servlet/FileDownLoadServlet中?filename=中.jpg
在path info和Query String中都指定了汉字

IE8.x  Http请求消息


Chrome15.x  Http请求消息


   我们发现path info中都采用的是UTF-8编码,而Query String确采用了不同的编码方式:IE8.x采用的是GBK编码(这边没有正确的显示,至于是什么原因还不清楚),Chrome15.x采用的是UTF-8编码。

浏览器报:


根据上面的错误我们可以很明显的知道,Tomcat服务器没有正确的进行解码,从而找不到Servlet。


了解Tomcat的URL解码:

1.URL 的 URI 部分进行解码的字符集是在 connector 的 <Connector URIEncoding=”UTF-8”/> 中定义的,如果没有定义,那么将以默认编码 ISO-8859-1 解析。所以如果有中文 URL 时最好把 URIEncoding 设置成 UTF-8 编码。
2.GET 方式 HTTP 请求的 QueryString 与 POST 方式 HTTP 请求的表单参数都是作为 Parameters 保存,都是通过 request.getParameter 获取参数值。对它们的解码是在 request.getParameter 方法第一次被调用时进行的。request.getParameter 方法被调用时将会调用 org.apache.catalina.connector.Request 的 parseParameters 方法。这个方法将会对 GET 和 POST 方式传递的参数进行解码。

结果:
    我们在Servlet的doGet方法中System.out.println(request.getParameter("filename"))
通过chrome访问的Servlet可以正确的显示汉字,而通过IE访问显示乱码
所有我们这里可以知道Tomcat对QueryString采取的解码方式是UTF-8,下面我们要确认的是Tomcat默认对QueryString采取的编码方式是UTF-8还是因为我们设置的URIEncoding=”UTF-8”?

通过这个实验来说明:首先删除server.xml中指定的URIEncoding=”UTF-8”
在浏览器中输入:
http://localhost:8080/FileUpload/servlet/FileDownLoadServlet?filename=中.jpg
结果:
在两个浏览器中都显示乱码,我们在增加两条输出语句:
new String(request.getParameter("filename").getBytes("ISO-8859-1"), "UTF-8");
new String(request.getParameter("filename").getBytes("ISO-8859-1"), "GBK");

IE在第二条输出语句中显示正确的汉字
Chrome在第一条输出语句总显示正确的汉字
结论:
   1.在IE中QueryString部分采用的默认编码方式是GBK
   2.Tomcat对QueryString的默认解码方式是ISO-8859-1
   3.URIEncoding参数提供了对path info和Query String 部分的解码方式

备注:
new String(request.getParameter("filename").getBytes("ISO-8859-1"), "UTF-8")语句可以获取正确的汉字,原因?


   ISO-8859-1 字符集的编码范围是 0000-00FF,正好和一个字节的编码范围相对应。这种特性保证了使用 ISO-8859-1 进行编码和解码可以保持编码数值“不变”。虽然中文字符在经过网络传输时,被错误地“拆”成了两个欧洲字符,但由于输出时也是用 ISO-8859-1,结果被“拆”开的中文字的两半又被合并在一起,从而又刚好组成了一个正确的汉字。虽然最终能取得正确的汉字,但是还是不建议用这种不正常的方式取得参数值,因为这中间增加了一次额外的编码与解码。



2.在已打开的网页上,直接用Get或Post方法发出HTTP请求

以html页面为例
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
作用1:告诉浏览器网页中数据是什么编码;
     2: 表单提交时,通常浏览器会根据ContentType指定的charset对表单中的数据编码,然后发送给服务器的。

IE8.X  http请求


Chrome15.x  Http请求



可以看到QueryString部分都采用了charset设置的UTF-8字符集进行编码
我们可以看看主流搜索引擎百度和Google

可以查看其html源码指定了charset为gb2312
<meta http-equiv="Content-Type" content="text/html;charset=gb2312">

<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
可以知道,百度默认使用的编码方式是gb2312,而Google默认是UTF-8

在jsp页面中还可以通过其他方式指定编码,和html页面charset效果一样的设置方式还有
contentType,response.setCharacterEncoding(),response.setContentType(),response.setHeader();
response.setContentType(),response.setHeader();优先级最好,其次是response.setCharacterEncoding();再者是<%@page contentType="text/html; chareset=gbk"%>,最后是<meta http-equiv="content-type"content="text/html; charset=gb2312" />


我们经常设置一个Filter,(此时我们设置前台页面的编码为UTF-8),
(1.并加上如下代码:
request.setCharacterEncoding("UTF-8");
chain.doFilter(request, response);

这样我们在Servlet输出参数:
1.System.out.println(request.getParameter("aa");
2.new String(request.getParameter("aa").getBytes("ISO-8859-1"), "UTF-8");
3.new String(request.getParameter("aa").getBytes("ISO-8859-1"), "GBK");

结果:
1正确显示中文,2、3显示乱码,原因:request.setCharacterEncoding对前台的数据进行了解码,所有我们在Servlet中获取参数时不需要再进行解码。
(2.加上如下代码:
request.getParameter("aa");
request.setCharacterEncoding("UTF-8");
chain.doFilter(request, response);

此时的结果是:
2正确显示中文,1、3显示乱码。
原因:前面已经提到” 解码是在 request.getParameter 方法第一次被调用时进行的”,并且此时我们没有在Tomcat中设置URIEncoding属性,默认的解码方式是ISO-8859-1.所以,在request.getParameter("aa");的时候是对UTF-8进行编码的中文用ISO-8859-1进行解码,所有是乱码,此时request.setCharacterEncoding("UTF-8")又对通过ISO-8859-1解码的字符用UTF-8进行解码,所有1结果是乱码。而2刚好可以正确的显示中文,其原因已经在上面解释过了。

总结:出现乱码问题主要是因为编码与解码的字符集不统一造成的,所以对于编码我们自己完全可以指定的我们应该尽量去指定,不要使用默认值,对于浏览器默认设置的我们完全可以动手查看它使用的默认字符集。
UTF-8 在编码效率上和编码安全性上做了平衡,是理想的中文编码方式


补充1:
我们发现不同的浏览器对QueryString采用了不同的编码方式,这就照成了我们服务器端需要对不同的情况进行讨论,其实我们这里可以采取另外一种方式,保证客户端只用一种编码方法向服务器发出请求。
使用Javascript先对URL编码,然后再向服务器提交,不要给浏览器插手的机会。因为Javascript的输出总是一致的,所以就保证了服务器得到的数据是格式统一的

Javascript语言用于编码的函数,一共有三个:
1.escape()虽然这个函数现在已经不提倡使用了,但是由于历史原因,很多地方还在使用它
escape()不能直接用于URL编码,它的真正作用是返回一个字符的Unicode编码值,对应的解码函数是unescape()
2. encodeURI()是Javascript中真正用来对URL编码的函数。
它着眼于对整个URL进行编码,因此除了常见的符号以外,对其他一些在网址中有特殊含义的符号“; / ? : @ & = + $ , #”,也不进行编码。编码后,它输出符号的utf-8形式,并且在每个字节前加上%它对应的解码函数是decodeURI()
3. encodeURIComponent()。与encodeURI()的区别是,它用于对URL的组成部分进行个别编码,而不用于对整个URL进行编码。因此,“; / ? : @ & = + $ , #”,这些在encodeURI()中不被编码的符号,在encodeURIComponent()中统统会被编码。至于具体的编码方法,两者是一样。

对应的在服务器端我们可以通过:
分别是:
URLDecoder.decode(encodeStr,"UTF-8")
URLEncoder.encode(rawStr, "GBK")


参考:http://www.ibm.com/developerworks/cn/java/j-lo-chinesecoding/
  • 大小: 10 KB
  • 大小: 55.6 KB
  • 大小: 1.1 KB
  • 大小: 1.6 KB
  • 大小: 16 KB
  • 大小: 26.5 KB
  • 大小: 1 KB
  • 大小: 1.5 KB
  • 大小: 73 KB
  • 大小: 58.4 KB
分享到:
评论

相关推荐

    ysoserial-master.zip

    ysoserial是一个用于生成利用不安全的Java对象反序列化的有效负载的概念验证工具。它包含一系列在常见Java库中发现的"gadget chains",可以在特定条件下利用执行不安全的反序列化操作的Java应用程序。ysoserial项目最初在2015年AppSecCali会议上提出,包含针对Apache Commons Collections(3.x和4.x版本)、Spring Beans/Core(4.x版本)和Groovy(2.3.x版本)的利用链

    zigbee CC2530无线自组网协议栈系统代码实现协调器与终端的TI Sensor实验和Monitor使用.zip

    1、嵌入式物联网单片机项目开发例程,简单、方便、好用,节省开发时间。 2、代码使用IAR软件开发,当前在CC2530上运行,如果是其他型号芯片,请自行移植。 3、软件下载时,请注意接上硬件,并确认烧录器连接正常。 4、有偿指导v:wulianjishu666; 5、如果接入其他传感器,请查看账号发布的其他资料。 6、单片机与模块的接线,在代码当中均有定义,请自行对照。 7、若硬件有差异,请根据自身情况调整代码,程序仅供参考学习。 8、代码有注释说明,请耐心阅读。 9、例程具有一定专业性,非专业人士请谨慎操作。

    YOLO算法-自卸卡车-挖掘机-轮式装载机数据集-2644张图像带标签-自卸卡车-挖掘机-轮式装载机.zip

    YOLO系列算法目标检测数据集,包含标签,可以直接训练模型和验证测试,数据集已经划分好,包含数据集配置文件data.yaml,适用yolov5,yolov8,yolov9,yolov7,yolov10,yolo11算法; 包含两种标签格:yolo格式(txt文件)和voc格式(xml文件),分别保存在两个文件夹中,文件名末尾是部分类别名称; yolo格式:<class> <x_center> <y_center> <width> <height>, 其中: <class> 是目标的类别索引(从0开始)。 <x_center> 和 <y_center> 是目标框中心点的x和y坐标,这些坐标是相对于图像宽度和高度的比例值,范围在0到1之间。 <width> 和 <height> 是目标框的宽度和高度,也是相对于图像宽度和高度的比例值; 【注】可以下拉页面,在资源详情处查看标签具体内容;

    Oracle10gDBA学习手册中文PDF清晰版最新版本

    **Oracle 10g DBA学习手册:安装Oracle和构建数据库** **目的:** 本章节旨在指导您完成Oracle数据库软件的安装和数据库的创建。您将通过Oracle Universal Installer (OUI)了解软件安装过程,并学习如何利用Database Configuration Assistant (DBCA)创建附加数据库。 **主题概览:** 1. 利用Oracle Universal Installer (OUI)安装软件 2. 利用Database Configuration Assistant (DBCA)创建数据库 **第2章:Oracle软件的安装与数据库构建** **Oracle Universal Installer (OUI)的运用:** Oracle Universal Installer (OUI)是一个图形用户界面(GUI)工具,它允许您查看、安装和卸载机器上的Oracle软件。通过OUI,您可以轻松地管理Oracle软件的安装和维护。 **安装步骤:** 以下是使用OUI安装Oracle软件并创建数据库的具体步骤:

    消防验收过程服务--现场记录表.doc

    消防验收过程服务--现场记录表.doc

    (4655036)数据库 管理与应用 期末考试题 数据库试题

    数据库管理\09-10年第1学期数据库期末考试试卷A(改卷参考).doc。内容来源于网络分享,如有侵权请联系我删除。另外如果没有积分的同学需要下载,请私信我。

    YOLO算法-瓶纸盒合并数据集-3161张图像带标签-纸张-纸箱-瓶子.zip

    YOLO系列算法目标检测数据集,包含标签,可以直接训练模型和验证测试,数据集已经划分好,包含数据集配置文件data.yaml,适用yolov5,yolov8,yolov9,yolov7,yolov10,yolo11算法; 包含两种标签格:yolo格式(txt文件)和voc格式(xml文件),分别保存在两个文件夹中,文件名末尾是部分类别名称; yolo格式:<class> <x_center> <y_center> <width> <height>, 其中: <class> 是目标的类别索引(从0开始)。 <x_center> 和 <y_center> 是目标框中心点的x和y坐标,这些坐标是相对于图像宽度和高度的比例值,范围在0到1之间。 <width> 和 <height> 是目标框的宽度和高度,也是相对于图像宽度和高度的比例值; 【注】可以下拉页面,在资源详情处查看标签具体内容;

    职业暴露后的处理流程.docx

    职业暴露后的处理流程.docx

    Java Web开发短消息系统

    Java Web开发短消息系统

    java毕设项目之ssm基于java和mysql的多角色学生管理系统+jsp(完整前后端+说明文档+mysql+lw).zip

    项目包含完整前后端源码和数据库文件 环境说明: 开发语言:Java 框架:ssm,mybatis JDK版本:JDK1.8 数据库:mysql 5.7 数据库工具:Navicat11 开发软件:eclipse/idea Maven包:Maven3.3 服务器:tomcat7

    批量导出多项目核心目录工具

    这是一款可以配置过滤目录及过滤的文件后缀的工具,并且支持多个项目同时输出导出,并过滤指定不需要导出的目录及文件后缀。 导出后将会保留原有的路径,并在新的文件夹中体现。

    【图像压缩】基于matlab GUI DCT图像压缩(含MAX MED MIN NONE)【含Matlab源码 9946期】.zip

    Matlab领域上传的视频均有对应的完整代码,皆可运行,亲测可用,适合小白; 1、代码压缩包内容 主函数:main.m; 调用函数:其他m文件;无需运行 运行结果效果图; 2、代码运行版本 Matlab 2019b;若运行有误,根据提示修改;若不会,私信博主; 3、运行操作步骤 步骤一:将所有文件放到Matlab的当前文件夹中; 步骤二:双击打开main.m文件; 步骤三:点击运行,等程序运行完得到结果; 4、仿真咨询 如需其他服务,可私信博主; 4.1 博客或资源的完整代码提供 4.2 期刊或参考文献复现 4.3 Matlab程序定制 4.4 科研合作

    YOLO算法-挖掘机与火焰数据集-7735张图像带标签-挖掘机.zip

    YOLO算法-挖掘机与火焰数据集-7735张图像带标签-挖掘机.zip

    操作系统实验 Ucore lab5

    操作系统实验 Ucore lab5

    IMG_5950.jpg

    IMG_5950.jpg

    竞选报价评分表.docx

    竞选报价评分表.docx

    java系统,mysql、springboot等框架

    java系统,mysql、springboot等框架

    zigbee CC2530网关+4节点无线通讯实现温湿度、光敏、LED、继电器等传感节点数据的采集上传,网关通过ESP8266上传远程服务器及下发控制.zip

    1、嵌入式物联网单片机项目开发例程,简单、方便、好用,节省开发时间。 2、代码使用IAR软件开发,当前在CC2530上运行,如果是其他型号芯片,请自行移植。 3、软件下载时,请注意接上硬件,并确认烧录器连接正常。 4、有偿指导v:wulianjishu666; 5、如果接入其他传感器,请查看账号发布的其他资料。 6、单片机与模块的接线,在代码当中均有定义,请自行对照。 7、若硬件有差异,请根据自身情况调整代码,程序仅供参考学习。 8、代码有注释说明,请耐心阅读。 9、例程具有一定专业性,非专业人士请谨慎操作。

    YOLO算法-快递衣物数据集-496张图像带标签.zip

    YOLO系列算法目标检测数据集,包含标签,可以直接训练模型和验证测试,数据集已经划分好,包含数据集配置文件data.yaml,适用yolov5,yolov8,yolov9,yolov7,yolov10,yolo11算法; 包含两种标签格:yolo格式(txt文件)和voc格式(xml文件),分别保存在两个文件夹中,文件名末尾是部分类别名称; yolo格式:<class> <x_center> <y_center> <width> <height>, 其中: <class> 是目标的类别索引(从0开始)。 <x_center> 和 <y_center> 是目标框中心点的x和y坐标,这些坐标是相对于图像宽度和高度的比例值,范围在0到1之间。 <width> 和 <height> 是目标框的宽度和高度,也是相对于图像宽度和高度的比例值; 【注】可以下拉页面,在资源详情处查看标签具体内容;

    搜索引擎lucen的相关介绍 从事搜索行业程序研发、人工智能、存储等技术人员和企业

    内容概要:本文详细讲解了搜索引擎的基础原理,特别是索引机制、优化 like 前缀模糊查询的方法、建立索引的标准以及针对中文的分词处理。文章进一步深入探讨了Lucene,包括它的使用场景、特性、框架结构、Maven引入方法,尤其是Analyzer及其TokenStream的实现细节,以及自定义Analyzer的具体步骤和示例代码。 适合人群:数据库管理员、后端开发者以及希望深入了解搜索引擎底层实现的技术人员。 使用场景及目标:适用于那些需要优化数据库查询性能、实施或改进搜索引擎技术的场景。主要目标在于提高数据库的访问效率,实现高效的数据检索。 阅读建议:由于文章涉及大量的技术术语和实现细节,建议在阅读过程中对照实际开发项目,结合示例代码进行实践操作,有助于更好地理解和吸收知识点。

Global site tag (gtag.js) - Google Analytics