Servlet一次乱码排查后的总结

由来

在写一个小小的表单提交功能的时候,出现了乱码,很奇怪request上来的参数全部是乱码,而从数据库查询出来的中文显示到页面正常,锁定肯定是request对象那里出了问题。后来经过排查,发现是我封装的框架中出了问题,总结为在setCharacterEncoding方法之前,调用了getParameter方法,导致字符集改变失败。没看过Tomcat实现Servlet的源码,貌似是一旦调用getParameter方法Request的参数就会全部被解析,从而再调用setCharacterEncoding就无效了。

原理解析

其实编码问题本质还是两点:

浏览器在封装Http请求的时候的编码和服务器在解析Http请求编码不一致
服务器返回数据的时候编码和浏览器解析不同。
那么我们就从这两点入手解析。

浏览器请求

在点击提交表单的那一刻,浏览器把表单内容封装成一个Http请求,数据通过a=1&b=2这样的形式直接请求服务器,表单值会被浏览器最一次urlencode,对于不同的请求方式编码不同:

Get和Post请求

浏览器会读取页面的编码(页面编码会在Content-type头中体现),用此编码对表单值做urlencode,那么到服务器的编码方式就是你Content-Type里的编码。很多通过JS提交表单为了规避浏览器的urlencode带来的编码混淆,会对数据首先做一次urlencode,这样在服务器上做一次urldecode既可(因为js做完urlencode后内容为ASCII字符,所以这样的字符无论浏览器用什么编码解码出来都是一样的)

AJAX请求

在Jquery中AJAX请求全部使用utf8编码封装请求,如果你的页面和项目用的非utf8编码,一定会出现乱码

浏览器地址栏直接输入带参数的地址

这种情况就比较复杂,不同的浏览器编码也不相同。Chrome之类的浏览器默认使用utf8编码(urlencode),而IE则使用GBK(死变态IE!!!)。

服务器端解码

对于服务器端我在此只讨论Servlet。

Get请求

对于Get请求,有两种方式解码:

在Servlet容器中设置,例如Tomcat设置URIEncoding="UTF-8",就会对Get请求用utf8解码(貌似Tomcat7会报无效,具体解决请百度,反正我不同这种方法)
String name = new String(request.getParameter("name").getBytes("iso-8859-1"),"GBK"));第一个编码就是你Servlet容器(例如Tomcat)里设置的编码,默认iso-8859-1,第二个参数就是你浏览器使用的编码格式。如果你用表单提交,那这个编码就是页面的编码(Content-Type里的charset=XXX),如果你直接用浏览器地址栏里敲,恭喜你,你得判断userAgent来使用不同编码了。这也是我为啥不提倡第一种方式,因为它遇到浏览器直接敲出来的参数就非常不灵活。
至于为什么要使用getBytes("iso-8859-1"),是因为在你浏览器用某种编码后,Servlet容器自作多情给你用iso-8859-1解码了一下,如果你设置了URIEncoding="UTF-8"它就会用utf8给你解码,运气好你浏览器用的也是这种编码,那解出来就直接用了,所以在ISO-8859-1的情况下你得再“原路返回”到二进制,重新用正确的编码解码一下。

**Post请求和Ajax请求
**
Post请求就比较简单一点了,同样你可以使用Get请求中的方法2来解决,不过比较麻烦,这时候我们就可以使用Servlet里的方法request.setCharacterEncoding方法设置你的解码类型,例如你的页面编码是utf8,表单则urlencode成utf8了,那么你在调用getParameter方法之前(记住,一定要之前!!在第一次调用getParameter之前!)使用setCharacterEncoding方法。 Ajax请求同理。

响应请求

响应也是相同道理,这回轮到服务器做编码,浏览器做解码。只需要设置response.setCharacterEncoding,就会自动在响应头的Content-Type中加入charset=XXX,返回的内容就可以被正常解析啦~

我想我说的相对比较清楚了,网上很多解决乱码的帖子都只是讲你加上某句代码就会解决,这样是不科学的,一定也要知道原理,也要知道每句代码背后做了哪些工作。其实我们在操作HttpServlet对象的时候,本质上是对Http头的一些信息做修改。

如果有什么问题或者理解错误的地方,欢迎指正讨论。

时间: 2025-01-21 07:15:56

Servlet一次乱码排查后的总结的相关文章

utf-8-spring mvc json返回中文乱码 配置后依然不好使

问题描述 spring mvc json返回中文乱码 配置后依然不好使 <context:annotation-config /> <context:component-scan base-package="may.web.action"></context:component-scan> <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMet

Servlet的中文乱码常用解决方法

Servlet的中文乱码常用解决方法 在servlet页面就出错了,打印出就是乱码,why? public class toDetail extends HttpServlet {  public void doGet(HttpServletRequest request, HttpServletResponse response)    throws ServletException, IOException {   response.setContentType("text/html&quo

servlet ajax-怎么用servlet获取oracle数据库信息后传递到jquery的ajax上进行验证

问题描述 怎么用servlet获取oracle数据库信息后传递到jquery的ajax上进行验证 package com.ibm.ajax.app1.entity; public class WebUser { private String uname; public WebUser(String uname){ this.uname=uname; } public String getUname() { return uname; } public void setUname(String u

servlet中的乱码问题(设置了utf-8)

问题描述 servlet中的乱码问题(设置了utf-8) 我在前端通过文本框获取一个值传到servlet中(前端测试过,可以确定不是前端问题),servlet中得到的值却是乱码 下面是servlet中的代码 public class selAllServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletExcepti

Servlet输出中文乱码的问题之Filter解决方法

Servlet输出中文乱码的问题之Filter解决方法 Filter过滤器的代码如下: package filter; import java.io.IOException; import java.util.Collection; import java.util.Iterator; import java.util.Map; import java.util.Set; import javax.servlet.Filter; import javax.servlet.FilterChain;

servlet 韩文乱码

问题描述 前端使用ajax向后台请求,韩文参数接收乱码:1.ajax使用Get方式,contentType:"application/json;charset=utf-8",,参数经过encodeURIComponent转码:2.单独运行servlet的那个java文件时,不会出现乱码,而且System.getProperty("file.encoding")打印结果为"UTF-8":3.开启tomcat后,servlet中打印的System.g

关于jsp和servlet中的乱码问题

在jsp和servlet的开发中,今天自己做的一个小例子中出现了中文乱码问题,用了许多方法,发现还是解决不了.最后我用了过滤器,才算终结. 此方法总结如下:在jsp页面中使用<%@ page pageEncoding="GB2312"%> ,这里的pageEncoding是GB2312,那么我们在过滤器web.xml中所使用的<param-value>GB2312</param-value>也为GB2312.总之一条:就是上述两者一致即可,比如同为U

Servlet+JDBC+MySQL乱码

问题描述 通过Get方式提交参数,url:http://localhost:8080/aaaa/light?nick="aaa"&mobile=""&prov="江西"&city="景德镇"&game="对对碰"Servlet里面的doGet代码:String nick = new String(req.getParameter("nick").getBy

jsp传参 servlet接收中文乱码问题的解决方法_JSP编程

在公司实习了8个月,一直都是做android和h5的,但是发现做程序连一点服务都不会该怎么办,所以最近开始学起了java,不知道是不是因为框架学多了,现在看起springmvc框架比以前看起来简单太多了,这里我是准备从hibernate开始学习,毕竟数据是根本嘛,首先我用的是hibernate+servlet,但是在jsp页面传参到servlet的时候中文一直乱码,我尝试了好多方法,最后还是解决了. 第一,首先看清项目的编码,jsp页面的编码 第二,修改tomcat 下面的server.xml文