JSP页面中文乱码解决方案和pageEncoding,contentType的作用

       如果你已经在JSP开发中为页面中文乱码而花费不少时间的话,那么不妨再花费一点时间来看下以下内容,希望对你有所帮助(本文更注重讲述博主自己的理解过程)

       以下内容需了解get,post提交方式

       以下内容需对JSP的request对象和response对象有一定的了解

       博主想强调的是,我是抱着复习和抛砖引玉的心态写下这篇博客,文章中肯定存在着不足,博主希望自己的理解能帮助到一部分人,也很高兴的接受所有的关于文章中不足之处的指点。

       文章部分原理的真实性没有验证,但是具有一定的可靠性(代码认证),博主目前是大三学子,页面乱码也曾经遇到过,反复琢磨过很多次,才有这些不一定正确但是可以帮助博主自己理解的见解,在此分享给各位网友。  下面进入正题

首先,我们要有这样一个观点,A和B两者互相发送数据,数据在网络中是以bit传输的,我们以A发送数据给B为例,在A这边涉及从数据到bit的转化(即编码),在B这边涉及到从bit到数据的转化(即解码),

 

如上图所示(图的格式可能不太好,体谅一下)很明显,如果A对数据的编码方式和B对bit的解码方式不一致的话,势必会导致B在将bit还原成数据时,造成数据显示错误,即乱码现象。(注:在JSP开发中图中的A端既可以当做web服务器,也可以当做客户浏览器,因为客户浏览器在访问资源时也会发送数据,同时也会接收web服务器端响应的数据)

如果想解决这个问题,那么我们应该怎么办,很简单,有两种方法:

①A,B双方都默认采取同一种方式对数据进行编码和解码(在JSP中采用的是“ISO-8859-1”)

②A在发送的数据里加上一段通知信息,这段通知信息可以通知B端在A端是怎么进行编码的,这样B端接受到数据后,就可以用同样的方式来解码了

 

