一、概述

客户端与服务器端在交互过程中,需要将字符以某种编码方式转化为字节流进行传输,因此涉及字符的编码和解码。某一方以编码方案A编码,另一方须以同样的编码方案解码,否则会出现乱码。

客户端与服务器端的交互可分为三种:

  • 服务端向客户端传递数据
  • 客户端向服务端传递数据(POST)
  • 客户端向服务端传递数据(GET)

服务端在不指定编码方式时,默认使用 ISO-8859-1 解码

客户端在使用 encodeURIComponent() 方法时,使用 UTF-8 编码

二、服务端向客户端传递数据

服务端向客户端传递数据依赖HttpServletResponse类提供的方法,需要两步:

1、以某种编码写数据

response.getOutputStream().write("异常处理hello".getBytes("UTF-8"));

或者

response.setCharacterEncoding("UTF-8");
response.getWriter().write("异常处理hello");

2、添加响应头,告知客户端解码方式

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

三、客户端向服务端传递数据(POST)

客户端向服务端传递数据依赖HttpServletRequest类提供的方法,需要两步:

1、设置解码方式

request.setCharacterEncoding("UTF-8");

2、读取参数

String name = request.getParameter("name");
Integer age = Integer.valueOf(request.getParameter("age"));

测试请求包(使用Fiddler发起)

POST http://localhost:8080/java-web-test/encoding/1 HTTP/1.1
Content-Type: application/x-www-form-urlencoded name=%E9%80%89%E6%8B%A9%E5%A4%A7%E4%BA%8E%E5%8A%AA%E5%8A%9B&age=859

四、客户端向服务端传递数据(GET)

客户端通过GET方式(即通过url)传递参数,须以如下方式解析:

String name = new String(request.getParameter("name").getBytes("ISO-8859-1"), "UTF-8");

测试:http://localhost:8080/java-web-test/encoding/1?name=%E9%80%89%E6%8B%A9&age=52

即服务端默认以 ISO-8859-1 编码方式解析,解析时须以 ISO-8859-1 编码方式还原为字节码,再在以 UTF-8 编码方式解码

补充:

浏览器的encodeURIComponent()编码方式是将特定字符以 UTF-8 方式编码为二进制,再以%为分隔、以十六进制方式展示,如:

encodeURIComponent('选择'); // 输出:%E9%80%89%E6%8B%A9

java等价代码:

String str = URLEncoder.encode("选择", "UTF-8");

同样,decodeURIComponent() 解码方式是将以%为分隔的十六进制字符转换为二进制,再以 UTF-8 方式解码

decodeURIComponent("%E9%80%89%E6%8B%A9") // 输出:选择

java等价代码:

String str = URLDecoder.decode("%E9%80%89%E6%8B%A9", "UTF-8");

五、web.xml中设置编码方式

web.xml中,编码方式的设置可通过添加过滤器实现:

 <filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

过滤器的部分源码如下:

    @Override
