开发者社区> codingcoge> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

Http请求和响应的编码问题

简介: 前言: 今天来谈谈Tomcat服务器和网页之间编码和解码之间的关系。关于URL编码的问题可以看链接:廖雪峰修正:百度现在编码也是UTF-8 关于编码之间的转换问题可以看链接:编码转换问题 浏览器端的编码: 默认解码是GB2312影响form提交数据的编码的因素包括:form的accept-charset属性、html文档的编码方案即document.charset。
+关注继续查看

前言:

今天来谈谈Tomcat服务器和网页之间编码和解码之间的关系。
关于URL编码的问题可以看
链接:廖雪峰
修正:百度现在编码也是UTF-8

关于编码之间的转换问题可以看
链接:编码转换问题

浏览器端的编码:

默认解码是GB2312
影响form提交数据的编码的因素包括:form的accept-charset属性、html文档的编码方案即document.charset。其中,form的accept-charset是否能够有效,依赖具体浏览器的实现,有些浏览器并不支持,如IE。文档编码方案可以通过document.charset来修改。

浏览器端的解码:

默认解码是GB2312
这个是国情所致,不管是windows还是linux都是如此,除非自己设置。

通常来说,浏览器会先按照Content-Type的编码设置来解析文本,然后在解析过程中发现charset设置,再更换编码重新读取。若Content-Type没有设置编码,或者说这个HTML文件根本就不是走的HTTP协议,浏览器通常会猜测编码来解析文本,然后发现charset设置再更换编码读取。

来做个测试:
写了一个网页 没有声明meta等编码格式,但是文本是UTF-8编写的。
这时候浏览器打开该网页,发现乱码问题。
然后后台接受数据

request.setCharacterEncoding("GBK"); //或者GB2312
System.out.println(request.getParameter("name"));

输出结果不是乱码。
替换:

request.setCharacterEncoding("UTF-8"); //或者不写
System.out.println(request.getParameter("name"));

就根据request默认编码格式 iso-8859-1出现乱码。

浏览器的数据体解码方案依赖返回信息。
a) 浏览器首先从返回头header中查找编码方案标注(Content-Type),举个栗子:

response.setHeader  
("content-type", "text/html;charset=utf-8");  

b)如果没有标注,在得知返回内容为html内容的话,将从head的meta标签中读取,举个栗子:

 <meta http-equiv=Content-Type  
 content="text/html;charset=utf-8">

c)如果还没找到,浏览器就不知道如何解码,会消极的选择一种解码方案。默认解码是GB2312

在理论上,推荐html文档在meta中声明编码,且编码的声明一定要在文件开始的1024字节内完成,所以最好在head标签开始时立即声明。

总结:服务器的编码解码主要是看:

1. 头header中meta的编码方案
2. html文档的编码方案 
3. form的accept-charset编码方案

只要页面声明了charset什么格式,那么编码和解码就什么格式。


服务器端的编码:

中文版的浏览器一般会默认的使用GBK,通过设置浏览器也可以使用UTF-8,可能不同的用户就有不同的浏览器设置,也就造成不同的编码方式,所以很多网站的做法都是先把url里面的中文或特殊字符用 javascript做URL encode,然后再拼接url提交数据

Tomcat8以上默认是UTF-8

所以编码默认是UTF-8

所以getBytes()是默认采用UTF-8 还可以选择编码格式。
举个栗子:

response.getOutputStream().write  
("22这d是一个字节输出".getBytes("GBK"));

分析:

response存放的格式是GBK 浏览器默认是GBK打开正常显示
如果改为.getBytes()则为UTF-8 浏览器打开就会乱码

总结:
HttpServletResponse跟HttpServletRequest默认编码不一样
HttpServletResponse默认编码不是iso-8859-1,而是取决于直接存入的编码格式,意思取决于getBytes
默认应该是在doGet方法中,因为浏览器默认是以Get方式访问Servlet。

设置浏览器解码格式

