尚学堂.张志宇.乱码分析_07_form表单存储格式.doc

 

1       结论

req.setCharacterEncoding( "gbk" );

含义是取上一个页面的参数,按照 gbk 进行解码

tomcat 取参数默认按照 iso-8859-1 进行解码

resp.setContentType( "text/html;charset=gbk" );

含义是发送内容到客户端浏览器,按照 gbk 进行编码

tomcat 发送内容到客户端浏览器,默认按照 iso-8859-1 进行编码

 

 

场景 1

场景 2

场景 3

 

 

 

form 表单存为什么格式

ansi

ansi

utf-8

 

 

 

form 表单提交方式

post

post

post

 

 

 

Servletresp.setContentType

-

charset=gbk

charset=gbk

 

 

 

Servletreq.setCharacterEncoding

-

gbk

gbk

 

 

 

是否有乱码

没有乱码

没有乱码

鎴戜滑

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

2       场景 1

form.html

<form action="/my/servlet/TestServlet" method="post" >

    <input name="username">

    <input type="submit" value=" 提交 ">

</form>

 

TestServlet.java

import java.io.IOException;

import java.io.PrintWriter;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

 

public class TestServlet extends HttpServlet {

 

    @Override

    protected void doGet(HttpServletRequest req, HttpServletResponse resp)

           throws ServletException, IOException {

       PrintWriter out = resp.getWriter();

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

       System. out .println(username);

       out .println(username);

       out .close();

    }

 

    @Override

    protected void doPost(HttpServletRequest req, HttpServletResponse resp)

           throws ServletException, IOException {

       doGet(req, resp);

    }

}

 

web.xml

    <servlet>

      <servlet-name>TestServlet</servlet-name>

      <servlet-class>TestServlet</servlet-class>

    </servlet>

 

    <servlet-mapping>

        <servlet-name>TestServlet</servlet-name> 

        <url-pattern>/servlet/TestServlet</url-pattern>

    </servlet-mapping>

 

访问这个地址 http://127.0.0.1/my/form.html

输入“我们”然后提交。我们看到的是正确的中文,没有乱码

2.1   分析

 

下面通过例子详细说明为什么没有乱码。

虽然场景 1 没有乱码。但不是最终的解决办法。

因为页面本身的中文会有乱码。

 

// 重要结论

//jvm 只能表示 unicode 收录的字符们

//jvm 在内存里用 utf-16 编码表示一个字符

//System.out.println 先按照操作系统默认的编码来编码,得到的字节们传到 consoleconsole 再按系统默认的编码解码

//zhongwen.getBytes("GBK")--> 编码

//new String(zhongwen.getBytes("GBK"), "iso8859-1");--> 解码

//tomcat 取参数默认按照 iso-8859-1 进行解码

//tomcat 发送内容到客户端浏览器,默认按照 iso-8859-1 进行编码

 

// 字符 ""gbk 编码: ced2

// 字符 ""utf-16 编码: 6211

// 字符 ""utf-8 编码: e6 88 91

public class TestBB {

 

    public static void main(String args[]) throws Exception {

       //jvm 在内存里用 utf-16 编码表示一个字符 ,

       // 所以在内存中, zhongwen 这个引用指向的字符串对象包括 2 个字节 62 11

       String zhongwen = "" ;

       //println 方法不会把内存中的 utf-16 编码输出到 console

       // 而是按照系统默认编码( gbk )编码,然后才将 gbk 编码( ced2 )输出到 console

       //cosole 接收 gbk 编码( ced2 ),再按照系统默认编码来解码,显示出正确的中文

       System . out .println(zhongwen);

       //getBytes 方法是编码的意思。

       // 下面验证 "" 这个字符的 gbk 编码是 ced2

       byte [] bytes = zhongwen.getBytes( "gbk" );

       System . out .println( "--------GBK----------" );

       for ( byte b:bytes){

           System . out .format( "%x " ,b);

       }

       System . out .println();

       // 浏览器默认按照 gbk 编码,然后将参数传到服务器

       // 浏览器将以什么编码来提交参数,和 form 表单这个 html 页面的存储方式有关。

       // 如果 form 表单存为 ansi ,即 jbk ,那么提交参数也用 gbk.

      

      

       // 服务器端接收 gbk 编码 2 个字节( ced2 ),默认按照 iso8859-1 解码

       // 所以解码出错误的 2 个字符

       System . out .println( "-------iso8859-1--------" );

       //2iso8859-1 字符在内存里表示为 4 个字节: 00 ce 00 d2

       zhongwen = new String(zhongwen.getBytes( "GBK" ), "iso8859-1" );

       //println 方法不会把内存中的 utf-16 编码输出到 console

       // 而是按照系统默认编码( gbk )来编码,得到 2 个字节: 3f 3f , (为什么是 3f 下面会解释)

       // 然后才将这些 gbk 编码输出到 console

       //cosole 再按照系统默认编码来解码,得到 2?

       // (因为 ascii 中, ? 就是 3f ,并且 gbkascii 兼容,所以在 gbk 中, 3f 也是 ?

      

       System . out .println(zhongwen);

      

       // 内存中的 00 ce 表示的那个 iso8859-1 字符在 gbk 中没有收录,所以按照 gbk 编码就会出错。

       // 如果出错,一律编码为 3f ,所以得到 23f

       bytes = zhongwen.getBytes( "gbk" );

       for ( byte b:bytes){

           System . out .format( "%x " ,b);

       }

       System . out .println();

      

       // 服务器再按照 iso8859-1 编码,传到客户端浏览器

       bytes = zhongwen.getBytes( "iso8859-1" );

 

       // 最初的 gbk 编码 cede 是不是没有丢?

       // 可见有些编码解码的过程是可逆的。

       // 当然有些编码解码的过程就不可逆。

       for ( byte b:bytes){

           System . out .format( "%x " ,b);

       }

       System . out .println();

      

       // 浏览器得到传过来的字节们,再按照 gbk 解码。得到正确的中文。

       System . out .println( "-------GBK--------" );

       System . out .println( new String(bytes, "GBK" ));

    }

}

 

 

3       场景 2

 

form.html

<form action="/my/servlet/TestServlet" method="post" >

    <input name="username">

    <input type="submit" value=" 提交 ">

</form>

 

TestServlet.java

import java.io.IOException;

import java.io.PrintWriter;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

 

public class TestServlet extends HttpServlet {

 

    @Override

    protected void doGet(HttpServletRequest req, HttpServletResponse resp)

           throws ServletException, IOException {

       resp.setContentType( "text/html;charset=gbk" );

       PrintWriter out = resp.getWriter();

       req.setCharacterEncoding( "gbk" );

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

       System. out .println(username);

       out .println(username);

       out .close();

    }

 

    @Override

    protected void doPost(HttpServletRequest req, HttpServletResponse resp)

           throws ServletException, IOException {

       doGet(req, resp);

    }

}

 

web.xml

    <servlet>

      <servlet-name>TestServlet</servlet-name>

      <servlet-class>TestServlet</servlet-class>

    </servlet>

 

    <servlet-mapping>

        <servlet-name>TestServlet</servlet-name> 

        <url-pattern>/servlet/TestServlet</url-pattern>

    </servlet-mapping>

 

访问这个地址 http://127.0.0.1/my/form.html

输入“我们”然后提交。我们看到的是正确的中文,没有乱码

3.1   分析

浏览器发送 form 表单内容到服务器

服务器接收内容,进行解码

服务器将解码后得到的内容进行编码,再传到浏览器

浏览器接收内容,进行解码

详细内容略。。。。。。

4       场景 3

略。。。。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值