`
yaomeone
  • 浏览: 60590 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

url中文乱码分析

    博客分类:
  • java
阅读更多

案例:

1、  环境介绍:

项目采用的是 SSH 框架技术,模板视图用的是 FreeMarker ,对于编码问题做了以下的配

置:

 tomcat 服务器没配置 URIEncoding 参数。

 struts2 配置文件配置了如下的参数:

  <!-- 编码 -->

< constant name = "struts.i18n.encoding" value = "UTF-8" />

 web.xml 进行了如下配置:

<!-- 编码处理过滤器 -->

    < filter >

       < filter-name > encodingFilter </ filter-name >

       < filter-class >

           org.springframework.web.filter.CharacterEncodingFilter

       </ filter-class >

       < init-param >

           < param-name > encoding </ param-name >

           < param-value > utf-8 </ param-value >

       </ init-param >

       < init-param >

           < param-name > forceEncoding </ param-name >

           < param-value > true </ param-value >

       </ init-param >

</ filter >

现在来看一下这三者分别的用途,

A  URIEncoding 的作用是什么呢?

解析请求的 URL 是在 org.apache.coyote.HTTP11.InternalInputBuffer parseRequestLine 方法中,这个方法把传过来的 URL  byte[] 设置到org.apache.coyote.Request 的相应的属性中。这里的 URL 仍然是 byte 格式,转成char 是在 org.apache.catalina.connector.CoyoteAdapter  convertURI 方法中完成的:    

protected void convertURI(MessageBytes uri, Request request) throws Exception {

       ByteChunk bc = uri.getByteChunk();

       int length = bc.getLength();

       CharChunk cc = uri.getCharChunk();

       cc.allocate(length, -1);

       String enc = connector.getURIEncoding();

       if (enc != null ) {

           B2CConverter conv = request.getURIConverter();

           try {

                 if (conv == null ) {

                    conv = new B2CConverter(enc);

                    request.setURIConverter(conv);

                }

            catch (IOException e){...}

           if (conv != null ) {

              try {

                   conv.convert(bc, cc, cc.getBuffer().length -  cc.getEnd());

                   uri.setChars(cc.getBuffer(), 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);

    }

 

从上面的代码中可以知道对 URL  URI 部分 ( 也就是具体的请求资源部分不包括?后面的参数 ) 进行解码的字符集是在 connector  <Connector URIEncoding=”UTF-8”/> 中定义的,如果没有定义,那么将以默认编码 ISO-8859-1 解析。所以如果有中文 URL 时最好把 URIEncoding 设置成 UTF-8 编码。

 

QueryString 又如何解析? GET 方式 HTTP 请求的 QueryString  POST 方式 HTTP 请求的表单参数都是作为Parameters 保存,都是通过 request.getParameter 获取参数值。对它们的解码是在 request.getParameter 方法第一次被调用时进行的。 request.getParameter 方法被调用时将会调用 org.apache.catalina.connector.Request parseParameters 方法。这个方法将会对 GET  POST 方式传递的参数进行解码,但是它们的解码字符集有可能不一样。 POST 表单的解码将在后面介绍, QueryString 的解码字符集是在哪定义的呢?它本身是通过HTTP  Header 传到服务端的,并且也在 URL 中,是否和 URI 的解码字符集一样呢?从前面浏览器对 PathInfo QueryString 的编码采取不同的编码格式不同可以猜测到解码字符集肯定也不会是一致的。的确是这样QueryString 的解码字符集要么是 Header  ContentType 中定义的 Charset 要么就是默认的 ISO-8859-1 ,要使用 ContentType 中定义的编码就要设 connector  <Connector URIEncoding=”UTF-8” useBodyEncodingForURI=”true”/> 中的 useBodyEncodingForURI 设置为 true 。这个配置项的名字有点让人产生混淆,它并不是对整个 URI 都采用 BodyEncoding 进行解码而仅仅是对 QueryString 使用 BodyEncoding 解码,这一点还要特别注意。

从上面的 URL 编码和解码过程来看,比较复杂,而且编码和解码并不是我们在应用程序中能完全控制的,所以在我们的应用程序中应该尽量避免在 URL 中使用非 ASCII 字符,不然很可能会碰到乱码问题,当然在我们的服务器端最好设置 <Connector/> 中的 URIEncoding  useBodyEncodingForURI 两个参数。

   也就是说对请求资源的解码和对后面所带参数的解码采用的字符集可能是不同的, URIEncoding 的设置只会告诉服务器如何对请求资源解码,而不会告诉服务器如何对请求参数解码,配置了 useBodyEncodingForURI 则告诉服务器使用 bodyEncoding 进行解码。

   根据以上分析,可以知道项目没有配置 URIEncoding  useBodyEncodingForURI 两个参数。则对请求资源以及请求参数都会采用默认的 ISO8859-1 ,进行解码。

不过要说一点,虽然这里如果进行了指定,但是由于不同浏览器对 URL 进行编码的方式不同,也会出现乱码,以下是分析 :

浏览器:

1  GET 方式提交,浏览器会对 URL 进行 URL encode ,然后发送给服务器。 
(1) 
对于中文 IE, 如果在高级选项中选中总以 UTF-8 发送 ( 默认方式 ) ,则 PathInfo  URL Encode 是按照 UTF-8 编码 ,QueryString 是按照 GBK 编码。 
http://localhost:8080/example/ 
中国 ?name= 中国 
实际上提交是: 
GET /example/%E4%B8%AD%E5%9B%BD?name=%D6%D0%B9%FA

(1) 对于中文 IE, 如果在高级选项中取消总以 UTF-8 发送,则 PathInfo  QueryString URL encode 按照 GBK 编码。 
实际上提交是: 
GET /example/%D6%D0%B9%FA?name=%D6%D0%B9%FA

(3) 对于中文 firefox ,则 pathInfo  queryString 都是 URL encode 按照 GBK 编码。 
实际上提交是: 
GET /example/%D6%D0%B9%FA?name=%D6%D0%B9%FA

很显然,不同的浏览器以及同一浏览器的不同设置,会影响最终 URL  PathInfo 的编码。对于中文的 IE  FIREFOX 都是采用 GBK 编码 QueryString 

小结:解决方案: 
1
  URL 中如果含有中文等非 ASCII 字符,则浏览器会对它们进行 URLEncode 。为了避免浏览器采用了我们不希望的编码,所以最好不要在 URL 中直接使用非 ASCII 字符,而采用URL Encode 编码过的字符串 %.
比如: 
URL
  http://localhost:8080/example/ 中国 ?name= 中国 
建议: 
URL
  http://localhost:8080/example/%D6%D0%B9%FA?name=%D6%D0%B9%FA

2 、我们建议 URL  PathInfo  QueryString 采用相同的编码,这样对服务器端处理的时候会更加简单。

  由于我什么都没有设置,所以可以猜到,如果有中文路径或者是中文参数的 URL ,一定会出现中文乱码。假设我进行了设置,但是如果我在页面中没对中文路径和中文参数 URL 进行编码处理,那么由于不同浏览器的编码方式不同也会造成中文乱码问题,也就说终极解决方案是:所以最好不要在 URL 中直接使用非 ASCII 字符,而采用 URL Encode 编码过的字符串 %.

B  < constant name = "struts.i18n.encoding" value = "UTF-8" />

这个参数有什么作用呢?

关于这个参数有什么作用,网上也进行过讨论,参考这篇文档 http://cgl198617.iteye.com/blog/1066401 ,从这篇文档可以看出这个参数的设置对于解码和页面显示有很大的作用,对于请求阶段来说相当于执行了HttpServletRequest  setCharacterEncoding 这个方法,但是对于这个方法,之前一直都没认真去理解,是不是设置了这个参数 url 中文乱码问题就解决了呢,答案是否定的, HttpServletRequest.setCharacterEncoding() 方法仅仅只适用于设置 post 提交的 request body 的编码而不是设置 get 方法提交的 queryString 的编码。该方法告诉应用服务器应该采用什么编码解析 post 传过来的内容。很多文章并没有说明这一点。看看 servlet  api 也可以知道这一点:

Overrides the name of the character encoding used in the body of this request 

这个方法用来设置网页 body 的编码方式,可以在页面中设置,也可以在获取参数之前,通过 HttpSevletRequest对象设置,现在来看 POST 提交:

POST 表单的编解码

在前面提到了 POST 表单提交的参数的解码是在第一次调用 request.getParameter 发生的, POST 表单参数传递方式与 QueryString 不同,它是通过 HTTP  BODY 传递到服务端的。当我们在页面上点击 submit 按钮时浏览器首先将根据 ContentType  Charset 编码格式对表单填的参数进行编码然后提交到服务器端,在服务器端同样也是用 ContentType 中字符集进行解码。所以通过 POST 表单提交的参数一般不会出现问题,而且这个字符集编码是我们自己设置的,可以通过 request.setCharacterEncoding(charset) 来设置。

另外针对 multipart/form-data 类型的参数,也就是上传的文件编码同样也是使用ContentType(  里所说的 ContentType 是指 http 头的 ContentType ,而不是在网页中meta 中的 ContentType 定义的字符集编码,值得注意的地方是上传文件是用字节流的方式传输到服务器的本地临时目录,这个过程并没有涉及到字符编码,而真正编码是在将文件内容添加  parameters 中,如果用这个编码不能编码时将会用默认编码 ISO-8859-1 来编码。

通过上面的分析我们可以知道, post 提交的编码解码跟服务器端的设置没有任何关系,而且也别妄想通过使用 request.setCharacterEncoding() 方法来解决 url 传递参数中文乱码的问题。

C  web.xml 中配置了解决中文编码问题的过滤器,我们查看源码发现这个:

  if ( encoding != null && ( forceEncoding || request.getCharacterEncoding() == null ))

        {

            request.setCharacterEncoding( encoding );

            if ( forceEncoding && responseSetCharacterEncodingAvailable )

                response.setCharacterEncoding( encoding );

        }

        filterChain.doFilter(request, response);

看到这个方法没有:

request.setCharacterEncoding( encoding );

现在就知道为什么我配置了中文编码过滤器还是出错的原因了嘛,这个过滤器只会对 post 提交有效,这是防止你在页面中没有设置 ContentType  charset 而导致中文乱码。

 

   经过上面的分析总结一下终极解决办法:

1、   Tomcat 中设置 URIEncoding  useBodyEncodingForURI 这两个参数。

2、  页面中或 js 中有中文路径或从参数,先进行编码,编码字符集和上面 tomcat 中配置的一样。

分享到:
评论

相关推荐

    奇数个中文字符url传递乱码

    当URL中包含奇数个中文字符时,可能会出现乱码的情况,这不仅会影响用户体验,还可能导致程序逻辑错误。本文将深入探讨“奇数个中文字符URL传递乱码”的问题,并提供一种可行的解决方案。 ### 一、问题背景 #### ...

    中文乱码问题分析 自己总结的

    中文乱码问题分析 中文乱码问题是 Java 和 JSP 开发中的一种常见问题,主要是由于 Java 和 JSP 源文件的保存方式是基于字节流的,而编译成 class 文件过程中,使用的编码方式与源文件的编码不一致所致。在 Java ...

    java中文乱码分析

    ### Java中文乱码分析 #### 一、概述 在Java Web开发中,中文乱码问题是一个常见的技术难题,尤其在处理HTTP请求时尤为突出。本文将深入探讨HTTP请求中的中文乱码现象,并提供相应的解决方案。 #### 二、HTTP请求...

    web开发中url乱码处理

    4. **问题分析**:在尝试这两种方法无效的情况下,可能是因为URL在到达后台之前已经被自动解码,并按照ISO-8859-1进行存储。这时,我们需要在后台再次进行编码转换,将已解码的ISO-8859-1编码字符串转换回UTF-8。 5...

    JSP中汉字乱码现象分析与解决.pdf

    ### JSP中汉字乱码现象分析与解决 #### 摘要 在JSP开发过程中,汉字乱码问题是一个常见的技术挑战,它不仅影响用户体验,还可能阻碍项目的顺利进行。本文详细探讨了JSP中汉字乱码现象的原因,并提供了一系列有效的...

    解决Flex 中文乱码

    在开发Flex应用程序时,我们经常会遇到中文乱码的问题,这主要源于AS3(ActionScript 3)和服务器之间编码不一致导致的。Flex是Adobe推出的一款用于构建富互联网应用程序(RIA)的框架,其核心编程语言是AS3。在处理...

    html 中文乱码 HTML超链接中文乱码问题分析及解决方法

    如果直接拼接,传到后台Action的参数对象中后取出会是乱码,需要编码后再拼接到URL上。 解决方法是在Action中添加一个成员变量,保存编码后的中文参数。在vm页面渲染时取出这个变量值,再拼接超链接。 在这里碰到的...

    HTML超链接中文乱码问题分析及解决方法.docx

    本文将分析超链接中文乱码问题的成因和解决方法。 问题分析 在 HTML 超链接中,当我们需要将中文参数作为 GET 请求的参数时,直接拼接中文参数到 URL 上可能会导致乱码。例如,在一个超链接 URL 中,我们需要将...

    JSP中文乱码问题分析及处理方法

    ### JSP中文乱码问题分析及处理方法 #### 一、问题根源剖析 JSP(Java Server Pages)作为Web开发中的一种技术,广泛应用于动态网页的生成。然而,在处理中文字符时,JSP经常会遇到“乱码”问题,即中文字符无法...

    js中文乱码问题分析及解决方案.docx

    js中文乱码问题分析及解决方案 在Web开发中,JavaScript文件的编码问题是一个常见的错误,特别是在引入外部JavaScript文件时。如果Web页面和JavaScript文件使用不同的编码,可能会出现乱码问题。本文将分析...

    中文乱码处理问题总结

    1. **问题描述**:通过URL直接传递中文参数时出现乱码。 2. **解决方案**: - 使用过滤器(Filter)在请求处理前设置编码格式。 - 如果已经发生了乱码,可以通过字符串编码转换的方式来修复。 - **示例代码**:...

    extjs 前后台交互参数出现中文乱码问题的解决方法

    // 发送POST请求,并将编码后的中文参数拼接到URL中 conn.open("POST", "/SanXiaMS/servlet/AccountBookServlet1?CustomFormName=" + CustomFormName1, false); conn.send(null); // 获取服务器响应结果 var ...

    java中文乱码解决问题

    下面我们对容易产生乱码问题的场景进行分析,并提出解决方案。 1. 以 POST 方法提交的表单数据中有中文字符 在 Servlet/JSP 程序中,通过请求对象的 getParameter() 方法得到的字符串是以 ISO-8859-1 转换而来,这...

    JSP汉字乱码解决大全

    #### 二、中文乱码原因分析 中文乱码通常由编码不一致导致,具体可以分为以下几个方面: 1. **请求参数编码问题**:当客户端发送含有中文字符的请求参数时,如果服务器端处理请求参数的编码与客户端发送时使用的...

    json 中文乱码解决方案

    ### json 中文乱码解决方案 在处理JSON数据时,经常会出现中文乱码的问题,尤其是在不同编码格式间进行转换时更为常见。本文将详细介绍如何解决JSON中的中文乱码问题,并提供几种简单实用的方法来帮助开发者避免这...

    jQuery中文乱码

    ### jQuery中文乱码完美解决方案 在处理Web应用中,尤其是涉及到多语言环境时,中文乱码问题时常困扰着开发者。本文将深入探讨jQuery在处理中文数据时遇到的乱码问题,并提供一系列有效的解决方案。 #### 一、理解...

    解决Tomcat中文乱码

    ### 解决Tomcat中文乱码问题 在使用Tomcat服务器部署Web应用时,经常会遇到中文乱码的问题。本文将详细探讨这一现象的原因,并提供一种有效的解决方案。 #### 问题背景 在Tomcat环境下运行Web应用程序时,如果...

    java插入mysql中文乱码解决

    #### 二、乱码原因分析 中文乱码主要由以下几个方面的原因引起: 1. **字符集不一致**:如果Java程序、JDBC驱动、MySQL服务器以及数据库表的字符集设置不一致,就会导致中文乱码。例如,如果Java程序使用的是GBK...

Global site tag (gtag.js) - Google Analytics