您当前的位置: 首页 > 慢生活 > 程序人生 网站首页程序人生
06-Request请求参数中文乱码-GET解决方案(GET与POST通用解决乱码方法)
发布时间:2024-11-29 15:41:29编辑:雪饮阅读()
-
request的get请求中文乱码原因是浏览器将queryString的中文字符发送给tomcat的时候在我们目前的环境下是进行了UTF-8的编码,而tomcat内部收到这个queryString时候会进行解码,但它默认解码方式是ISO-8859-1,且好像不能修改干预(这里指tomcat7,maven插件版的tomcat目前最高支持tomcat7,”tomcat8已经解决了get请求中文乱码问题”,据说,我不是太相信,毕竟maven插件版的tomcat目前最高支持tomcat7,而且原生tomcat8我在cmd控制台也有中文乱码情况,但是这里好像又是没有什么关联了吧,先不纠结了。)
- 将字符串按照编码方式转为二进制
- 每个字节转为2个16进制数并在前边加上%
URL编码规则:
要将“张三”转成二进制,我们首先需要明确一点:计算机处理的是字符的编码,而不是字符本身。对于中文字符,常用的编码方式是UTF-8。
步骤一:获取“张”和“三”的UTF-8编码
“张”的UTF-8编码:
“张”的Unicode码点是4E2D(十六进制)。
转换成二进制是0100 1110 0010 1101。
“三”的UTF-8编码:
“三”的Unicode码点是4E09(十六进制)。
转换成二进制是0100 1110 0000 1001。
合并编码
将“张”和“三”的UTF-8编码合并起来,得到“张三”的二进制表示:
01001110 00101101 01001110 00001001
以“张”的详细计算过程为例:
有些浏览器是地址栏里面是明文,并不是没有编码,而是对用户而言优化可见了,内部还是编码了。
但f12的network中是可见到已经编码了的url。
这里在webapp目录下建立index5.html内容如
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div style="display: flex;justify-content: space-between;">
<form action="http://localhost:8081/servlet01/HttpServlet13" method="get" style="width: 50%;">
<h1>GET</h1>
<div>
<label>username</label>
<input name="username" value="小明"/>
</div>
<div>
<label>password</label>
<input name="password" value="123456"/>
</div>
<div>
<label>hobby</label>
<input type="checkbox" name="hobby" value="1" checked /> swim
<input type="checkbox" name="hobby" value="2" checked /> climb mountain
</div>
<div>
<input type="submit" value="submit"/>
</div>
</form>
<form action="http://localhost:8081/servlet01/HttpServlet13" method="post" style="width: 50%;">
<h1>POST</h1>
<div>
<label>username</label>
<input name="username" value="小李"/>
</div>
<div>
<label>password</label>
<input name="password" value="6788"/>
</div>
<div>
<label>hobby</label>
<input type="checkbox" name="hobby" value="1" checked /> swim
<input type="checkbox" name="hobby" value="2" checked /> climb mountain
</div>
<div>
<input type="submit" value="submit"/>
</div>
</form>
</div>
</body>
</html>
当然还要把之前pom.xml中的<uriEncoding>UTF-8</uriEncoding>注释掉
以使得get请求行的中文参数值重新乱码起来。
建立HttpServlet13.java如
package com;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Map;
@WebServlet("/HttpServlet13")
public class HttpServlet13 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("---------get--------");
String username=req.getParameter("username");
System.out.println("username:"+username);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("---------post--------");
doGet(req,resp);
}
}
那么此时我们可以访问如
http://localhost:8081/servlet01/index5.html
然后在f12打开的情况下,我这里是Edge浏览器,然后提交这里的第一个get请求的form表单,可以看到network中的请求URL实际上如:
http://localhost:8081/servlet01/HttpServlet13?username=%E5%B0%8F%E6%98%8E&password=123456&hobby=1&hobby=2
这就印证了确实是编码了的。
java内置的url转码,可以导包java.net.URLEncoder
实例如
System.out.println("小明的URL的utf-8编码:"+URLEncoder.encode("小明","utf-8"));
同样java.net.URLEncoder包支持解码
String encode=URLEncoder.encode("小明","utf-8");
System.out.println("小明的URL的utf-8解码:"+ URLDecoder.decode(encode,"utf-8"));
乱码的原因,tomcat以ISO-8859-1解码的。
那么也可以模拟tomcat的解码操作。
String encode=URLEncoder.encode("小明","utf-8");
System.out.println("小明的URL的ISO-8859-1解码:"+ URLDecoder.decode(encode,"ISO-8859-1"));
在控制台中可见的是有又一次乱了起来。
但数据底层的二进制数据仍旧是不会改变的。所以知道了原理了,则可以逆向还原回来。
先看下十进制的效果(在Java中,当你直接在控制台输出一个byte类型的变量时,它默认会以十进制(也称为基数10或base-10)的形式显示。这是因为Java的print和println方法默认以十进制格式输出整数类型(包括byte、short、int、long等)。)
String encode=URLEncoder.encode("小明","utf-8");
System.out.println("encode:"+encode);
String decode=URLDecoder.decode(encode,"ISO-8859-1");
System.out.println("decode:"+decode);
byte[] bytes=decode.getBytes("ISO-8859-1");
System.out.println("----------------");
for(byte b:bytes){
System.out.print(b+" ");
}
可以参考win10计算器程序员类型研究下,输入16进制如8E,得到10进制-114
所以我们可以进行还原
String encode=URLEncoder.encode("小明","utf-8");
System.out.println("encode:"+encode);
String decode=URLDecoder.decode(encode,"ISO-8859-1");
System.out.println("decode:"+decode);
//字节数组
byte[] bytes=decode.getBytes("ISO-8859-1");
System.out.println("----------------");
for(byte b:bytes){
System.out.print(b+" ");
}
//字节数组转成字符串
String s=new String(bytes,"utf-8");
System.out.println("重新解码于utf8的结果:"+s);
所以实战于doGet中
byte[] bytes=username.getBytes(StandardCharsets.ISO_8859_1);
username=new String(bytes,StandardCharsets.UTF_8);
System.out.println("处理乱码后的username:"+username);
这样同时还能解决post的乱码问题。我doPost里面也不用设置如
req.setCharacterEncoding("UTF-8");这个了。
“Tomcat8.0之后,已将GET请求乱码问题解决,设置默认的解码方式为UTF-8。”
关键字词:
相关文章
-
无相关信息