解决get方式提交url传参中文乱码问题

一、服务器原因(tomcat)

Tomcat 中接收请求没有设置编码的情况下,默认使用 ISO-8859-1 编码。
页面编码使用 UTF-8,get方式自然使用 UTF-8 编码;但服务器接收时没有指定解码格式,在使用 request.getParameter 获取参数值的时候,服务端会自动使用 Tomcat 默认的 ISO-8859-1 进行解码,传参带中文时自然乱码。因为编码和解码不匹配。

解决方案:
方案1:

后台可通过 String str = new String(request.getParameter(“user”).getBytes(“iso-8859-1”), “utf-8”) 进行手动转码
这一行代码里面包含3个过程:

  1. request.getParameter(“user”):会自动使用 Tomcat 默认的 ISO-8859-1 进行解码
  2. .getBytes(“iso-8859-1”):使用 ISO-8859-1 对前面的string进行编码
  3. new String(byte[] byte, “UTF-8”);使用 UTF-8 对字符数组byte进行解码

过程为:
UTF-8编码->iso-8859-1解码->iso-8859-1编码->UTF-8解码。
先用iso-8859-1解码,再用iso-8859-1编码就相当于回到了用UTF-8编码的起点,此时再用UTF-8解码就不会乱码了。

try {
	user.setUsername(new String(request.getParameter("user").getBytes("iso-8859-1"), "UTF-8"));
	} catch (UnsupportedEncodingException e) {
		e.printStackTrace();
	}

但是再实施的过程中却报错了:Invalid character found in the request target.The valid characters are defined in RFC 7230 and RFC3986.

经了解,这个问题是高版本tomcat中的新特性:就是严格按照 RFC 3986 规范进行访问解析,而 RFC 3986 规范定义了Url中只允许包含英文字母(a-zA-Z)、数字(0-9)、-_.~4个特殊字符以及所有保留字符(! * ’ ( ) ; : @ & = + $ , / ? # [ ]),所以通过Url传中文时会报错。

解决方法是将tomcat更换为低版本的。

方案2:

修改Tomcat目录下的conf/server.xml文件:

找到如下代码:
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />

这段代码规定了Tomcat监听HTTP请求的端口号等信息。可以在这里添加一个属性:URIEncoding,将该属性值设置为UTF-8,即可让Tomcat(默认ISO-8859-1编码)以UTF-8的编码处理get请求。

修改完成后:
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" URIEncoding="UTF-8" />

这样,页面使用UTF-8编码,服务器使用UTF-8解码,就不会有中文乱码了。

注意:如果是使用eclipse将项目部署到Tomcat而不是直接使用Tomcat的话,需要到eclipse的Servers项目下的server.xml文件中进行更改,而不是直接修改Tomcat中的server.xml文件,因为每一次部署时,都会使用eclipse中的Tomcat配置文件覆盖Tomcat目录下的配置文件,不修改eclipse就会导致修改失败。eclipse路径位置见下图:

在这里插入图片描述

二、前台页面编码,后台解码

方案3:(不依赖Tomcat的配置,推荐)

浏览器中两次URL编码,服务器中自己再做一次URL解码。

原理:

如果只进行一次encodeURI,得到的是UTF-8形式的URL,服务器端通过request.getParameter()解码查询参数(通常是ISO-8859-1)就会得到乱码。

如果进行两次encodeURI,第一次编码得到的是UTF-8形式的URL,第二次编码得到的依然是UTF-8形式的URL,但是在效果上相当于首先进行了一次UTF-8编码(此时已经全部转换为ASCII字符),再进行了一次ISO-8859-1编码,因为对英文字符来说UTF-8编码和ISO-8859-1编码的效果相同。

在服务器端,首先通过request.getParameter()自动进行第一次解码(ISO-8859-1)得到ascii字符,然后再使用UTF-8进行第二次解码,即使用java.net.URLDecoder(key,“UTF-8”)方法。

两次编码两次解码的过程为:
UTF-8编码->UTF-8(iso-8859-1)编码->iso-8859-1解码->UTF-8解码,编码和解码的过程是对称的,所以不会出现乱码。


代码实现:
jsp:
<a href="javascript:;" onclick="encode()">修改用户名</a>

注:
javascript: 是一个伪协议,表示在触发<a>默认动作时,执行一段JavaScript代码。

而 javascript:; 表示不作任何操作,这样会防止链接跳转到其他页面。

这么做是为了保留链接的样式,但不让链接执行实际操作,具体的操作交给链接的onclick事件处理。

js:
<script type="text/javascript">
	function encode() {
		var name = document.getElementById("username").innerHTML;
		window.location.href = "${pageContext.request.contextPath}/user/getUserInfo?username=" + encodeURI(encodeURI(name));
	}
</script>
后台:
try {
	user.setUsername(URLDecoder.decode(user.getUsername(), "UTF-8")); // 解码
	} catch (UnsupportedEncodingException e) {
		e.printStackTrace();
	}

测试小BUG:使用eclipse的内置浏览器时发现 window.location.href 跳转失效,换用其他浏览器就好了。

参考:
  1. https://blog.csdn.net/u012564085/article/details/80003283
  2. https://blog.csdn.net/SmuEdward/article/details/51755298
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值