protected void doFilterInternal(
HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException { if (this.encoding != null && (this.forceEncoding || request.getCharacterEncoding() == null)) {
request.setCharacterEncoding(this.encoding);
if (this.forceEncoding) {
response.setCharacterEncoding(this.encoding);
}
}
filterChain.doFilter(request, response);
}

即设置了请求与响应内容区的编码方式,但对GET请求无处理,因此仍然需要另外处理,如下:

@RestController
public class TestController { @RequestMapping(value = "/hello")
public Map<String, Object> helloWorld(@RequestParam("name") String name) throws UnsupportedEncodingException { Map<String, Object> map = new HashMap<String, Object>();
map.put("name", new String(name.getBytes("ISO-8859-1"), "UTF-8"));
return map;
}
}

测试:http://localhost:8080/myweb/hello?name=%E7%A8%8B%E5%90%9B&age=29

例外一种解决方法为添加过滤器,详细可参考javaweb学习总结(四十三)——Filter高级开发

参考:

javaweb学习总结(七)——HttpServletResponse对象(一)

javaweb学习总结(十)——HttpServletRequest对象(一)

javaweb学习总结(四十三)——Filter高级开发

Spring MVC 使用介绍(十)—— 编码的更多相关文章

  1. Spring MVC 使用介绍(十五)数据验证 (二)依赖注入与方法级别验证

    一.概述 JSR-349 (Bean Validation 1.1)对数据验证进一步进行的规范,主要内容如下: 1.依赖注入验证 2.方法级别验证 二.依赖注入验证 spring提供BeanValid ...

  2. Spring MVC 使用介绍(十四)文件上传下载

    一.概述 文件上传时,http请求头Content-Type须为multipart/form-data,有两种实现方式: 1.基于FormData对象,该方式简单灵活 2.基于<form> ...

  3. Spring MVC 使用介绍(十三)数据验证 (一)基本介绍

    一.消息处理功能 Spring提供MessageSource接口用于提供消息处理功能: public interface MessageSource { String getMessage(Strin ...

  4. Spring MVC 使用介绍(十二)控制器返回结果统一处理

    一.概述 在为前端提供http接口时,通常返回的数据需要统一的json格式,如包含错误码和错误信息等字段. 该功能的实现有四种可能的方式: AOP 利用环绕通知,对包含@RequestMapping注 ...

  5. Spring MVC 使用介绍(五)—— 注解式控制器(一):基本介绍

    一.hello world 相对于基于Controller接口的方式,基于注解方式的配置步骤如下: HandlerMapping 与HandlerAdapter 分别配置为RequestMapping ...

  6. Spring MVC 使用介绍(八)—— 类型转换

    一.概述 spring类型转换有两种方式: PropertyEditor:可实现String<--->Object 之间相互转换 Converter:可实现任意类型的相互转换 类型转换的过 ...

  7. spring mvc简单介绍xml版

    spring mvc介绍:其实spring mvc就是基于servlet实现的,只不过他讲请求处理的流程分配的更细致而已. spring mvc核心理念的4个组件: 1.DispatcherServl ...

  8. Spring MVC 数据验证——validate编码方式

    1.导入jar包 validation-api-1.0.0.GA.jar这是比較关键的一个jar包,主要用于解析注解@Valid. hibernate-validator-4.3.2.Final.ja ...

  9. Spring MVC 原理介绍(执行流程)

    Spring MVC工作流程图   图一   图二    Spring工作流程描述       1. 用户向服务器发送请求,请求被Spring 前端控制Servelt DispatcherServle ...

  10. Spring MVC 简单介绍

    Spring MVC 是典型的mvc架构,适合web开发. controler 输入输出的控制器,也是对外view提供数据的接口,调用service层. model 数据,由bean组成(相应表),关 ...

随机推荐

  1. Xamarin for Visual Studio下载后的文件路径

    Xamarin for Visual Studio的下载很纠结,在官网上不知道如何下载?现在找到一个办法:可以先在网上找一个低版本的之后安装,然后利用VS更新.利用VS更新这里也遇到了问题,下载成功之 ...

  2. WEB前端常见面试题汇总:(一)

    1.JS找字符串中出现最多的字符 例如:求字符串'nininihaoa'中出现次数最多字符 方法一: var str = "nininihaoa"; var o = {}; for ...

  3. Mysql基本操作指令集锦

    一.MySQL服务的启动.停止与卸载 在 Windows 命令提示符下运行: 启动: net start MySQL 停止: net stop MySQL 卸载: sc delete MySQL 二. ...

  4. 作为JavaScript开发人员,这些必备的VS Code插件你都用过吗?

    本文翻译自:https://www.sitepoint.com/vs-code-extensions-javascript-developers/ 转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的 ...

  5. vmware 开启VM的硬件cpu虚拟化功能

    物理机的cpu硬件虚拟化功能,通过开启bios中的设置,而vmware中创建的虚拟机也可以开启该特性,如下. 这样的话,就直接可以基于这些VM安装openstack计算节点.控制节点.网络节点了.

  6. shell脚本批量ssh登陆主机并执行命令

    shell脚本批量ssh登陆主机并执行命令 今天在客户现场遇到了这个问题,客户没有管理工具,无法批量登陆主机下发命令,几个个C段啊,让我一个一个登陆,.................. 所以写了个s ...

  7. MongoDB基础学习

    *:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: 0 !important; } /* ...

  8. c/c++ 多线程 等待一次性事件 std::promise用法

    多线程 等待一次性事件 std::promise用法 背景:不是很明白,不知道为了解决什么业务场景,感觉std::async可以优雅的搞定一切的一次等待性事件,为什么还有个std::promise. ...

  9. sqlmap --tamper 绕过WAF脚本分类整理

    分类: https://blog.csdn.net/whatday/article/details/54774043 详细介绍: https://blog.csdn.net/qq_34444097/a ...

  10. 协程demo,1异步爬网页 2异步socket请求

    一.异步爬网页 ''' 协程并发爬网页 ''' from urllib import request import gevent,time from gevent import monkey # 让g ...