我们模拟一个这样的情况,A端作为客户浏览器端,B端作为web服务器端,A端发送一个URL请求,请求B端的一个test.jsp文件,这个jsp的作用就是将用户的用户名(userId)在浏览器的窗口内显示出来。(其中用户要发送的数据我们假定就是指userId,因为这在实际开发过程是我们比较关注的,这样减小了问题的规模,而服务器则发送响应的数据。同时我们也应要有这样的意识,不应麻烦客户,客户只需要访问提交便足够了,编码和解码对客户来说是透明的,所有这些工作,都应由服务器端去做好或者说由服务器端去适应客户

下面我们从客户浏览器发送数据到web服务器来说明:

我们知道URL请求有get,post方式(博主是初学JSP,所关注到的这有这两种,如果有更多的或者不正确的地方,欢迎评论),这两种方式所采取的编码是不同的:

get:我们先说get的形式,在URL中可以通过在URL地址后面添加一个?userId=ID(这个ID可以是英文或者中文字符),譬如http://localhost:8080/Test/test.jsp?userId=Planck 或者是 http://localhost:8080/Test/test.jsp?userId=普朗克,根据上面的假设,那么浏览器会对这个userId=Planck(userId=普朗克)进行编码,这里要强调的是,浏览器对于这里面的内容是默认采取“ISO-8859-1”的方式进行编码的(注“ISO-8859-1”不能显示中文),这也是为什么我们在test.jsp中,即使调用了request.serCharacterEncoding("utf-8")之后,客户浏览器还是会显示乱码的原因,setCharacterEncoding("utf-8")只能让服务器将bit流按照utf-8的格式进行解码,而客户浏览器那边是采用ISO-8859-1编码的,是以在服务器接收并转码的时候,内容就已经不对了。有以下解决办法(体现由服务器去适应客户端,当然这种在后面添加?userId=ID的方式现在基本没看见了,更多的是用户在网页中的表单中去输入ID

<%
    String userId=new String(request.getParameter("userId").getBytes("ISO-8859-1"),"utf-8");   //此处是将ISO-8859-1的数据转化为utf-8的数据
%>

post:我们以表单post提交来说,首先是用户访问服务器,服务器返回数据,客户浏览器得到一张表单,用户在表单中进行填写ID,例如163邮箱界面,我们借来说明表单

注意这种post的方式是会先从服务器得到一个页面(取名login.jsp),然后用户输入数据,点击登录后跳转到test.jsp页面,test.jsp页面应该要显示用户的userID,那么我们(或者说服务器)怎么知道userID的编码呢,或者说有没有好的办法,不至于每次都要重新转成utf-8格式,我们注意到有一个login.jsp,我们可以通过response.setCharacterEncoding("utf-8")来设置login.jsp的编码格式,这样客户浏览器端会将login页面的编码显示为utf-8的格式,那么对于login页面里面的数据自然也是utf-8格式了,然后客户浏览器post提交后,会转向test.jsp,我们只需要在test.jsp中通过request.setCharacterEncoding("utf-8")便可以正确解码了(在这里希望大家注意的是,我们是先请求的login.jsp,此时用户不需要传递userID,而服务器端设置login.jsp的编码格式为utf-8,之后用户才得到编码格式为utf-8的login页面去填写表单,然后提交,服务器这时才得到了userID)

图示如下:

通过图片,我们不难发现,恰好是我们通过设置login.jsp的编码方式和设置test.jsp的解码方式使得用户根本不需要去设置或者担心页面编码,这部分的工作在服务器端就做好了。

浏览完上面内容我们不妨先小小的总结一下:

get方式:浏览器默认采取“ISO-8859-1”方式去编码数据,所以我们在test.jsp(服务器端)中设置setCharacterEncoding("utf-8")是没用的,(那么有人会说那么设置setCharacterEncoding("ISO-8859-1")不就行了?很显然我们开头就说了,针对的中文乱码,而ISO-8859-1是不显示中文的。)可以通过上文中提到的方法,便可以保证我们服务器能正确对浏览器的数据进行解码。

post方式:通过login.jsp设置response.setCharacterEncoding("utf-8") 和test.jsp中设置request.setCharacterEncoding("utf-8")便可以保证我们服务器能正确对浏览器的数据进行解码

从总结我们可以看到,上面保证了服务器能对客户端发来的数据(我们只讨论了userId,因为这是我们比较关心的)进行正确的解码,那么接下来便是要客户浏览器能对服务器发送来的数据能正确解码了。

下面我们从web服务器发送数据到客户浏览器来说明:

      基于这种情况其实比较简单,只要告知浏览器服务器使用的编码是什么即可,然后客户端会根据服务器的通知来对bit流进行解码,所以问题又回到了服务器端,服务器通知用户浏览器编码格式的方法如下:

①response.setCharacterEncoding("utf-8);

②<%@ page contentType="text/html;charset=utf-8"%>

③<%@ page pageEncoding="utf-8"%>(这个指令原本的作用并不是体现在这,具体下面还会介绍)

其中三者优先级为①>②>③ 即若同时存在①和② 则服务器会将数据按照①提供的编码格式对用户发来的数据进行编码,客户端浏览器也会按照①的编码格式进行解码,很巧妙的是,如果三个语句你都没有,那么服务器会默认按照ISO-8859-1对数据进行。

讲到这里,实际大体上的问题已经解决了,但是我们在学习jsp的时候还遇见了<%@page pageEncoding="utf-8"% contentType="text/html;charset"%>,那么这个有什么用呢?请看下面的分析

我们都知道,web服务器对于.jsp文件,会先将其转化成.java文件,然后编译这个.java文件,生成.class文件,最终执行这个.class文件,然后生成客户浏览器需要的数据,那么这里可以分为4个文件3个过程,请看下面的图解:

从上图我们能够很清楚的知道pageEncoding和contentType中charset的作用,图中①过程可以简化为开发者编码和服务器解码的过程,开发者需通过pageEncoding来告知服务器自己的编码格式,然后服务器就会按照开发者提供的编码格式去解码。(下面会有代码和结果展示)

知道了pageEncoding和contentType中charset的作用后,我们还需要注意的是:

①当pageEncoding没指定而contentType中charset指定了编码格式时,则pageEncoding的编码格式会默认与contentType中charset一样,同理当contentType中charset没指定而pageEconding指定了编码格式时,contentType中charset的编码格式会默认保持与pageEncoding一致

②如果两个都没指定,二者皆默认为"ISO-8859-1"

下面是代码和测试结果,我们只观察图中的①过程:

首先是pageEncoding和contentType中charset都未指定的情况:

然后我们查看其生成的setContentType_jsp.java文件的内容:

然后是指定contentType中charset为utf-8的情况(pageEncoding我这里就不展示了,因为pageEncoding是作用于.jsp->.java这个过程,我们应更关心当pageEconding未指定而contentType中charset指定时,pageEncoding是否会与contentType中charset保持一致):

于是我们可以修改代码为:

然后我们查看其生成的setContentType_jsp.java文件的内容:

可以看到结果如同之前提到的一样

文章已经到最后了,能耐心看到这里,博主表示衷心的感谢,希望这篇博客对你有所帮助。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值