该片简要讲述:JSP页面传输过程中,浏览器与服务器的编码解码以及HTTP协议对URL进行的编码解码。

问题如下:

//所有的JSP页面的编码都是UTF-8的格式
//test1.jsp
<%@ page language="java" import="java.util.*,java.net.*" pageEncoding="UTF-8"%><a href="test2.jsp?str=<%=URLEncoder.encode("中国人","gb2312") %>">链接</a>//test2.jsp
<%@ page language="java" import="java.util.*,java.net.*" pageEncoding="UTF-8"%><%String name=  URLDecoder.decode(request.getParameter("str"),"gb2312");name =new String(name1.getBytes("ISO-8859-1"),"gb2312");
%><%=name %>

首先简要描述点击链接到页面显示过程:

点击链接 – 浏览器编码(HTTP URL 编码) – 服务器解码 – 构建返回数据体–服务器编码 – 浏览器解码。

POST请求不再多说,乱码主要发生在GET请求且URL后面追加了中文参数。

上述例子,过程应该是这样:

① 首先在页面中进行了URL编码

结果如下:

<a href="test2.jsp?str=%D6%D0%B9%FA%C8%CB">链接</a>
//这里手动进行URL编码,等效于浏览器对中文进行编码。
//因为参数在url上面,是GET请求,故而URL编码解码是浏览器和服务器的关系,与我们无关。
//如果不做设置,默认编码方式为是ISO-8859-1。

② 浏览器编码

点击查看浏览器端的编码。

  • 因为GET请求,只有URL(参数附加于URL),故只对URL进行编码。

  • 因为非直接在浏览器输入地址进行请求,而是点击文档内链接。故编码依据文档编码 —UTF-8

  • 因为JSP页面手动指定了编码格式,且进行了URL编码。

③ HTTP传输

数据在网络中以报文的形式,二进制流的格式进行传输。服务器拿到的path之后需进行解析。这个过程默认编码方案为ISO-8859-1。

至此,是这样子的:ISO-8859-1(UTF-8(<a href="test2.jsp?str=%D6%D0%B9%FA%C8%CB">链接</a>))

④ 服务器解码

web服务器接收到客户端的请求后,会将其内容转给web容器来处理;

因为接到的请求path(url)是编码过的二进制流,所以在处理前会将其转换成ASCII码 。但是请求中可能还有部分参数和消息体的数据是经过编码的(例如中文字符被编码),这里就涉及到对请求内容和参数进行解码的问题。

Tomcat 默认对url 使用 ISO-8859-1解码。注意:ISO-8859-1 为单字节表示。

所以,无论你前面浏览器进行了什么编码,尘归尘,土归土,一切都还原到字节(不过这里的字节是由特定字符集转换而来的,即 第一个页面的GB2312)!!!

在这里,剥去了外面的ISO-8859-1,剩下UTF-8(<a href="test2.jsp?str=%D6%D0%B9%FA%C8%CB">链接</a>)

⑤ 过程描述

原URL---->GET时浏览器根据HTTP头的Content-Type的charset,POST根据(content="text/html; charset=utf-8")对URL进行编码或者利用JavaScript(如果JavaScript编码了则浏览器一看都是ASCII字符就不再编码)使用GBK或者UTF-8等编码对URL进行编码
---->ASCII字符 + %
---->以iso-8859-1编码方式转换为二进制
---->随请求头一起发送出去(GET没有请求实体, POST有)
---->服务器接收到经过iso-8859-1编码后的URL
---->服务器用iso-8859-1编码进行解码
---->得到值(这里得到URL中文参数的字节信息)

⑥ Tomcat 返回响应

构建数据体,设置响应类型和编码(UTF-8)。。。

ContentType : text/html;charset=UTF-8

该过程中会拿到请求传过来的参数:

方法一:

 String name=  URLDecoder.decode(request.getParameter("str"),"gb2312");//此时name仍旧为乱码name=new String(name2.getBytes("ISO-8859-1"));//默认使用系统编码,可使用System.getProperty("file.encode");进行查看

Charset.defaultCharset()方法如下所示:

   public static Charset defaultCharset() {if (defaultCharset == null) {synchronized (Charset.class) {String csn = AccessController.doPrivileged(new GetPropertyAction("file.encoding"));Charset cs = lookup(csn);if (cs != null)defaultCharset = cs;elsedefaultCharset = forName("UTF-8");}}return defaultCharset;}

使用request.getParameter()获取的数据是被服务器误认为ISO-8859-1编码的,也就是说客户端发送过来的数据无论是UTF-8还是GBK,服务器都认为是ISO-8859-1,这就说明我们需要在使用request.getParameter()获取数据后,再转发成正确的编码。

如下所示,则正确解码:

 String name=URLDecoder.decode("%D6%D0%B9%FA%C8%CB", "gb2312");// name 中国人

