`

JSP页面编译成Servlet类文件过程中所涉及到的编码问题

阅读更多

当请求一个JSP页面时,一般的都需要经历下面几个阶段:

1、应用服务器根据JSP页面生成一个Java文件

2、应用服务器调用java.exe将Java文件编译成一个Servlet对应的class文件

3、用户的浏览器请求JSP对应的Servlet,Web容器起一个线程执行Servlet,将数据返回给客户端浏览器

4、用户的IE根据返回的数据,将结果显示给用户。

 

第一步中应用服务器根据Jsp页面生成一个Java文件时,需要读取源Jsp页面到内存中,然后以某种编码方式生成Servlet类文件,这一读的过程会涉及到采用什么编码方式来读取的问题?这里先看一下结论:如页面中设置了pageEncoding="XX",则服务器在读取Jsp页面时,就会使用上面设置的XX来读取,如果没有设置,再看是否设置了contentType="text/html; charset=XXX" ,如果设置了,则用charset中指定的编码方式来读取。如果这两个都没有指定时,则使用默认的编码方式ISO8859-1来读取

以上是读取的过程,当把Jsp页面读取到内存后,在内存中以Unicode编码存在,这时需要根据Jsp文件生成Servlet类文件,既然要定文件,这里又会涉及到编码问题,这里该使用什么编码方式来输出到文件呢?先看结论:Tomcact是使用UTF-8编码方式来输出的 ,这也是理所当然的,因为页面上会有不同的各种语言。

 

 

下面来证实上面的两个结论。

 

首先我们写一个Jsp页面gbk.jsp,从文件名就可知我们创建一个以GBK编码方式保存的Jsp文件。

下面是我创建并设置好编码方式的过程:

<%@ page language="java" %>
<html>
	<body>
		<form name=form1 action="" method="get">
			<input type="text" name="textParam1" size="50 px" value="國a">
			<br>
			<input type="file" name="fileParam" size="50 px" value="">
			<br>
			<input type="button" value="submit" onclick="submitForm()">
		</form>
		<script type="text/javascript"> 
			function submitForm(){ 
				//注释
				var str ="國a"; 
				form1.action = "http://localhost:8088/gb2312rs.jsp?qryParam1=" +
				 encodeURIComponent(str) + "&qryParam2="+  encodeURIComponent(form1.textParam1.value) ;
				form1.submit(); 
			} 
		</script>
	</body>
</html>

 

 

 

 

 

保存后,我们开始访问一下,浏览器显示如下:

从上图看出浏览器使用的是ISO编码方式,所以上面文本框里显示正常才怪呢~!但当我们把浏览器的编码方式换成GBK时,看是什么样,~!~#@!¥,晕~!找了半天浏览器上面根本就没有GBK这一编码方式,中文的就只有GB2312,我们就选一下GB2312试试看,如下图:


 咦~!我们选择是GB2312怎么也可显示出繁体字啊?其实浏览器中的GB2312就是用的操作系统默认的编码GBK来显示的,至于解释请看《Java中的字符集编码入门(三)GB2312,GBK与中文网页 》。好奇心没有后继续往下看。

 

我们打开服务器帮我们生成的Servlet类文件,其中输出中文的地方代码片断如下:

 

我们发现中文“注释”与“國”字,都变成了乱码。既我们知道了上面结论:该文件是UTF-8编码格式的,那我就以UTF-8来读读这个文件,读代码如下:

 

String fileName = "E:/tomcat-5.5.23/work/Catalina/localhost/HttpStream/org/apache/jsp/gbk_jsp.java";
PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream("e:/tmp/gbk_jsp.java"), "UTF-8"));
BufferedReader br = new BufferedReader(new InputStreamReader(
		new FileInputStream(fileName), "utf-8"));
String readContent = null;
while ((readContent = br.readLine()) != null) {
	pw.write(readContent+"\r\n");
	pw.flush();				
}
pw.close();

 

 读出的文件片断如下:

从上面输出的结果可以进一步证明生成的Sevlet就是UTF-8编码方式的存储的,因为这两个文件内容乱码显示的样子都是一样的。

 

从最开始来看在浏览器中能正常显示,那说明生成的Servlet类文件真实的内容没有毁坏,不然不可能在浏览器中能正常显示的,我们要坚信这一点。那既然文件内容没有毁坏,为什么生成的Servlet类文件却显示的是乱码呢?

 

经过我的一些分析,原因大致如下:

服务器在读取Jsp源文件时是采用的ISO8859-1来读取的(这是因为页没有配置任何编码信息),而Jsp源文件本身却又是GBK编码的,这一读的过程为字符解码过程,且又是以ISO8859-1来解的(会把GBK编码每个字节映射到ISO8859-1字符集下,而每个字节的大小为0-255,在ISO8859-1字符集里是可以找到对应的字符来替代的),这一转换过程并不会丢失任何编码信息,只是字符的显示方式不同而已了(GBK是一个个汉字的显示,而ISO却是半个半个地显示)。

而在读取完后放在内存里以Unicode形式存在(即ISO字符以Unicode编码存储,而非原来ISO编码,这一过程由Java完成,但ISO的编码实质上与Unicode编码是一样的,只是所占字节数不一样),再以UTF-8输出时,由于这些Unicode字符在UTF-8字符集编码里是存在的,并为上面显示的那些字符(实质上这些字符就是ISO字符集中的字符),也不会造成编码信息丢失。

既然我们知道了是这样一过程:GBK文件——》以ISO8859-1来读(解码)——》以UTF-8输出(编码),那我现在还她一个眉目清秀,先以UTF-8来读生成的Servlet文件(解码),然后以ISO8859-1来编码(这样就回到了服务器以ISO8859-1读取的内容了),最后以GBK来解码(就回到了最原始的Jsp文件了),最后...当然是现原型了(狐狸精一个啊,不过还是挺美的哦),一切显示正常,回到了过去。

以下是代码实现:

String fileName = "E:/tomcat-5.5.23/work/Catalina/localhost/HttpStream/org/apache/jsp/gbk_jsp.java";
PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(
		"e:/tmp/gbk_jsp.java"), "UTF-8"));
BufferedReader br = new BufferedReader(new InputStreamReader(
		new FileInputStream(fileName), "utf-8"));
String readContent = null;
while ((readContent = br.readLine()) != null) {
	pw.write(new String(readContent.getBytes("iso8859-1"), "gbk") + "\r\n");
	pw.flush();
}
pw.close();

结果如何,看看下面小小的截图便知:

 

 

  • 大小: 6.6 KB
  • 大小: 10.7 KB
  • 大小: 10.8 KB
  • 大小: 6.6 KB
  • 大小: 890 Bytes
分享到:
评论

相关推荐

    java-servlet-api.doc

    当你的应用存储数据到Session中,或从Session中清除数据,Servlet都会通过HttpSessionBindingListener检杳什么类被绑定或被取消绑定。这个接口的方法会通报被绑定或被取消绑定的对象。 绪言 这是一份关于2.1版...

    这是我的第一个

    当我们第一次访问jsp的时候,tomcat需要吧jsp翻译成一个java文件,然后在编译成class文件,然后在运行。 --------------------- 作者:java_esky110 来源:CSDN 原文:...

    网上书店系统的原代码(jsp,servlet)

    这是本人本科毕业设计时做的一个系统,数据库是access,使用jsp,servlet,服务器是tomcat,数据库是BookShop文件夹下的.mdb文件,里面的.class文件请自己再编译一下放到相关目录下

    servlet_jsp_course:servlet jsp课程项目源码及教案

    原生文件上传(io操作)4,smartupload方式文件上传原生的smartupload对编码这一块没有做处理,导致上传中文名称的图片时文件名乱码,因此反编译并修改了smartupload代码,重新打成jar包。为支持中文命名的图片显示...

    JAVA程序员面试题

    JSP编译后是"类servlet"。Servlet和JSP最主要的不同点在于,Servlet的应用逻辑是在Java文件中,并且完全从表示层中的HTML里分离开来。而JSP的情况是Java和HTML可以组合成一个扩展名为.jsp的文件。JSP侧重于视图,...

    jsp内置对象的用法

    pageContext对象提供了对JSP页面内所有的对象及名字空间的访问,也就是说他可以访问到本页所在的SESSION,也可以取本页面所在的application的某一属性值,他相当于页面中所有功能的集大成者,它的本类名也叫...

    JSP存储过程过滤器用例

    1 用过滤器实现数据初始化 2 用过滤器实现中文编码转换 3 用servlet实现页面控件 4 sql2005 由于sql2000不支持对text类型的查询.sql2005则支持. 5 HashMap是随机从中取数据的.而采用LinkedHashMap即链表...

    java 面试题 总结

    动态INCLUDE用jsp:include动作实现 &lt;jsp:include page="included.jsp" flush="true" /&gt;它总是会检查所含文件中的变化,适合用于包含动态页面,并且可以带参数。 静态INCLUDE用include伪码实现,定不会检查所含文件的...

    搞定J2EE:STRUTS+SPRING+HIBERNATE整合详解与典型案例 (2)

    10.3.2 编写JSP页面helloWorld.jsp 10.3.3 编写控制器HelloWorldController.java 10.3.4 建立Spring的配置文档dispatcherServlet-servlet.xml 10.3.5 配置web.xml 10.3.6 启动Tomcat运行程序 10.4 Spring 的视图...

    jsp中文问题过滤器实现源码

    通过servlet过滤器来解决request的编码的设置。这个方法不需要改动原来的代码,比较好。现成的写好的过滤器代码,只要把它编译一下就可以用了.

    java面试宝典

    140、如何中SERVLET或JSP下载一个文件(如:binary,text,executable)? 36 141、使用useBean标志初始化BEAN时如何接受初始化参数 36 142、使用JSP如何获得客户浏览器的信息? 36 143、能象调用子程序一样调用JSP吗?...

    JSP显示中文问题的解决方案

    这两天在win98下装apache1.3.9加jserv和gnujsp1.0,jdk1.2.2,jsdk2.0 发现中文无法正常显示。要么乱码,要么出错。 经网友提醒,总结了以下几条... 3:在编译servlet和jsp时加入代码选项。编译servlet使用 javac -encodi

    千方百计笔试题大全

    140、如何中SERVLET或JSP下载一个文件(如:binary,text,executable)? 36 141、使用useBean标志初始化BEAN时如何接受初始化参数 36 142、使用JSP如何获得客户浏览器的信息? 36 143、能象调用子程序一样调用JSP吗?...

    Java Web编程宝典-十年典藏版.pdf.part2(共2个)

    2.8.3 在JSP页面中使用Include指令后,JSP不能编译 2.9 精彩回顾 第3章前人栽树后人乘凉 ——、JSP内置对象 3.1 本章学习任务 3.1.1 本章知识体系 3.1.2 实例开发任务 3.2 简化开发JSP内置对象概述 3.2.1 为什么...

    JSP程序设计实例教程(第2版)-电子课件第1章-Java-Web编程基础.pptx

    分层开发的特点 下层不知道上层的存在 仅完成自身的功能 不关心结果如何使用 每一层仅知道其下层的存在,忽略其他层的存在 只关心结果的取得 不关心结果的实现过程 JSTL通常会与EL表达式合作实现JSP页面的编码 JSP...

    《程序天下:J2EE整合详解与典型案例》光盘源码

    10.3.2 编写JSP页面helloWorld.jsp 10.3.3 编写控制器HelloWorldController.java 10.3.4 建立Spring的配置文档dispatcherServlet-servlet.xml 10.3.5 配置web.xml 10.3.6 启动Tomcat运行程序 10.4 Spring 的视图...

    搞定J2EE:STRUTS+SPRING+HIBERNATE整合详解与典型案例 (1)

    10.3.2 编写JSP页面helloWorld.jsp 10.3.3 编写控制器HelloWorldController.java 10.3.4 建立Spring的配置文档dispatcherServlet-servlet.xml 10.3.5 配置web.xml 10.3.6 启动Tomcat运行程序 10.4 Spring 的视图...

    搞定J2EE:STRUTS+SPRING+HIBERNATE整合详解与典型案例 (3)

    10.3.2 编写JSP页面helloWorld.jsp 10.3.3 编写控制器HelloWorldController.java 10.3.4 建立Spring的配置文档dispatcherServlet-servlet.xml 10.3.5 配置web.xml 10.3.6 启动Tomcat运行程序 10.4 Spring 的视图...

    超级有影响力霸气的Java面试题大全文档

     动态INCLUDE用jsp:include动作实现 &lt;jsp:include page="included.jsp" flush="true" /&gt;它总是会检查所含文件中的变化,适合用于包含动态页面,并且可以带参数。 静态INCLUDE用include伪码实现,定不会检查所含文件...

    外文翻译 stus MVC

    This article introduces Struts, a Model-View-Controller implementation that uses servlets and JavaServer Pages (JSP) technology. Struts can help you control change in your Web project and promote ...

Global site tag (gtag.js) - Google Analytics