浅谈web开发中的乱码问题

本文详细介绍了在Web开发中处理GET和POST请求中文乱码的方法,并提供了响应时避免中文乱码的策略。
编码问题是很多开发者在 Web 开发过程中经常会遇到的问题,有的虽然能够机械的记住解决的代码,但是对乱码出现的原因以及解决的原理未作过了解。因此本文这部分内容作一个简单的总结和解释。

请求中文乱码


HTTP 请求中,最常用的请求方式为 GET  POST。请求参数会随着不同的请求方式出现在不同的位置,所以对于中文乱码的处理方式也不一样。

GET 请求中文参数乱码解决
GET 方式提交参数时,参数是直接出现在 URL 中的,对于 GET 请求,中文参数乱码问题解决方式有3种。

1.修改 Tomcat 编码。
Tomcat 
安装路径–> conf –>server.xml –> Connector 标签–> 增加 URIEncoding 属性
  
1
  
  
<Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"URIEncoding="UTF-8"/>
  
通常不建议使用这种方式,因为一个采用Tomcat8.0 之前版本服务器的老项目,代码中可能已经处理了GET请求的乱码问题,采用这种方式反而会导致乱码的出现。Tomcat8以及以上版本已经将默认编码修改为 UTF-8 因此不用修改。
2. 通过 URLEncoder  URLDecoder 进行编解码操作。
  
1
  
2
  
  
  String encode = URLEncoder.encode(request.getParameter("name"),"ISO-8859-1");
  
String name = URLDecoder.decode(encode,"UTF-8");
  
代码解释:
GET 请求的参数是出现在 URL 中的 QueryString 部分的,URL 中如果含有中文等非 ASCII 字符,则浏览器会对它们进行 URLEncode,然后发送给服务器,在通过request.getParameter(“name”) 取出时又会对该name 对应的参数进行 URLDecode。通常在进行 URLEncode 的时候采用的编码为UTF-8,而在 URLDecode 的时候会采用 Tomcat 服务器的默认编码 ISO-8859-1,编码和解码所采用的编码方式不一致,所以出现乱码。既然通过request.getParameter(“name”) 得到了一个采用ISO-8859-1 进行 URLDecode 的乱码,那么我们可以对该乱码通过 ISO-8859-1 进行URLEncode,此时的值就是浏览器最初提交到后台的通过 UTF-8 URLEncode 后的数据。然后我们通过与浏览器一致的 UTF-8 编码对该数据进行解码。两端编码一致,乱码问题就得到了解决。

Talk is cheap,Show you the code.
我们通过下面的代码来解释乱码出现到解决的过程,
  
1
  
2
  
3
  
4
  
5
  
6
  
7
  
8
  
9
  
10
  
11
  
12
  
13
  
14
  
15
  
16
  
17
  
18
  
  
@Test
  
public void test1()throws Exception {
  
          // 1,原始中文参数
  
          String parameter = "中文";
  
          System.out.println("原始中文参数:"+parameter);
  
          // 2,浏览器通过 UTF-8 进行 URLEncode
  
          String  browerEncodeParameter = URLEncoder.encode(parameter, "UTF-8");
  
          System.out.println("浏览器通过 UTF-8 进行 URLEncode 后的值:"  +browerEncodeParameter);
  
          // 3,通过 ISO-8859-1 进行 URLDecode
  
          String  serverDecodeParameter = URLDecoder.decode(browerEncodeParameter, "ISO-8859-1");
  
          System.out.println("直接取出时通过 ISO-8859-1 进行 URLDecode 后得到的乱码:"+serverDecodeParameter);
  
          // 4,手动通过 ISO-8859-1 对乱码进行 URLEncode 
  
          String  codeEncodeParameter = URLEncoder.encode(serverDecodeParameter,"ISO-8859-1");
  
          System.out.println("手动对乱码通过 ISO-8859-1 进行 URLEncode 得到的浏览器原始提交的值:"+codeEncodeParameter);
  
          // 5,手动通过 UTF-8 对步骤4得到的值进行 URLDecode 后得到正确中文参数
  
          String  codeDecodeParameter = URLDecoder.decode(codeEncodeParameter,"UTF-8");
  
          System.out.println("手动通过 UTF-8 进行 URLDecode 后得到的正确中文参数:"+codeDecodeParameter);
  
}
  