注意,%D6%D0%B9%FA%C8%C直接使用gb2312解码可得到正确结果。但是如果使用request.getParameter获取str则会得到乱码ÖйúÈË

那么,为什么不直接使用ISO-8859-1获取字节,然后再使用GBK或者gb2312解码呢?URLDecoder.decode(request.getParameter("str"),"gb2312");完全就是多余了。

ISO-8859-1向下兼容ASCII,并且HTTP通信过程中默认使用的就是ISO-8859-1编码。

方法二:

String name=new String(request.getParameter("str").getBytes("ISO-8859-1"),"GBK");
//GBK GB2312 //String name2 = new String(request.getParameter("str").getBytes("ISO-8859-1"),"UTF-8")
//name2 ���

其中方法一首先进行了URL解码,其次直接使用new String([]bytes,charset)进行构建字符串。

方法二则直接使用new String([]bytes,charset)进行构建字符串。

服务器拿到的是字节流,因为 Tomcat 默认对URL使用ISO-8859-1进行解码,所以可以直接直接使用new String([]bytes,charset)进行构建字符串!需要注意的是这里的charset需要与页面进行URL编码时候的编码集一致。

方法三,使用request.getQueryString();获取Query String。

既然参数在URL后面,那么就在Query Data里面可以使用request.getQueryString();方法获取,如下所示:

String queryData = request.getQueryString();
//queryData: str=%D6%D0%B9%FA%C8%CB
//截取str 值,再使用URLDecoder.decode()即可。

⑦ 浏览器解析响应

浏览器拿到响应信息,开始进行解析。

首先会获取解码类型:UTF-8

点击查看浏览器解析过程。浏览器解析HTML文档


【Tips】:
这里说明一下何为URL编码解码:

编码:

URLEncoder.encode("中国人","gbk")
**即:`%D6%D0%B9%FA%C8%CB`**

将字符串以特定的编码格式转化成application/x-www-form-urlencoded 格式

根据2005年发布的RFC3986“%编码”规范:

  • 对URL中属于ASCII字符集的非保留字不做编码;
  • 对URL中的保留字需要取其ASCII内码,然后加上“%”前缀将该字符进行替换(编码);
  • 对于URL中的非ASCII字符需要取其Unicode内码,然后加上“%”前缀将该字符进行替换(编码)。

由于这种编码是采用“%”加上字符内码的方式,所以,有些地方也称其为“百分号编码”。

JAVA源码翻译:

解码则反之 。
点击查看Http协议中的编码解码


题外话 :

如果 第一个页面不进行URL编码呢?

<a href="test2.jsp?str=中国人 ">链接</a>-->

测试的谷歌浏览器:

如上图所示,浏览器会自动根据页面编码(UTF-8)进行URL编码。

可直接使用上述方法二进行获取。

String name=new String(request.getParameter("str").getBytes("ISO-8859-1"),"UTF-8");
//注意页面编码为UTF-8

需要注意JSP页面中的Java代码<%=name %>,其实对应编译后的 out.print(name);故而不需要再加;。另外out变量声明的对象为JspWriter,其类继承示意图如下:


⑧ 关于application/x-www-form-urlencoded等字符编码的解释说明

在Form元素的语法中,EncType表明提交数据的格式 用 Enctype 属性指定将数据回发到服务器时浏览器使用的编码类型。下边是说明:

application/x-www-form-urlencoded: 窗体数据被编码为名称/值对。这是标准的编码格式。multipart/form-data: 窗体数据被编码为一条消息,页上的每个控件对应消息中的一个部分。 text/plain: 窗体数据以纯文本形式进行编码,其中不含任何控件或格式字符。

form的enctype属性为编码方式,常用有两种:application/x-www-form-urlencoded和multipart/form-data,默认为application/x-www-form-urlencoded。

当action为get时候,浏览器用x-www-form-urlencoded的编码方式把form数据转换成一个字串(name1=value1&name2=value2…),然后把这个字串append到url后面,用?分割,加载这个新的url。

当action为post时候,浏览器把form数据封装到http body中,然后发送到server。

如果没有type=file的控件,用默认的application/x-www-form-urlencoded就可以了。

但是如果有type=file的话,就要用到multipart/form-data了。

浏览器会把整个表单以控件为单位分割,并为每个部分加上Content-Disposition(form-data或者file),Content-Type(默认为text/plain),name(控件name)等信息,并加上分割符(boundary)。

