java web 学习总结之 Servlet/JSP 编码问题

ServletJSP编码问题  

字节流:

 1.得到OutputStream  字节流


  OutputStream os = response.getOutputStream();
  用默认编码输出数据,就是本地编码GBK
  os.write("李赛是一个正直的男人".getBytes());

  在浏览器上输出正常。
  
 用代码设置浏览器的编码
  
  第一种搞法通过响应头
  response.setHeader("Content-Type", "text/html;charset=UTF-8");
  第二种搞法: 用meta标签模拟 (只针对IE浏览器有效果)
  os.write("<meta http-equiv='Content-Type'  

  content='text/html;charset=UTF-8' >".getBytes());
  第三种搞法:
  response.setContentType("text/html;charset=UTF-8");
  用指定的编码输出
  os.write("李赛是一个正直的男人".getBytes("gbk"));

   2.字符流

   得到字符流
   解决办法:设置服务器响应正文编码
   response.setCharacterEncoding("gbk");更改服务器往浏览器输出的编码,iso-8859-1gbk往外输出
  
    如下一行代码有 两个功能:

告知浏览器用什么编码。

另外一个功能,告知服务器输出用什么编码
    response.setContentType("text/html;charset=gbk");
    代码的设置要先于printwriter的出现
    PrintWriter pw = response.getWriter();
    因为默认采用iso-8859-1输出,输出时肯定乱码
    pw.write("崔召金是一个成功男士");

 

  //设置response使用的码表,以控制response以什么码表向浏览器写出数据
  response.setCharacterEncoding("UTF-8");

  //指定浏览器以什么码表打开服务器发送的数据 以下的2种都可以
  response.setHeader("content-type", "text/html;charset=UTF-8");
  response.setContentType("text/html;charset=UTF-8")

  //把客户端提交的数据转码

  request.setCharacterEncoding("UTF-8");

关于JSP页面中的pageEncodingcontentType两种属性的详细解析

简单的说,pageEncodingjsp文件本身的编码 contentTypecharset是指服务器发送给客户端时的内容编码,例如:pageEncoding="GBK",这句话的意思是,告诉JVM这个jsp本身采用的"GBK"编码,JSP编译成Servlet传给JVM的时候,就用“GBK”的编码方式将Jsp网页源文件翻译成统一的UTF-8形式的Java字节码,如果不加设定,则 JVM默认的用iso-8859这种编码方式。 contentType里的charset=gbk,指示的是此网页文件输出到浏览器的输出方式为gbk。在这个过程中,一个JSP的源文件需要经过三个阶段、两次编码,才能完成一次完整的输出。

以一个JSP文件通过Servlet容器假(设为Tomcat)输出到浏览器并显示的过程为例来说明三个阶段、两次编码的具体过程

第一阶段:第一次编码:从JSPServlet.java文件),从pageEncoding———>UTF-8

在第一阶段中完成Jsp的第一次编码:第一次编码用到的指令是pageEncoding,根据pageEncoding=“XXX”的指示,找到编码的规则为“XXX”,服务器在将JSP文件编译成.java文件时会根据pageEncoding的设定读取jsp,结果是由指定的编码方案翻译成统一的UTF-8 JAVA源码(即.java),如果pageEncoding没有设定,则使用默认的iso-8859这种编码方式。设定错了出来的就是中文乱码。

第二阶段:从Servlet文件(.java)到Java字节码文件(.class),从UTF-8———>UTF-8

第一阶段是将jsp编译成.java文件,第二阶段主要是将(.java)的源文件翻译成JVM可识别的java byteCode,也就是Java字节码文件,是由JAVAC命令完成的,这些文件就是通常我们所说的(.class)文件。在这一阶段中,不论JSP编写时候用的是什么编码方案,经过这个阶段的结果全部是UTF-8encodingjava源码。 JAVACUTF-8encoding读取java源码,编译成UTF-8 encoding的二进制码(即.class),这是JVM对常数字串在二进制码(java encoding)内表达的规范。这一过程是由JVM的内在规范决定的,不受外界控件,这也是为什么,有时候看起来是乱码的程序能编译通过,但是去无法正常显示的原因。

第三阶段:第二次编码:从Tomcat服务器到浏览器,从UTF-8―――>contentType

这一阶段,主要是Tomcat显示的输出JSP网页的过程,这在一过程中用到的指令是contentType Tomcat(或其的application container)载入和执行由第二阶段生成出来JAVA二进制码,输出的结果,也就是在客户端可见到的结果,在这事输出过程中,由contentType属性中的charset来指示,将UTF8形式的二进制码以charset的编码形式来输出。如果没有人为设定,则默认的是ISO8859-1.的形式。

注意的问题:以上说的这个过程在大多数据情况是普遍适用的。但这也不是绝对的,还要看各自JSPC的处理方式.在网页设计中,设定pageEncoding不等于contentType,更有利亚洲区的文字 CJKVJSP网页的开发和展示, (pageEncoding=GB2312不等于 contentType=utf-8) jsp文件不像.java.java在被编译器读入的时候默认采用的是操作系统所设定的locale所对应的编码,比如中国大陆就是GBK,台湾就是BIG5或者MS950。而一般我们不管是在记事本还是在ue中写代码,如果没有经过特别转码的话,写出来的都是本地编码格式的内容。所以编译器采用的方法刚好可以让虚拟机得到正确的资料。但是jsp文件不是这样,它没有这个默认转码过程,如果指定了pageEncoding就可以实现正确转码了。举个例子: <%@ page contentType="text/html;charset=utf-8" %>大都会打印出乱码,因为输入“你好”的编码方式你没有指定,在大多数情况下我们在中国大陆地区所用的电脑在输入的你好的时候,都会用gbk来编码,但是对服务器而言,是否正确抓到你好却不得而知。但是如果更改为 <%@ page contentType="text/html;charset=utf-8" pageEncoding="GBK"%>这样就服务器一定会是正确抓到你好了,这就是为什么有两个不同的指令设定,和两次不同的编码过程。

明白了这三个阶段和两次编码过程,那么在编程的时候,JSP网页中、数据库中、Web服务器中,关于一些字符的设定就会很清楚,要不然,会设来设去,字符跟着转来转去,最终没没转出过正确的来,记住一点,万变不离其踪,只要把最本质的东西搞明白,不管怎么变都不会有太大的问题。

近期笔者会把数据库与网页交互过程中出现的一些乱码问题、字符集问题、编码规则问题再整理下,在下一篇文章中与读者见面。







 


posted @ 2014-07-09 00:51  博客园杀手  阅读(257)  评论(0编辑  收藏  举报