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");

修正:

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://m.imooc.com/article/18897
http://blog.51cto.com/yuehaoyisheng/1324709
```

目录
相关文章
|
15天前
|
JSON Java 数据格式
java操作http请求针对不同提交方式(application/json和application/x-www-form-urlencoded)
java操作http请求针对不同提交方式(application/json和application/x-www-form-urlencoded)
66 25
java操作http请求针对不同提交方式(application/json和application/x-www-form-urlencoded)
|
13天前
|
Web App开发 大数据 应用服务中间件
什么是 HTTP Range请求(范围请求)
HTTP Range 请求是一种非常有用的 HTTP 功能,允许客户端请求资源的特定部分,从而提高传输效率和用户体验。通过合理使用 Range 请求,可以实现断点续传、视频流播放和按需加载等功能。了解并掌握 HTTP Range 请求的工作原理和应用场景,对开发高效的网络应用至关重要。
53 15
|
17天前
|
数据采集 JSON 测试技术
Grequests,非常 Nice 的 Python 异步 HTTP 请求神器
在Python开发中,处理HTTP请求至关重要。`grequests`库基于`requests`,支持异步请求,通过`gevent`实现并发,提高性能。本文介绍了`grequests`的安装、基本与高级功能,如GET/POST请求、并发控制等,并探讨其在实际项目中的应用。
26 3
|
22天前
|
前端开发 UED 开发者
CSS Sprites和图标字体在网页图标加载优化中的应用。CSS Sprites通过合并多图标减少HTTP请求,提升加载速度
本文探讨了CSS Sprites和图标字体在网页图标加载优化中的应用。CSS Sprites通过合并多图标减少HTTP请求,提升加载速度;图标字体则以字体形式呈现图标,便于调整样式。文章分析了两者的优缺点及应用场景,并提供了应用技巧和注意事项,旨在帮助开发者提升页面性能,改善用户体验。
23 5
|
1月前
|
JSON API 数据格式
Python中获取HTTP请求响应体的详解
本文介绍了如何使用Python的`requests`和`urllib`库发送HTTP请求并处理响应体。`requests`库简化了HTTP请求过程,适合快速开发;`urllib`库则更为底层,适用于性能要求较高的场景。文章详细演示了发送GET请求、处理JSON响应等常见操作。
45 3
|
1月前
|
安全 API 网络安全
使用OkHttp进行HTTPS请求的Kotlin实现
使用OkHttp进行HTTPS请求的Kotlin实现
|
14天前
|
Web App开发 网络安全 数据安全/隐私保护
Lua中实现HTTP请求的User-Agent自定义
Lua中实现HTTP请求的User-Agent自定义
|
1月前
|
前端开发 JavaScript Java
如何捕获和处理HTTP GET请求的异常
如何捕获和处理HTTP GET请求的异常
|
1月前
|
开发者
HTTP 协议请求方法的发展历程
【10月更文挑战第21天】
|
1月前
|
安全
HTTP 协议的请求方法
【10月更文挑战第21天】

热门文章

最新文章