response.setHeader("Content-type", "text/html;  
charset=UTF-8");

如果修改的话 可以看这一篇 很详细:

https://blog.csdn.net/jiangwei0910410003/article/details/22886847

修正:

response.getWriter().write();的默认编码是UTF-8
response.getOutputStream().write(string.getBytes());  
默认编码格式是UTF-8

完整栗子:

response.setHeader("Content-type", "text/html;charset=UTF-8");
response.getOutputStream().write("22这是一个字节输出".getBytes());
response.getWriter().write("哈哈对是");

输出:

22这是一个字节输出

总结:

  1. getOutputStreamgetWriter这两个方法互相排斥,调用了其中的任何一个方法后,就不能再调用另一方法。
  2. getOutputStream()和getWriter()可以层叠使用。
  3. Serlvet的service方法结束后,Servlet引擎将检查getWriter或getOutputStream方法返回的输出流对象是否已经调用过close方法,如果没有,Servlet引擎将调用close方法关闭该输出流对象。

服务器端的解码:

这块是我认为最难理解的。……
可以参考这篇:

https://blog.csdn.net/qq_38409944/article/details/80633743

  1. Tomcat8以上版本默认编码格式是UTF-8
  2. HttpServletRequest和HttpServletResponse容器默认编码格式是iso-8859-1

Get和Post解码格式:
request容器保存的是浏览器的数据,一般是UTF-8格式。
request的方法如:getParameter解码格式会根据Get和Post来设置解码格式。

1. Get默认解码格式是Tomcat8编码格式。所以URL解码是UTF-8,
覆盖掉了request容器解码格式
2. Post默认解码格式是request编码格式。与Tomcat8编码格式无关

从浏览器发起的访问方式有三种:

request乱码指的是:浏览器向服务器发送的请求参数中包含中文字符,
服务器获取到的请求参数的值是乱码;

一般默认浏览器传递过来的数据是UTF-8格式。
对于传输的数据 有两种方式传输 一种是Post一种是Get 对于不同方式传递过来的数据。解码方式又是不同的。

Get是放在URL参数
Post是放在实体内容里 

但都可以通过HttpServletRequest request来解码

在地址栏直接输入URL访问、
点击页面中的超链接访问、
提交表单访问。

第一种访问方式浏览器默认将参数按照utf-8进行编码,
后面两种访问方式浏览器将参数按照当前页面的显示编码进行编码。所以对于request乱码,只需要在服务器端设置相应的解码格式即可。由于访问方式不同,浏览器对参数的编码格式也不同,为了方便处理,通过超链接和表单的访问也规定必须是utf-8格式,即显示当前页面的编码也要使用utf-8,这样浏览器将统一使用utf-8对参数进行编码。

在服务器端,通过request.setCharacterEncoding("utf-8”)即可设置服务器response容器的编码为utf-8(默认是ISO-8859-1),
但是它只对请求体里面的参数有效;
如果参数跟在请求行中的uri后边,它就无能为力了。因此请求方式不同,解决乱码的方案也不同。

通过修改server.xml指定服务器对get和post统一按照utf-8解码,要求tomcat管理下的所有web应用都要使用utf-8编码
结论: 约定很重要,网站一般采用UTF-8作为默认编码。如果不是特殊需求,不要变换成其他编码。

总结:get请求建议尽量不带中文参数

https://www.cnblogs.com/caowei/p/2013-12-11_request-response.html
https://blog.csdn.net/jiangwei0910410003/article/details/22886847
https://m.imooc.com/article/18897
http://blog.51cto.com/yuehaoyisheng/1324709

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
HTTP请求和响应过程
HTTP请求和响应过程 1.HTTP协议   Internate的基本协议是TCP/IP(传输控制协议和网际协议)。而目前使用的FTP,HTTP都是建立在TCP/IP上的应用层协议。
787 0
HTTP协议相关概念(一)
HTTP协议相关概念(一)
9 0
HTTP协议相关概念(二)
HTTP协议相关概念(二)
16 0
Http实战之无状态协议、keep-alive分析(2)
Http实战之无状态协议、keep-alive分析(2)
24 0
http协议概念
http协议概念
13 0
HTTP协议的几个重要概念
    1.连接(Connection):一个传输层的实际环流,它是建立在两个相互通讯的应用程序之间。   2.消息(Message):HTTP通讯的基本单位,包括一个结构化的八元组序列并通过连接传输。
733 0
超文本传输协议 -- HTTP/1.0 Hyptertext Transfer Protocol
组织:中国互动出版网(http://www.china-pub.com/)RFC文档中文翻译计划(http://www.china-pub.com/compters/emook/aboutemook.htm)E-mail:ouyang@china-pub.com译者:黄晓东(黄晓东  xdhuang@eyou.com)译文发布时间:2001-7-14版权:本中文翻译文档版权归中国互动出版网所有。
1744 0
+关注
codingcoge
种一棵树最好的时间是十年前,其次是现在。 java自学后台ing,请多指教 Github: https://github.com/jjc123
文章
问答
文章排行榜
最热
最新
相关电子书
更多
阿里巴巴HTTP 2.0实践及无线通信协议的演进之路
立即下载
数据智能人机交互实践
立即下载
低代码开发师(初级)实战教程
立即下载