执行结果:

  
1
  
2
  
3
  
4
  
5
  
  
  原始中文参数:  中文
  
浏览器通过 UTF-8 进行 URLEncode 后的值:   %E4%B8%AD%E6%96%87
  
直接取出时通过 ISO-8859-1 进行 URLDecode 后得到的乱码:   ä¸­æ–‡
  
手动对乱码通过 ISO-8859-1 进行 URLEncode 得到的浏览器原始提交的值:   %E4%B8%AD%E6%96%87
  
手动通过 UTF-8 进行 URLDecode 后得到的正确中文参数:   中文

那么接下来继续对 GET 请求的剩下一种方式以及 POST 请求的中文乱码解决方式作一个总结。
3. 通过 String 的构造方法。
1
String name = new String(request.getParameter("name").getBytes("IOS-8859-1"),"UTF-8");
代码解释:
无论从浏览器提交时中文参数是什么编码格式,到达服务器时因为 Tomcat 编码方式的原因,采用 ISO-8859-1 的方式给解析成了乱码
request.getParameter(“name”) 获取到的就是一个通过 ISO-8859-1 方式解析之后的乱码,那么我们通过 getBytes(“ISO-8859-1”) 将它反解成原有编码的字符数组,相当于打回原形,这是一个正确的字符数组,然后通过 String 的构造方法将这个正确的字符数组转成 UTF-8 编码的字符串。因为代码相对简单,因此通常采用这种方式。

POST请求中文参数乱码解决

对于 POST 方式,表单中的参数值对是通过 request body 发送给服务器,此时浏览器会根据网页的 ContentType(“text/html; charset=编码”) 中指定的编码进行对表单中的数据进行编码,然后发给服务器。POST 的参数是在请求体中,直接到达后台,数据在 Servlet 中的 request 中。request 有一个缓冲区,request 的缓冲区采用的是 ISO-8859-1 编码,因为 requeset 是 Tomcat 负责创建的,所以用的是 Tomcat 的编码。解决方式是设置 request 缓冲区编码。在服务器端的程序中我们可以通过 request 对象 的 setCharacterEncoding 方法设置编码,然后通过 request 对象的 getParameter 获得正确的数据。
1
2
request.setCharacterEncoding("UTF-8");
String value = requst.getParameter("name");
响应中文乱码
通常情况我们都是通过 HttpServletResponse 对象向页面进行响应,HttpServletResponse 有两种响应方式,一种是 OutputStream 字节流,另一种是 PrintWriter 字符流。是否会出现中文乱码,以及乱码解决方式跟采用的流的类型有关。
字节流
使用字节流不一定会出现中文乱码,取决于操作系统,工作空间以及浏览器打开页面时采用的编码。如果两端编码一致,则不会出现中文乱码,不一致则出现乱码。
  • 解决方式:
  • 设置字符数组取出时的编码
  • 设置浏览器打开时的编码
1
2
response.getOutPutStream.write("中文".getBytes("UTF-8"));
response.setHeader("Content-Type","text/html;charset=UTF-8");
总之是设置输出时的字节数组编码和浏览器解析时的编码一致。中文转成字节数组的时候,如果 IDE 工作空间的编码正好和浏览器一致,可以不用设置字符数组取出时的编码,但是为了保险起见,建议还是设置。
字符流
使用字符流一定会出现中文乱码,HttpServletResponse 使用的字符流是有缓冲区的,缓冲区使用的默认编码是 IOS-8859-1,压根儿就不支持中文。
  • 解决方式:
  • 设置字符流缓冲区的编码
  • 设置浏览器打开时的编码
1
2
3
response.setCharacterEncoding("UTF-8");
response.setHeader("Content-Type","text/html;charset=UTF-8");
response.getWriter().println("中文");
简化写法
1
2
response.setContentType("text/html;charset=UTF-8");
response.getWriter().println("中文");

