GET请求的中文乱码问题及处理意义

GET请求的中文乱码有关问题及处理意义

GET请求的中文乱码问题及处理意义

首先看一段乱码的程序:

 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

  //0设置编码

  request.setCharacterEncoding("UTF-8");

  String username=request.getParameter("username");

  String password=request.getParameter("userPwd");

  System.out.println("处理之前:"+username+":"+password);

  //此时输出的结果:处理之前:胡玉勉:aa1234bb---也就是说中文字符本身的编码还是不对。

  //做如下处理:

  username = new String(username.getBytes("ISO8859-1"),"UTF-8");

  System.out.println("处理之后:"+username+":"+password);

  response.setContentType("text/html;charset=UTF-8");

  ServletOutputStream out=response.getOutputStream();

  out.println(username);

  out.println(password);

 }

 

乱码原因的分析:

get请求的原理图:

 

1.数据解析编码:指的是html页面form表当数据提交时候的编码方式,这个编码方式和页面编码是统一的,这里设置为UTF-8

2.GET请求的的请求数据,并不在请求体体中,而是在请求行中的?之后。而整个请求数据,包括请求行,请求头,请求体都会通过http协议发送到服务端去处理。(HTTP协议时不支持中文的,默认编码:ISO8859-1

对比post请求,post请求的的请求数据都包含在请求体中,当发送了了服务端的时候,通过设置request.setCharacterEncoding("UTF-8"),就能够使得数据传输到服务端的时候,能够将其解析成utf-8的数据。

但是,这样的设置编码的操作对请求行中的数据缺失无效的。

3.前面说了数据时通过http协议的方式发送到服务端,而请求行的信息(原始状态下是UTF-8编码)经过http协议进行传输的时候,http协议对其进行了默认编码的编码操作。并发送到了服务端,而服务端类似post请求的处理方式,对其有没有作用。

那么,服务段应该如何对这样的乱码,就行解码,让其还原成UTF-8编码呢。实际上就是还原成原始数据的编码?

(乱码产生的核心本质:源编码和读取显示的编码不一致)

思路:找到源编码的二进制,然后重新用UTF-8进行解码就可以了。

4.解决办法:

服务端:String username=request.getParamter("username");----这是获得的ISO8859-1编码的乱码数据

解码:

username.getBytes("ISO8859-1");-----这样就获得了原始数据。

而原始数据就是按照UTF-8编码的,那么此时,只需要将其变成UTF-8的字符串数据就ok

new String(username.getBytes("ISO8859-1,"UTF-8""));

最终表现在上面的程序中,值处理之前,是乱码的,通过解码在还原的操作,中文则不再乱码。

 

仍然存在的疑惑:

1. response.setContentType("text/html;charset=UTF-8");

如果没有手动解码的代码username.getBytes("ISO8859-1"); 通过上述方式设置response编码,将其发送到浏览器,没有出现乱码。

这种情形是合理的吗?是不是上述操作的底层也是用过来类似 username.getBytes("ISO8859-1") 这样的解码方式?(可以这么理解)

 

2.如果是post请求的时候,请求内容在请求体中,不也要通过http协议对其进行编码吗?为什么数据发送到服务端,就直接可以通过

request.setCharcterEncoding(UTF-8)对数据进行解码?(视频里面提到流的处理方式)

 

这里面,request.setCharacterEncoding(UTF-8)值能请求体中的流进行处理。

 

那么这个还有一个问题就是,

  response.setContentType("text/html;charset=UTF-8");

  ServletOutputStream out=response.getOutputStream();

  out.println(username);

  out.println(password);

做了这样的操作以后,即使没有手动解码,在服务端通过上述流操作,将数据输出到浏览器中,没有出现乱码。

 

那么对于get请求,手动解码的意义是什么呢。后来明白了,因为大多数情况下,还是要将数据信息存储到数据库中个,

存储到数据库的操作,可不是流的操作,那么这个时候,如果这届存储到数据库的情况下,就会乱码的。所以通过手动解码的方式的意义还是大大的。

 

当然,一般不用字节流来处理文本数据,上述代码,改成response.getWriter的方式处理就ok

 

 

 

SpringMVCredirecturl中有中文,模拟redirect发送请求后出现中文乱码:

解决:redirect中的realName有中文,这里发送服务器请求时,会把请求先发送给浏览器(直接在浏览器输地址可以是因为浏览器本来就转了码再请求的服务器),必须转码后,再由浏览器把UTF-8编码的字符发送给服务器。

        redirect = encode(redirect);

       return "redirect:" + ((redirect == null || redirect.equals("")) ? this.getMy("weixin/vip/") : redirect);

      

    }

   

    public static String encode(String url) 

    { 

        try { 

             Matcher matcher = Pattern.compile("[\\u4e00-\\u9fa5]").matcher(url); 

             while (matcher.find()) { 

               String tmp=matcher.group(); 

               url=url.replaceAll(tmp,java.net.URLEncoder.encode(tmp,"UTF-8")); 

             } 

        } catch (UnsupportedEncodingException e) { 

            e.printStackTrace(); 

        } 

         

        return url; 

    }

 

 

 

tomcat请求数据的编码设置

tomcat5中,为了保证get数据采用UTF8编码,在server.xml中进行了如下设置:
<Connector port="8080" maxThreads="150" minSpareThreads="25"
maxSpareThreads="75" enableLookups="false" redirectPort="8443"
acceptCount="100" debug="99" connectionTimeout="20000"
disableUploadTimeout="true" URIEncoding="UTF-8"/>
这里指定了get时候的数据编码。但是,当使用IIS作为webserver转发servlet/jsp请求给Tomcat时候,这个设置却失效了。其实原因很简单:IIS是通过AJP协议,把请求转发到Tomcat监听的8009端口上的,所以这里针对8080的设置自然就无效了。正确的方法是进行下面的设置:
<Connector port="8009" enableLookups="false" redirectPort="8443"
debug="0" protocol="AJP/1.3" URIEncoding="UTF-8"/>

========================================================================================

Tomcat 6.0

路径:Tomcat 6.0\conf\server.xml
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
URIEncoding="UTF-8" />

<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" URIEncoding="UTF-8" />

========================================================================================

问题解决办法 
1)
修改server.xml,在connector标签中增加URIEncoding="gb2312"  
2)
url编码  
java.net.URLEncoder.encode(   url   ); 
 
注意:url的起始如果非中文如   "/test/中文/中国.jsp"  
则应该写成"/test/"   +   java.net.URLEncoder.encode(   "中文/中国.jsp"   );  
意思是只对中文编码,但是   "中文/中国.jsp"中的"/"没有问题

 

 

 

 

*************************

tomcat设置URIEncoding="utf-8"之后,可以解决了中文路径问题,例如:http://localhost:8081/测试.jpg

但是http://localhost:8081/TServlet?a=测试

这样获取不到中文,也不能正确编码,因为tomcat使用的是默认的ISO-8859-1编码,在变成UTF-8之前已经编码过了,所以乱码,要让不进行ISO-8859-1编码,还得加一句:useBodyEncodingForURI="true"

 

 

tomcat不设置,用默认的

你在你的servlet或者strutsaction中,对request对象设置编码即可解决问题。

例:request.setCharacterEncoding("GBK");

 

常用的方法是建一个过滤器filter,把request.setCharacterEncoding("GBK"); 放到过滤器的方法里,这样每次提交都会经过过滤器设置编码,就不需要每个servlet或者action中都写一次这个代码了