- 有时候我们在处理 get 请求时,比如下面的一个 url 跳转
window.location.href = "某个 url"
当你的 url 里存在某个参数为中文字符,那么你就可能遇到乱码问题,为什么说可能呢,因为 tomcat 默认编码其实是 ISO-8859-1,如果你在 tomcat 服务器配置了 utf-8 编码的话(config 目录下的 server.xml 文件),就不会出乱码了,配置如下(注意在你的使用的端口里配置,一般都是在 8080 端口下配置一下 URIEncoding)
<Connector port="8080" protocol="HTTP/1.1" | |
connectionTimeout="20000" | |
redirectPort="8443" URIEncoding="UTF-8"/> |
- 现在我们不在服务器里做上面配置,那么就需要使用到 js 的编码技术以及 java.net 包提供的解码技术,首先比如说我们传的 url 里存在一个参数 departName=“教育 BG 研发中心”,那么我们调用 js 的方法进行编码 encodeURI (encodeURI (departName)),如下:
var departName = encodeURI(encodeURI(departName)); | |
window.location.href = "http://a.b.c?departName="+departName; |
为什么做两次编码呢?
原因如下:
- 利用 encodeURI () 在 javascript 中对中文 URL 参数进行编码时,你的中文参数会被转换为类似于 “% E6% B5%8B% E8% AF%95” 这种字符串
- 但是浏览器机制会认为 “%” 是一个转义字符,浏览器会把地址栏 URL 中的传递的已转换参数 “%” 与 “%” 之间的已转义字符进行处理传递到后台 Action(接口)中。这样会造成与实际经过 encodeURI () 编码后的 URL 不符,因为浏览器误认为 “%” 是转义字符字符了,它并未将 “%” 认为是个普通字符。
- 要使得通过 encodeURI () 转换后的 URL 被浏览器正常处理,必须在外层再用 encodeURI () 处理一次已被 encodeURI () 编码后的 RUL。这此处理 encodeURI () 会将已编码后的 URL 中被浏览器解析为转义字符的 “%” 再次进行编码,转换为普通字符。
这个时候,在后台接口里使用 java.net 做一下转换就可以了:
String depName = java.net.URLDecoder.decode(request.getParameter("departName"), "UTF-8"); |
上面的转换方式是:js 前端转 2 次,后端转 1 次;
网上还有一种方式是:js 转一次,后端转 2 次,这个没有尝试,贴出来如下:
url=encodeURI(url) |
String app_name = java.net.URLDecoder.decode(request.getParameter("name"), "utf-8"); | |
app_name = new String(app_name.getBytes("ISO-8859-1"),"utf-8"); |
- 至于有些人疑惑 post 传递的参数里也有中文,为什么从前台传递过来不乱码呢?
原因是 post 是以数据包的形式将封装好的参数传递给后台,中间不会做编码转换相关的处理,所以后台直接获取也不会出现乱码。
当然有时 post 是会乱码的(比如使用 HttpClient 包下的工具,远程调用其它服务器的接口,偶尔会遇到这种乱码的情况),此时可以在接收时设置一下编码,如下几种方式:
1.java 代码里设置
request.setCharacterEncoding("UTF-8"); |
- 从 web 配置文件设置
<filter> | |
<description>字符集过滤器</description> | |
<filter-name>encodingFilter</filter-name> | |
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> | |
<init-param> | |
<description>字符集编码</description> | |
<param-name>encoding</param-name> | |
<param-value>UTF-8</param-value> | |
</init-param> | |
</filter> | |
<filter-mapping> | |
<filter-name>encodingFilter</filter-name> | |
<url-pattern>/*</url-pattern> | |
</filter-mapping> |
- 使用 HttpURLConnection 远程访问:
HttpURLConnection connection = null; | |
connection.setRequestProperty("contentType", "utf-8"); |
- 使用 InputStreamReader 读取流时
InputStreamReader in = null; | |
in = new InputStreamReader(connection.getInputStream(),"utf-8"); | |
BufferedReader bufferedReader = new BufferedReader(in); | |
StringBuffer stringBuffer = new StringBuffer(); | |
String line = null; | |
while ((line = bufferedReader.readLine()) != null) { | |
stringBuffer.append(line); | |
} | |
result = stringBuffer.toString(); |
- 使用 HttpClient 的 HttpGet 时
CloseableHttpClient httpclient = httpClientBuilder.build(); | |
HttpGet httpget = new HttpGet("url"); | |
CloseableHttpResponse response = httpclient.execute(httpget); | |
String content = EntityUtils.toString(response.getEntity(), "UTF-8"); |
- 使用 HttpClient 的 HttpPost 时
CloseableHttpClient httpclient = httpClientBuilder.build(); | |
HttpPost httpPost = new HttpPost(url); | |
List<BasicNameValuePair> params = new ArrayList<>(); | |
params.add(new BasicNameValuePair("userAccount",userAccount)); | |
params.add(new BasicNameValuePair("token",token)); | |
UrlEncodedFormEntity httpEntity= new UrlEncodedFormEntity(valuePairs, "UTF-8"); | |
httpMethod.setEntity(httpEntity); | |
CloseableHttpResponse response = httpclient.execute(httpMethod); | |
String content = EntityUtils.toString(response.getEntity(), "UTF-8"); |
具体前端 js 编码的使用说明可以参考 w3c 的文档:http://www.w3school.com.cn/jsref/jsref_encodeuri.asp
语法:encodeURI (URIstring)
参数 URIstring 描述:必需。一个字符串,含有 URI 或其他要编码的文本。
返回值:URIstring 的副本,其中的某些字符将被十六进制的转义序列进行替换。
说明:
- 该方法不会对 ASCII 字母和数字进行编码,也不会对这些 ASCII 标点符号进行编码: - _ . ! ~ * ' ( ) 。
- 该方法的目的是对 URI 进行完整的编码,因此对以下在 URI 中具有特殊含义的 ASCII 标点符号,encodeURI () 函数是不会进行转义的:;/?😡&=+$,#
提示和注释:如果 URI 组件中含有分隔符,比如?和 #,则应当使用 encodeURIComponent () 方法分别对各组件进行编码。