




已阅读5页,还剩4页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Java Web 应用程序的字符编码问题 Java Web 应用程序经常会出现乱码的情况,这里可以通过 Servlet API 中的标准 Filter 来实现,也可以在 Web 容器配置 URIEncoding。这些都依赖于浏览器的请求方式。 在 Web 容器的配置文件中配置 URIEncoding = UTF-8 使用 Servlet API 的标准 Filter 结果 地址栏中直接输入链接(含汉字) 失败(编码成功) 地址栏中直接输入链接(含汉字) 失败(编码成功) 地址栏中直接输入链接(含汉字) 失败(编码成功) 页面内的普通链接(a 标签,含汉字) 编码成功,地址栏中直接显示汉字 页面内的普通链接(a 标签,含汉字) 编码失败 页面内的普通链接(a 标签,含汉字) 编码成功,地址栏中直接显示汉字 form get 提交 编码成功,地址栏显示编码后的汉字 form get 提交 编码失败 form get 提交 编码成功,地址栏显示编码后的汉字 form post 提交 编码失败 form post 提交 编码成功 form post 提交 编码成功 因此,通过以上表格的总结,我们可以得出这样一个结论:URLEncoding 是针对 get 请求,Filter 是针对 post 请求。 Web容器的编码问题2008-11-19 09:08:53 技术 | 评论(0) | 浏览(595) 一、 概述基于 Java 编程语言进行应用开发时,不可避免地要处理中文。Java 编程语言默认的编码方式是 UNICODE,而我们通常使用的数据库及文件都是基于 GBK 编码的,我们经常碰到这样的情况:浏览基于 JSP 技术的网站看到的是乱码,文件打开后看到的也是乱码,被 Java 修改过的数据库的内容在别的场合应用时无法继续正确地提供信息。本文将从编码基本知识,Java对字符的处理,以及常见问题的解决三个方面对问题进行阐述。二、 编码基本知识最早的编码是ISO-8859-1,和ASCII编码相似。但为了方便表示各种各样的语言,逐渐出现了很多标准编码,重要的有如下几个。1、ISO-8859-1属于单字节编码,最多能表示的字符范围是0-255,应用于英文系列。比如,字母a的编码为0x61=97。很 明显,ISO-8859-1编码表示的字符范围很窄,无法表示中文字符。但是,由于是单字节编码,和计算机最基础的表示单位一致,所以很多时候,仍旧使用 ISO-8859-1编码来表示。而且在很多协议上,默认使用该编码。比如,虽然中文两个字不存在ISO-8859-1编码,以gb2312编码为例,应 该是d6d0cec4两个字符,使用ISO-8859-1编码的时候则将它拆开为4个字节来表示:d6d0cec4(事实上,在进行存储的 时候,也是以字节为单位处理的)。而如果是UTF编码,则是6个字节e4b8ade69687。很明显,这种表示方法还需要以另一种编码为基础。2、GB2312/GBK这就是汉子的国标码,专门用来表示汉字,是双字节编码,而英文字母和ISO-8859-1一致(兼容ISO-8859-1编码)。其中GBK编码能够用来同时表示繁体字和简体字,而gb2312只能表示简体字,GBK是兼容gb2312编码的。3、UNICODE这是最统一的编码,可以用来表示所有语言的字符,而且是定长双字节(也有四字节的)编码,包括英文字母在内。所以可以说它是不兼容ISO-8859-1编码 的,也不兼容任何编码。不过,相对于ISO-8859-1编码来说,UNICODE编码只是在前面增加了一个0字节,比如字母a为0061。需要说明的是,定长编码便于计算机处理(注意GB2312/GBK不是定长编码),而UNICODE又可以用来表示所有字符,所以在很多软件内部是使用UNICODE编码来处理的,比如java。4、UTF-8考虑到UNICODE编码不兼容ISO-8859-1编码,而且容易占用更多的空间:因为对于英文字母,UNICODE也需要两个字节来表示。所以 UNICODE不便于传输和存储。因此而产生了UTF-8编码,UTF-8编码兼容ISO-8859-1编码,同时也可以用来表示所有语言的字符,不过,UTF-8编码 是不定长编码,每一个字符的长度从1-6个字节不等。另外,UTF-8编码自带简单的校验功能。一般来讲,英文字母都是用一个字节表示,而汉字使用三个字节。 注意,虽然说UTF-8是为了使用更少的空间而使用的,但那只是相对于UNICODE编码来说,如果已经知道是汉字,则使用 GB2312/GBK无疑是最节省的。不过另一方面,值得说明的是,虽然UTF-8编码对汉字使用3个字节,但即使对于汉字网页,UTF-8编码也会比 UNICODE编码节省,因为网页中包含了很多的英文字符。三、 java对字符的处理在java应用软件中,会有多处涉及到字符集编码,有些地方需要进行正确的设置,有些地方需要进行一定程度的处理。1、getBytes(charset)这是java字符串处理的一个标准函数,其作用是将字符串所表示的字符按照char set编码,并以字节方式表示。注意字符串在java内存中总是按 UNICODE编码存储的。比如中文,正常情况下(即没有错误的时候)存储为4e2d6587,如果char set为GBK,则被编码为 d6d0cec4,然后返回字节d6d0cec4。如果char set为UTF-8则最后是e4b8ade69687。 如果是ISO-8859-1,则由于无法编码,最后返回3f3f(两个问号)。3、newString(charset)这是java字符串处理的另一个标准函数,和上一个函数的作用相反,将字节数组按照charset编码进行组合识别,最后转换为UNICODE存储。参考上述getBytes的例子,GBK和UTF-8都可以得出正确的结果4e2d6587,但ISO-8859-1最后变成了 003f003f(两个问号)。因为UTF-8可以用来表示/编码所有字符,所以newString(str.getBytes(UTF-8),UTF-8)=str,即完全可逆。4、setCharacterEncoding()该函数用来设置http请求或者相应的编码。值得注意的是这个函数只设置了Http协议body里面的编码,而对请求连接和Http头无效。因此,该指定只对POST方法有效,对GET方法无效。对于request,是指提交内容的编码,指定后可以通过getParameter()则直接获得正确的字符串,如果不指定,则默认使用ISO-8859-1 编码,需要进一步处理。值得注意的是在执行setCharacterEncoding()之前,不能执行任何 getParameter()。对于response,则是指定输出内容的编码,同时,该设置会传递给浏览器,告诉浏览器输出内容所采用的编码。5、几处设置对于web应用程序,和编码有关的设置或者函数如下。l JSP编译指定文件的存储编码,很明显,该设置应该置于文件的开头。例如:。另外,对于一般class文件,可以在编译的时候指定编码。l JSP输出指定文件输出到browser是使用的编码,该设置也应该置于文件的开头。例如:。该设置和response.setCharacterEncoding(GBK)等效。l META设置指定网页使用的编码,该设置对静态网页尤其有作用。因为静态网页无法采用JSP的设置,而且也无法执行 response.setCharacterEncoding()。例如:如果同时采用了JSP输出和meta设置两种编码指定方式,则JSP指定的优先。因为JSP指定的直接体现在response中。四、 常见问题的解决常见的编码问题大致可以分为四类:第一类是在编译期间造成,原因在于编写代码的编码格式和编译器使用的编译格式不一致;第二类是在运行时由于编码设置的不正确造成,主要因为没有正确设置request和response的字符集编码格式,输入与输出使用了不同的编码格式。第三类是使用URL传输数据时造成,由于HTTP协议规范并没有考虑多国文字,因此URL信息并不包含编码格式信息,编码格式只能依靠约定的形式来确定。第四类由引入资源文件造成,因为引入的资源文件编码格式与页面输出格式不同或没有指定引入资源的编码格式,使得引入的资源文件不能正确的确定编码格式。4.1编译问题4.1.1 编译器字符集指定对于Java类文件的编译问题并不常见,但是错误的本地编码可能会引起这类问题。编译Java文件时会使用Javac(标准Java 编译器)进行编译,它使用的字符集为操作系统默认的字符集,比如在中文 Windows 操作系统上是 GBK/GB18030 ,而在英文UNIX 操作系统上就是ISO-8859-1。因此开发人员会发现在 英文UNIX 操作系统上编译的类,其中双字节(中文)字符都成了乱码或者问号。解决方案是在编译时添加 encoding 参数,就可以做到与平台无关。语法为:javac -encoding GBK对于JSP文件,情况就不太一样了,应为容器在运行时才会对JSP做出解析,生成相应的class文件。如果不对文件做出编码的指定,容器则会使用默认的方式进行编码。此时,编码问题就有可能出现。解决的方法是指定页面使用的编码方式,如:。这样,容器便会知道使用何种编码对文件进行解析,运行环境发生改变后也不会出现编码的异常。4.2.3 使用Include引入可以使用 和两种方法引入另一个JSP页面。这两种方法引入的机制不同,前者使用的是静态引入的方式,在编译时它会将带引入的JSP页面同时生成在同一个class文件中。而后者是采用的动态引入方式,只有在页面请求时才会动态的调用另一个JSP页面。因为,它们引入的方式不同,因此,在处理这两种情况时解决的方法也不相同。使用时,由于引入的JSP页面是一个独立页面,因此可以和普通JSP页面一样进行编码和输出的指定。但是在使用时,被引入的文件不能像被引入的文件一样通过加入指定页面和输出编码的代码片段,因为,如果加入这段代码在解析 JSP文件时就会因为contentType内容重复而报错。但是,可以通过仅指定页面编码格式“”来解决中文问题。此时只指定了页面采用的编码方式,而没有制定页面contentType的内容,不会和主页面冲突。另外,如果使用包含文件时同时传递了包含汉字的参数,也有可能出现编码问题。解决这个问题的方法将在4.2.2节“Forward中问题”中进行介绍。4.2编码设置问题 编码设置问题产生的主要问题是没有正确设置request和response的字符集编码方式。解决的办法很多,可以在有可能产生问题的地方插入设置字符编码的代码片段,也可以通过使用Filter设置字符编码。本节首先介绍此类问题中常见的情况,以及它们的解决方法,最后介绍如何使用Filter统一解决编码设置问题。4.2.1显示问题JSP页面能正确地被编译并不意味着最终显示给用的内容是正确的。因为生成的页面内容还必须经过网络传输才能到达用户的浏览器,而这个过程中也存在着编码的转换问题。如果不对response进行设置,容器会使用默认的编码方式进行传送,而客户端浏览器也可能获取不到编码信息,最终用户看到的可能就是无法辨识的乱码。此时,用户可以通过调整浏览器的字符集来进行调整,但是这决不是用户所希望的。解决的方法很简单,只要指定JSP页面输出格式便可。语法为:。此标签与使用response.setCharacterEncoding()是等效的。综合前两个问题,对于一个JSP页面如果需要解决编译和显示的问题可以通过同时指定页面的编码格式和输出格式达到。语法为:。需要指出的是charset和pageEncoding并一定需要指定为相同的字符集,可以根据具体需要决定。比如说一个页面需要使用GBK编写,同时又希望以UTF-8的格式输出,就可以指定为。4.2.2 Form提交问题当浏览器提交表单的时候,可以指定相应的编码。例如:。一般不必不使用该设置,使用POST方法时浏览器会直接使用网页的编码。Form一般推荐使用POST方法提交请求。因为这种方法相比GET方法可以提交更多的内容,它不会受到请求参数的限制,而且更容易解决编码问题。对于如何解决GET方法里面的编码问题留在RUL编码一节介绍。4.2.3 Forward中文问题使用“jsp:forward”标签进行页面跳转,如果没有指定request的charcterEncoding则很有可能发生编码问题。在处理Forward请求时,如果request的encoding为空,容器便会使用ISO-8859-1的默认编码方式。GBK格式保存得数据并不能直接转换为ISO-8859-1格式,因为GBK是双字节编码,而ISO-8859-1是单字节编码,所以转换的过程中会丢失必要的信息。比如“中文”的GBK编码应该为“%d6%d0%ce%c4”,UTF-8编码为“%e4%b8%ad%e6%96%87”,但如果直接用ISO-8859-1编码格式进行转换,那么转换的结果为“%3f%3f”,丢失掉了必要信息,无法进行反编码操作。解决问题的方式只能是重定向前首先设置request的编码格式,如request.setCharacterEncoding(GBK)。值得注意的是在跳转后的页面便可以直接获得真确的编码,但是如果在获取参数前将字符集改为另外的格式,则同样会引起编码异常。因为改变编码集后,造成了编码前的字符集和解编码的字符集不匹配。4.2.4 使用Filter在每个有可能产生编码问题的地方设置字符集编码,既不便于页面的编码与设计,也不利于后期的维护。由于Filter会在servlet调用前被调用,所以可以使用Filter统一解决编码设置的问题,这将大大减轻编码和维护的工作量。用于设置请求字符集编码的Filter的功能可以设计得非常简单,只需要为每个请求设置特定的编码格式便可,当然,可以根据应用的需要设计的相对比较复杂,也可以对不同的模块使用不同的过滤器,解决多国语言问题。其核心逻辑可以简化为如下形式:public void doFilter() throws IOException, ServletException request.setCharacterEncoding(“GBK”);4.3URL编码问题URL的信息会先于HTTP请求中的其它信息被解析,所以即便使用4.2节中的方法进行了正确的设置仍有可能会产生编码问题。URL中包含请求的路径信息和参数信息两个部分,通过设置服务器的URI解析的默认编码或重构字符串都可以解决这类问题。不过,参数的处理和路径的处理在不同的浏览器间会存在细微的差别,因此将会分开介绍它们各自的解决方法。4.3.1 URL参数问题 URL请求所包含的参数只能使用容器的默认字符集解析,request的setCharacterEncoding函数所设置的编码格式并不能影响到参数的读取,所以当请求中包含汉字等信息时便会出现乱码的现象。 可以通过设置服务器的URIEncoding属性解决这个问题。但是这种解决方法和下一节所介绍的URL路径问题可能存在一定的冲突,下一节将详细分析这种情况。 另外,也可以通过程序代码显示的对数据进行解编码。此时需要确定容器的默认编码方法和待转化的目标编码方式。在不设置容器默认编码的情况下,容器会使用ISO-8859-1编码格式作为默认编码格式。如果应用使用的是GBK的编码格式,编码转化代码可以写为:new String(request.getParameter(name).getBytes(“ISO-8859-1”),”GBK”)。4.3.2 URL路径问题 处理URL路径中的汉字就不像处理参数那么容易了,不是简单的对服务器进行设置或者编写字符集转化代码就可以解决问题的。由于IE
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 安全保卫知识考试题库及答案解析
- 证券从业资格考试习题及答案解析
- 节能降耗工作总结和计划
- 口腔CBCT放射技术
- 手术室护理查房剖宫产
- 课件做法教学反思总结与反思
- 汽车行业采购工作总结
- 年终班组工作汇报
- 胶印版材工艺工安全规范考核试卷及答案
- 消防设施操作员(中级)基础知识考试题库及答案解析
- 有线基础知识
- 互联网广告投放与代理合同
- 2025年自来水集团招聘笔试参考题库含答案解析
- 新教师入职工作安排流程
- 2024年中国室内高尔夫设备市场调查研究报告
- 《商务英语视听说(3)》教学大纲
- 洱海保护课件
- (北师大版2024)七年级数学上学期期中测试卷
- 2024八年级数学上册第12章一次函数12.1函数第1课时上课课件新版沪科版
- 2024年秋新译林版英语三年级上册 Unit 3第1课时 Cartoon time 教学课件
- 全国计算机等级考试一级历年考试真题试题库(含答案)
评论
0/150
提交评论