一次http请求涉及的编解码

URL的编解码

URL的组成部分

以Tomcat服务器为例子,其中Port,ContextPath在Server.xml中配置
<Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>
<Context docBase="examples" path="/examples" reloadable="true" source="org.eclipse.jst.jee.server:examples"/>

ServletPath在Web应用的web.xml中的<url-pattern>中配置,PathInfo 是我们请求的具体的 Servlet,QueryString 是要传递的参数,注意这里是在浏览器里直接输入 URL 所以是通过 Get 方法请求的,如果是 POST 方法请求的话,QueryString 将通过表单方式提交到服务器端。

通过浏览器的请求过程,我们可知两个“君山”的编码结果是不同的:e5 90 9b e5 b1 b1,be fd c9 bd。说明了PathInfo和QueryString是由不同的逻辑代码处理的。

PathInfo的处理取决于Server.xml中的Connector标签中的定义,如果没有定义,那么将以默认编码 ISO-8859-1 解析。所以如果有中文 URL 时最好把 URIEncoding 设置成 UTF-8 编码。

QueryString 又如何解析? GET 方式 HTTP 请求的 QueryString 与 POST 方式 HTTP 请求的表单参数都是作为 Parameters 保存,都是通过 request.getParameter 获取参数值。对它们的解码是在 request.getParameter 方法第一次被调用时进行的。request.getParameter 方法被调用时将会调用 org.apache.catalina.connector.Request 的 parseParameters 方法。这个方法将会对 GET 和 POST 方式传递的参数进行解码,但是它们的解码字符集有可能不一样。POST 表单的解码将在后面介绍,QueryString 的解码字符集要么是 Header 中 ContentType 中定义的 Charset 要么就是默认的 ISO-8859-1,要使用 ContentType 中定义的编码就要设置 connector 的  中的 useBodyEncodingForURI 设置为 true。这个配置项的名字有点让人产生混淆,它并不是对整个 URI 都采用 BodyEncoding 进行解码而仅仅是对 QueryString 使用 BodyEncoding 解码,这一点还要特别注意。

所以在我们的应用程序中应该尽量避免在 URL 中使用非 ASCII 字符,不然很可能会碰到乱码问题,当然在我们的服务器端最好设置  中的 URIEncoding 和 useBodyEncodingForURI 两个参数。如下图:

HTTP Header的编解码

当客户端发起一个 HTTP 请求除了上面的 URL 外还可能会在 Header 中传递其它参数如 Cookie、redirectPath 等,这些用户设置的值很可能也会存在编码问题,Tomcat 对它们又是怎么解码的呢?

对 Header 中的项进行解码也是在调用 request.getHeader 是进行的,如果请求的 Header 项没有解码则调用 MessageBytes 的 toString 方法,这个方法将从 byte 到 char 的转化使用的默认编码也是 ISO-8859-1,而我们也不能设置 Header 的其它解码格式,所以如果你设置 Header 中有非 ASCII 字符解码肯定会有乱码。

我们在添加 Header 时也是同样的道理,不要在 Header 中传递非 ASCII 字符,如果一定要传递的话,我们可以先将这些字符用 org.apache.catalina.util.URLEncoder 编码然后再添加到 Header 中,这样在浏览器到服务器的传递过程中就不会丢失信息了,如果我们要访问这些项时再按照相应的字符集解码就好了。

POST表单中的编码

通过POST表单方式提交的参数,解码是在第一次调用request.getParamter(name)时发生的,通过POST表单方式提交的参数与QueryString不同,他是通过Http Body传递到服务端的,编码为Header中的Content-Type,解码也使用Content-Type,也可以通过request.setCharsetEncoding(charset)设置(必须在第一次调用getParamter前)。若没有指定编码,将使用系统默认编码进行编码,Content-Type为空,tomcat将使用系统默认编码进行解码。

HTTP BODY的编解码

当用户请求的资源已经成功获取后,这些内容将通过 Response 返回给客户端浏览器,这个过程先要经过编码再到浏览器进行解码。这个过程的编解码字符集可以通过 response.setCharacterEncoding 来设置,它将会覆盖 request.getCharacterEncoding 的值,并且通过 Header 的 Content-Type 返回客户端,浏览器接受到返回的 socket 流时将通过 Content-Type 的 charset 来解码,如果返回的 HTTP Header 中 Content-Type 没有设置 charset,那么浏览器将使用<meta HTTP-equiv="Content-Type", content="text/html; charset=utf-8">中的编码进行解码。如果也没有定义的话,那么浏览器将使用默认的编码来解码。