JSP页面请求响应过程中的编码解码相关推荐

  1. 卷积法求解系统的零状态响应_求解LTI系统零状态响应过程中的解法辨析

    求解 LTI 系统零状态响应过程中的解法辨析 马 丁 [摘 要] 摘要:利用卷积计算 LTI 系统的零状态响应时,单位冲激响应 h ( t ) 的求解是其中至关重要的一步.但用冲激平衡法及傅里叶反变换 ...

  2. php万国码,前后端交互过程中的编码

    起因 最近在写PHP,本身对PHP不太熟练.然后遇到编码这个问题,困扰了大半天,索性,系统探索解决一番. 前后端交互过程中涉及的编码 Browser cilent: 首先,浏览器的设置里有设置编码格式 ...

  3. 在应急响应过程中,有什么好的方法可以寻找某一日期创建的文件?

    ​ Q:在应急响应过程中,有什么好的方法可以寻找某一日期创建的文件? A:我会通过以下的方式来查找: 1.forfiles-寻找某一日期创建的文件 forfiles /m *.ps1 /d +2022 ...

  4. Java18-day09【字节缓冲流、字符流、编码表、字符串与字符流中的编码解码问题、字符流读写数据的方式、字符缓冲流、IO流小结】

    视频+资料(工程源码.笔记)[链接:https://pan.baidu.com/s/1MdFNUADVSFf-lVw3SJRvtg   提取码:zjxs] Java基础--学习笔记(零起点打开java ...

  5. Javascript中Base64编码解码的使用实例

    Javascript为我们提供了一个简单的方法来实现字符串的Base64编码和解码,分别是window.btoa()函数和window.atob()函数. 1 var encodedStr = win ...

  6. 【计算机网络】浏览器中的 http 请求响应过程

    客户端输入 url 后的相应过程 http 的工作过程通常包括请求和相应两个环节,属于标准的客户端服务器模型( C/S 模型).客户端发起 http 协议请求,服务器接收到请求后,返回对应的相应.具体 ...

  7. 通过HTTP请求响应过程了解HTTP协议

    首先了解一次完整的HTTP请求到响应的过程需要的步骤 1. 域名解析 2. 发起TCP的3次握手 3. 建立TCP连接后发起http请求 4. 服务器端响应http请求,浏览器得到html代码 5. ...

  8. 从URL输入到页面展现,过程中发生了什么?

    从在地址栏中输入了URL,到浏览器展现出页面整个过程中,大概经历了如下过程: 在浏览器地址中输入了URL并回车 域名解析 服务器处理请求 浏览器处理 网页的绘制 一.在浏览器地址中输入URL 首先解释 ...

  9. JSP页面的执行过程

    当客户端浏览器,向服务器发出访问一个JSP页面的请求时 服务器根据该请求加载相应的JSP页面,并对该页面进行编译,然后执行 执行过程 1.客户端通过浏览器,向服务器发出请求,在该请求中包含了请求的资源 ...

最新文章

  1. 丢失msvcr120d.dll、msvcr120.dll、msvcp120d.dll、msvcp120.dll问题解决方法
  2. Android SDK版本号 与 API Level 对应关系
  3. 所选驱动器不再有效,继续安装之前,请先检查安装路径的设置
  4. 【JAVA SERVLET 开发系列之二】创建WEBAPP详细步骤,通过SERVLET实现HTTP简单交互
  5. 编译原理 数据流方程_数据科学中最可悲的方程式
  6. 新疆大学c语言期末考试题库,2016年新疆师范大学教育科学学院C语言程序设计考研复试题库...
  7. HDU 3790 最短路径问题 (SPFA)
  8. LeetCode刷题(27)
  9. 编译原理教程_4 语法分析
  10. python cursor游标_python tuble、lambda及cursor游标相关
  11. HDU 3729【二分匹配】
  12. 无用小知识-递归的使用
  13. burp放包_详解BurpSuite软件 请求包 HTTP (9.23 第十天)
  14. 2015 kitti 数据集_kitti 数据集解析
  15. 计算机桌面如何分区,展示电脑如何分区
  16. xposed框架_把安卓手机开发到极致的框架xposed
  17. 阿里云服务器被恶意程序攻击
  18. Python人脸识别 Python3.7+OpenCV+Dlib+罗技C920摄像头 实现离线实时摄像头画面人脸检测+识别
  19. 将搜狗输入法默认的中文输入更改成英文
  20. MSP430 MSP430单片机输入/输出模块 通用I/O端口GPIO LED按键

热门文章

  1. c语言中local status6,C语言中易错的地方(一)
  2. Unicode 字符编码表|汉字Unicode编码的区间为:0x4E00→0x9FA5
  3. MQC手游行业解决方案详解
  4. Math_Calculus_07_向量代数与空间解析几何
  5. app逆向(10)| APP的加固与脱壳
  6. 南大通用GBase8s 常用SQL语句(233)
  7. 在Ubuntu中安装FRR构建虚拟路由器
  8. [转]关于男女两性关系的名言幽默!经典!!
  9. Linux Centos7.9安装oracle11g及注意事项(2)
  10. 计算鼠标移动的精确速度