文件下载时的中文文件名乱码处理
文件下载前,文件名一般是以 GET 请求方式的参数直接出现在浏览器的地址栏也就是 URL 中的,所以需要先通过解决 GET 请求中文乱码的方式将中文文件名接收成正常的中文。
在下载开始时,需要设置文件保存时采用的文件名,不同浏览器因为特性的不同需要分别设置,如 IE 等内核的浏览器要求 Content-Disposition 响应头中的中文文件名需要通过 URLEncoder 进行编码,而火狐浏览器要求 Content-Disposition 响应头中的中文文件名需要通过 Base64 进行编码。所以要通过请求头中的 User-Agent 头信息获取到浏览器类型后分别处理。
  • 解决方式
1
2
3
4
5
6
7
8
9
10
11
// 1.接收参数,解决 GET 请求参数中文乱码,目的是将中文文件名转成正常中文
String filename = new String(request.getParameter("filename").getBytes("ISO-8859-1"),"UTF-8");
// 根据浏览器的类型处理保存的中文文件名的乱码问题:
String agent = request.getHeader("User-Agent");
if(agent.contains("Firefox")){
        filename = base64EncodeFileName(filename);
}else{
        filename = URLEncoder.encode(filename,"UTF-8");
}
// 2.2设置Content-Disposition头
response.setHeader("Content-Disposition", "attachment;filename="+filename);
通过 Base64 编码中文文件名的方法代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
   // 参数为中文文件名
public static String base64EncodeFileName(String fileName) {
        BASE64Encoder base64Encoder = new BASE64Encoder();
        try {
                return "=?UTF-8?B?"
                                + new String(base64Encoder.encode(fileName
                                                .getBytes("UTF-8"))) + "?=";
        } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
                throw new RuntimeException(e);
        }
}

【Koopman】遍历论、动态模态分解和库普曼算子谱特性的计算研究(Matlab代码实现)内容概要:本文围绕【Koopman】遍历论、动态模态分解和库普曼算子谱特性的计算研究展开,重点介绍基于Matlab的代码实现方法。文章系统阐述了遍历理论的基本概念、动态模态分解(DMD)的数学原理及其与库普曼算子谱特性之间的内在联系,展示了如何通过数值计算手段分析非线性动力系统的演化行为。文中提供了完整的Matlab代码示例,涵盖数据驱动的模态分解、谱分析及可视化过程,帮助读者理解并复现相关算法。同时,文档还列举了多个相关的科研方向和技术应用场景,体现出该方法在复杂系统建模与分析中的广泛适用性。; 适合人群:具备一定动力系统、线性代数与数值分析基础,熟悉Matlab编程,从事控制理论、流体力学、信号处理或数据驱动建模等领域研究的研究生、博士生及科研人员。; 使用场景及目标:①深入理解库普曼算子理论及其在非线性系统分析中的应用;②掌握动态模态分解(DMD)算法的实现与优化;③应用于流体动力学、气候建模、生物系统、电力系统等领域的时空模态提取与预测;④支撑高水平论文复现与科研项目开发。; 阅读建议:建议读者结合Matlab代码逐段调试运行,对照理论推导加深理解;推荐参考文中提及的相关研究方向拓展应用场景;鼓励在实际数据上验证算法性能,并尝试改进与扩展算法功能。
本系统采用微信小程序作为前端交互界面,结合Spring Boot与Vue.js框架实现后端服务及管理后台的构建,形成一套完整的电子商务解决方案。该系统架构支持单一商户独立运营,亦兼容多商户入驻的平台模式,具备高度的灵活性与扩展性。 在技术实现上,后端以Java语言为核心,依托Spring Boot框架提供稳定的业务逻辑处理与数据接口服务;管理后台采用Vue.js进行开发,实现了直观高效的操作界面;前端微信小程序则为用户提供了便捷的移动端购物体验。整套系统各模块间紧密协作,功能链路完整闭环,已通过严格测试与优化,符合商业应用的标准要求。 系统设计注重业务场景的全面覆盖,不仅包含商品展示、交易流程、订单处理等核心电商功能,还集成了会员管理、营销工具、数据统计等辅助模块,能够满足不同规模商户的日常运营需求。其多店铺支持机制允许平台方对入驻商户进行统一管理,同时保障各店铺在品牌展示、商品销售及客户服务方面的独立运作空间。 该解决方案强调代码结构的规范性与可维护性,遵循企业级开发标准,确保了系统的长期稳定运行与后续功能迭代的可行性。整体而言,这是一套技术选型成熟、架构清晰、功能完备且可直接投入商用的电商平台系统。 资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值