如何解决JAVA WEB应用开发中的中文问题?
中文乱码问题是JAVA WEB开发新手经常碰到的问题,这个问题其实不复杂,只要开发者对WEB开发整个环境有清楚的认识,还是很容易解决的。因为Java语言内部是使用UNICODE表示字符串的,所以进入JVM和离开JVM的字符串都需要转换成UNCODE形式。
在JAVA WEB开发过程中,程序的部份是JSP或者HttpServlet,字符串有三个主要的进入点:html form、源程序、外部数据源(常见有数据库和资源文件)。
先说说源程序。
我们经常会在源程序里写一些文本,特别是在JSP里,“写”的时候是通过编辑器保存成文件的,所以首先要搞清楚的是:编辑器把文件保存成什么编码格式了?以VIM为例,它会以系统默认语言编码来保存文件,比如在MS Windows里区域设成中国,那么会以cp936编码字符串,cp936其实就是GB2312。但可以通过:set encoding或者:set fileencoding来改变。
接下来源程序要被编译器转换成字节码,其中jsp要先编译成.java,然后跟Servlet一样编译成.class,要保证编译器以正确的编码读入源文件,然后编译器就能以正确的格式转换并将字符串写进字节码里。
最后,JVM会加载字节码,并将字符串以UCS16的形式放在内存里。只要前面各步转换过程无误,这一步就能正常工作。这个环节,应用开发及布署人员无法控制的。
源程序里的字符串又可以分成两种,jsp里的静态部份以及由程序动态输出的部份。jsp在经过编译成.java后,也会变成通过out.print()输出,实际上跟用程序输出的部份没有本质的区别。对于Servlet或者jsp里的scriptlet来说,硬编码进字符串常量并不是一个好习惯,但是对于国际化要求不高的应用确实非常方便,还是经常会有人这样做的。
静态文本只要上面提到的各步转换无误,最后就能正确的进入Servlet Container了。
再说外部数据源。
外部数据源里的字符串会以某种格式编码保存着,通过一个转换程序被读进来。对于一般文件来说,这个转换程序是iostream库,对于resouce bundle文件来说转换过程是ResouceBundle的property读取方法,对于数据库来说是JDBC Driver里ResultSet的getString()方法。这里面潜藏着:字符串是以何种编码保存在存储器里,服务程序(文件系统或DBMS)是以何种编码传递给转换程序的,服务程序在传递之前是否进行过编码转换及转换是否正确,转换程序认为会收到的编码与实际收到的编码是否一致,转换程序工作是否正常等多个问题。不过说着复杂,其实写程序还是很简单的,无非给jdbc url加个参数指示编码格式或者在构造Reader时加个Charset参数,只有碰到问题时,才需要一步一步排查。
最麻烦的,就是最重要的html form。
form是WEB应用中用户输入信息的主要手段,form由浏览器显示,并在用户点击submit之后将其内容打包通过http协议提交给服务器端。
form通常会以GET或者POST方法提交,两种情况下浏览器传送的方法会略有不同。GET只能是
application/x-www-form-urlencoded,form字段是做为url的一部份提交的;而POST可能是
application/x-www-form-urlencoded或者
multipart/form-data,form字段是做为http包的内容提交的。这个差异会导致某些应用碰到某些form需要从ISO 8859_1转码而另一些则无须转换直接就是对的。
现在的事实标准是浏览器将会以html页面本身显示时确定的字符编码,对form内的文字符串进行编码,然后上传。
WEB Container收到URL请求之后,会根据特写的映射机制发现应该转给Servlet Container
(Apache详见modjk)
,Servlet Container收到HTTP请求之后,会构造一个HttpServletRequest对象,然后根据url mapping将Request对象传给HttpServlet。
HttpServlet实例收到HttpServletRequest参数之后,可以调用getCharacterEncoding()方法查询字符编码格式,不过不幸的是,事实上该方法会返回null。不过根据浏览提交form的行为,收到Request里字符编码格式完全是可以预测的,所以先setCharacterEncoding()一下,HttpServletRequest就可以正常工作了。
关于html form提交中的编码问题,更进一步的说明可以参考这里。
品雪其寒
本文地址:http://www.45fan.com/a/question/71759.html