参考文章:

  • https://www.ibm.com/developerworks/cn/java/j-lo-chinesecoding/index.html#icomments
  • http://ilovejava.cn/posts/4a17a007/

Java Web中涉及的编解码相关推荐

  1. Java Web中的中文编码问题分析

    一.为什么需要编码 在计算机中存储信息的最小单位是1个字节,即8bit,所以能标识的最大字符范围是0~255,而人类自然语言中例如汉语.日语要表示的符号太多,无法单纯用一个字节来完全表示,为了解决这个 ...

  2. 深入分析 Java Web 中的中文编码问题

    深入分析 Java Web 中的中文编码问题 背景: 编码问题一直困扰着程序开发人员,尤其是在 Java 中更加明显,因为 Java 是跨平台的语言,在不同平台的编码之间的切换较多.接下来将介绍 Ja ...

  3. 第三章 深入分析Java Web中的中文编码问题

    3.1 几种常见的编码格式 3.1.1 为什么要编码 一个字节 byte只能表示0~255个符号,要表示更多的字符,需要编码. 3.1.2 如何翻译 ASCII码:有128个,用一个字节的低7位表示. ...

  4. Spring中html字符编解码

    Spring中html字符编解码 场景描述 今天基于 jeesite 在做一个简单的curd的功能时,遇到个比较有意思的问题,在此记录一下,在使用springMVC form标签作双向绑定时,如果文本 ...

  5. java web 中有效解决中文乱码问题-pageEncoding与charset区别, response和request的setCharacterEncoding 区别

    java web 中有效解决中文乱码问题-pageEncoding与charset区别, response和request的setCharacterEncoding 区别 参考文章: (1)java ...

  6. java 控制jsp_JSP学习之Java Web中的安全控制实例详解

    普通用户界面 修改登录的Servlet,修改后的代码如下: LoginProcess.java代码: package servlet; import javabean.User; import jav ...

  7. 用servlet路径访问一个html,java web中servlet、jsp、html 互相访问的路径问题

    在html">java web种经常出现 404找不到网页的错误,究其原因,一般是访问的路径不对. html">java web中的路径使用按我的分法可以分两种情况,当 ...

  8. java web 中 读取windows图标并显示

    java web中读取windows对应文件名的 系统图标 ....显示 1.获取系统图标工具类 package utils;  import java.awt.Graphics;  import j ...

  9. Java web中不同浏览器间导出Excel文件名称乱码问题解决方案

    Java web中不同浏览器间导出Excel文件名称乱码问题解决方案 参考文章: (1)Java web中不同浏览器间导出Excel文件名称乱码问题解决方案 (2)https://www.cnblog ...

最新文章

  1. Rust和C / C ++的跨语言链接时间优化LTO
  2. android系统动态切换输入法,一种动态切换Android系统输入法的弹出模式的方法与流程...
  3. boost::yap::make_expression_function相关的测试程序
  4. poj 3131 双向搜索+hash判重
  5. Unity VS Unreal,游戏开发该如何选择引擎?
  6. Oracle Discover产品简介
  7. Micropython 如何用Turnipbit做一个自动浇水装置
  8. 详解JavaScript变量类型判断及domReady原理 写得很好
  9. 郁金香汇编代码注入怎么写看雪_汇编语言入门五:流程控制(一)
  10. 绝佳的ASR学习方案:这是一套开源的中文语音识别系统
  11. 思维导图中主题连接线格式修改教程
  12. Alexa | Alexa Auto SDK 概述
  13. Zoom会议使用指南
  14. 二叉树由遍历确定一棵树
  15. python如何爬有道翻译_python 爬有道翻译
  16. 卡内基梅隆大学计算机科学博士,卡内基梅隆大学有哪些专业处于世界顶尖水平?...
  17. 这个牛逼的在线项目任务管理工具,终于开源了!
  18. 【Dash搭建可视化网站】项目4: 利用Dash Plotly实现数据图表可视化
  19. 没有链克口袋,但我一样玩游戏掘金
  20. 数据结构实验 二叉树的基本操作

热门文章

  1. Redis 秒杀案例
  2. 自学web前端真的很难找到工作
  3. python我的所得税计算器_python实现计算器简易版
  4. [渝粤教育] 西南交通大学 体育健康课程Ⅰ—奥运裁判带你学规则 参考 资料
  5. 净现值、投资回收期例题讲解
  6. C#2.0 编写window服务
  7. 小白学习Python的第十六天之正则表达式
  8. FS4052A是一个4.0-23V宽电压输入,2A充电电流单电池 同步降压锂离子电池充电器
  9. K7 IDELAY2 仿真实验
  10. 高数(下)——平面及其方程