最近做一个项目,前台传到后台的数据是乱码。看着代码应该是正确的,但是就是有问题,然后请教了旁边的老司机才找到问题是什么。话不多说,下面是模拟情景的代码,其实也很简单,前台一个form表单,post  方法,然后传一个中文字符串到servlet。 如果第一次调用request,不是设置字符编 码(req.setCharacterEncoding("utf-8");)而是调用其他的request 方法,那么设置的字符编码不会成功。

前端模板:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="/post" method="post">
用户名<input type="text" name="name">
<input type="submit" value="提交">
</form>
</body>
</html>

Java 代码

package cn.servlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; @WebServlet("/post")
public class TestPost extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String cmd = req.getParameter("cmd");
list(req, resp); } public void list(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
String name = null;
if (req.getParameter("name") != null && !"".equals(req.getParameter("name"))) {
name = req.getParameter("name"); System.out.println("name-------------------------->>>:" + name); }
}
}

如上代码:request  首先调用 req.getParameter("cmd");然后再是  req.setCharacterEncoding("utf-8");出现的原因是request 在传入的时候如果不设置req格式,在第一次调用req 的时候tomcat 会自动的给req 增加字符格式 ,后面再设置 req.setCharacterEncoding("utf-8")就会无效。

要修改就很简单了①:把form 表单改为get

②: req.setCharacterEncoding("utf-8"); 声明在第一行,或者filter  里面做字符处理

③:

String  name = req.getParameter("name");

byte[] nameBytes = name.getBytes("ISO-8859-1");

name = new String(nameBytes,"utf-8");

以下文章是摘自

http://my.oschina.net/looly/blog/287255?p=2&temp=1470195279778#blog-comments-list

由来

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

原理解析

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

  1. 浏览器在封装Http请求的时候的编码和服务器在解析Http请求编码不一致
  2. 服务器返回数据的时候编码和浏览器解析不同。

那么我们就从这两点入手解析。

浏览器请求

在点击提交表单的那一刻,浏览器把表单内容封装成一个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请求,有两种方式解码:

  1. 在Servlet容器中设置,例如Tomcat设置URIEncoding="UTF-8",就会对Get请求用utf8解码(貌似Tomcat7会报无效,具体解决请百度,反正我不同这种方法)
  2. 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头的一些信息做修改。

tomcat中的get、post区别的更多相关文章

  1. Tomcat中HTTP与AJP区别

    Tomcat: HTTP与AJP区别 Tomcat服务器通过Connector连接器组件与客户程序建立连接,Connector组件负责接收客户的请求,以及把Tomcat服务器的响应结果发送给客户. 默 ...

  2. e.Tomcat中的sendfile支持

    sendfile实质是linux系统中一项优化技术,用以发送文件和网络通信时,减少用户态空间与磁盘倒换数据,而直接在内核级做数据拷贝,这项技术是linux2.4之后就有的,现在已经很普遍的用在了C的网 ...

  3. JSP中pageEncoding和charset区别,中文乱码解决方案(转载)

    转载自:JSP中pageEncoding和charset区别,中文乱码解决方案 JSP指令标签中<%@ page contentType="text/html;charset=GB23 ...

  4. 在Tomcat中采用基于表单的安全验证

    .概述   (1)基于表单的验证 基于From的安全认证可以通过TomcatServer对Form表单中所提供的数据进行验证,基于表单的验证使系统开发者可以自定义用户的登陆页面和报错页面.这种验证方法 ...

  5. 深度解读Tomcat中的NIO模型(转载)

    转自https://www.jianshu.com/p/76ff17bc6dea 一.I/O复用模型解读 Tomcat的NIO是基于I/O复用来实现的.对这点一定要清楚,不然我们的讨论就不在一个逻辑线 ...

  6. 在tomcat中加入SSL腾讯云证书的步骤

    在tomcat中加入SSL证书,可以用https方式访问域名,增加域名的安全性.当然也有很多应用要求https访问,也是安全性的考虑.阿里云和腾讯云都提供SSL证书,还有一些其他的大公司也提供,我这里 ...

  7. 在本地运行正常的静态网页放到tomcat中却显示异常的原因

    在本地写好了一个个人网站,本地直接用浏览器运行,很顺利,然而把网站放到Tomcat里面,却发现图片显示不出来,这就奇怪了. 后来发现,我的网站的Image文件夹用了大写“I”,而网页里面的路径用了小写 ...

  8. springboot项目发布到独立的tomcat中运行&打成jar包运行

    springboot的打包方式依赖于插件:(下面插件打出的包与普通的包目录结构有区别) <plugin> <groupId>org.springframework.boot&l ...

  9. Tomcat中Pipeline

    Pipeline 节选部分源码.源码版本 Tomcat8.5 处理模式 Pipeline--Valve是一种责任链模式,它和普通责任链模式有两点区别: 每个Pipeline都是有特定的Valve,而且 ...

  10. maven项目如何启动运行---发布到tomcat中

    前面两篇文章: 新建maven框架的web项目 以及 将原有项目改成maven框架 之后,我们已经有了maven的项目 那么 maven项目到底怎么启动呢 如果我们直接在myeclipse中按以前的启 ...

随机推荐

  1. [Angular 2] Select From Multiple Nested Angular 2 Elements

    You have complete control over the elements you nest inside of your component instance by using sele ...

  2. Map生成器 map适配器如今能够使用各种不同的Generator,iterator和常量值的组合来填充Map初始化对象

    Map生成器 map适配器如今能够使用各种不同的Generator,iterator和常量值的组合来填充Map初始化对象 package org.rui.collection2.map; /** * ...

  3. Java虚拟机工作原理具体解释

    一.类载入器 首先来看一下java程序的运行过程. 从这个框图非常easy大体上了解java程序工作原理.首先,你写好java代码,保存到硬盘其中.然后你在命令行中输入 javac YourClass ...

  4. Linux下判断cpu物理个数、几核

    自己服务器的输出 1. 查看物理CPU的个数   #cat /proc/cpuinfo |grep "physical id"|sort |uniq|wc -l    1 2. 查 ...

  5. windows 8.1 在硬盘上创建扩展分区

    管理员-命令提示符-> diskpart    -->进入分区工具. list disk     -->显示电脑连接磁盘数. select disk *  -->选择编号为*的 ...

  6. uva 12096 The SetStack Computer

    点击打开链接uva 12096 思路: STL模拟 分析: 1 题目给定5种操作,每次输出栈顶集合的元素的个数 2 利用stack和set来模拟,set保存集合的元素.遇到push的时候直接在stac ...

  7. The Kernel Newbie Corner: Kernel Debugging with proc "Sequence" Files--Part 2

    转载:https://www.linux.com/learn/linux-career-center/39972-kernel-debugging-with-proc-qsequenceq-files ...

  8. BootStrap2学习日记20---定制缩略图

    先看看效果: 代码: <ul class="thumbnails"> <li class="span3"> <div class= ...

  9. js字符串的各种格式的转换 ToString,Format

    1.转换钱的格式,仅限int型,float型,double型 double d = 400; d.ToString("C"); //¥400.00 2.10进制数,仅限int型的数 ...

  10. struts2与cookie实现自动登录和验证码验证

    主要介绍struts2与cookie结合实现自动登录 struts2与cookie结合时要注意采用.action 动作的方式实现cookie的读取 struts2的jar包 链接数据库文件 db.pr ...