文档章节

request.setCharacterEncoding 关于编码 概述

Zero零_度
 Zero零_度
发布于 2015/05/06 10:57
字数 1489
阅读 39
收藏 1

request.setCharacterEncoding 关于编码

 

概述
从Servlet2.3开始,支持客户端内容协商。服务端内容协商,很早就有,服务端在返回的数据中通过Content-Type来指定返回的数据内容。在REST叫嚣的背景下,客户端也需要协商:例如通过PUT方法提交一段XML或JSON数据来更新服务端的一个对象。客户端可通过URL后缀名.xml或.json的方式来告诉服务端提交的数据类型;也可通过HTTP头的Content-Type来告之服务端提交的数据类型。

 

关于该问题的Blog

【1】给出了两个办法

http://forum.springsource.org/showthread.php?t=14063

Hi,
I am woking on a site that receives input in CJK .
This may be a naive  question:
I am using org.springframework.web.servlet.DispatcherServlet as my servlet and I need to set CharacterEnconding on the HttpServletRequest.
I looked into the source code and I relaized there is no code that calls setCharacterEncoding

I dig into the forum and found 2 solutions:

1. Use the CharacterEncodingFilter

2. Override DispatcherServlet.doService  as:

public class MyServlet extends DispatcherServlet {
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
request.setCharacterEncoding( "UTF-8" );
super.doService( request , response ) ;
}
}

I tried to do #1 for it seems to be more desirable (cleaner) solution.
in web.xml I added:
< filter>
< filter-name>CharacterEncodingFilter</filter-name>
< filter-class>
org.springframework.web.filter.CharacterEncodingFi lter</filter-class>
< init-param>
< param-name>encoding</param-name>
< param-value>UTF-8</param-value>
< /init-param>
< /filter>
< filter-mapping>
< filter-name>CharacterEncodingFilter</filter-name>
< url-pattern>/*</url-pattern>
< /filter-mapping>

But it doesn't seem to work.
Could someone tell me how to do that? Use CharacterEncodingFilter?
Thanks in advance.

 

【2】注意事项

http://www.junlu.com/msg/125726.html

With the 2.3 servet API, there is a new method:
 request.setCharacterEncoding(String encoding)
通过Content-Type告诉服务端当前请求编码:
This lets you tell the server a request's character encoding.
(例如HTTP头: Content-Type:    text/html; charset=UTF-8
Content-Type:application/x-www-form-urlencoded; charset=UTF-8)

It is critical that  setCharacterEncoding is called BEFORE any
request.getParameter is called (or getReader). Otherwise, you are at the
mercy of the appserver for what you get back on the getParameter call.

For example, if setCharacterEncoding is not called, you could get a null
value back on getParameter("foo").

 

 

解决该问题:客户端协商编码方式

客户端协商http请求编码方式代码  收藏代码

  1. private String negotiateCharacterEncoding(HttpServletRequest request,Map<String,String> outParam) {  

  2.         String clientEncoding = request.getCharacterEncoding();//HTTP标准:客户端声称的编码(但是目前大多数浏览器并未实施该标准)  

  3.         outParam.put("point","HTTP标准");  

  4.         //协商过程:  

  5.         //1. 通过HTTP标准指定客户端编码;(在HTTP头中设置:Content-Type    =[text/html; charset=UTF-8])  

  6.         //2. 通过自定义HTTP头(Client-Charset)指定客户端编码;  

  7.         //3. 通过自定义HTTP查询参数(Client-Charset)指定客户端编码(只针对HTTP-GET方法)。(以免动态script标签发起请求时设置不了HTTP头;编码数值都是英文字符,提取编码数值跟编码无关。)  

  8.         //4. 如果所有的协商都没有,那么服务端强制使用配置:defaultEncoding  

  9.         //5. 如果服务端没有配置defaultEncoding,那么使用容器默认的ISO-8...(如果上述指定的编码不被支持,那么依然使用容器默认的)  

  10.         if(clientEncoding==null || clientEncoding.trim().equals("")) {  

  11.             clientEncoding = request.getHeader("Client-Charset");  

  12.             outParam.put("point","自定义HTTP头");  

  13.             if(clientEncoding==null || clientEncoding.trim().equals("")) {  

  14. //              clientEncoding = request.getParameter("Client-Charset");//不能通过该方式提取Client-Charset参数  

  15. //request.setCharacterEncoding(encoding);发挥作用的前提是:调用setCharacterEncoding之前不能执行任何request.getParameter  

  16.                 if("GET".equalsIgnoreCase(request.getMethod())) {  

  17.                     String queryString = request.getQueryString();  

  18.                     if(queryString!=null && !queryString.equals("")) {  

  19.                         //定位参数[Client-Charset]的起始和终止位置  

  20.                         int startIndex = queryString.indexOf("Client-Charset=");  

  21.                         int endIndex = -1;  

  22.                         if(startIndex!=-1) {  

  23.                             startIndex = startIndex+"Client-Charset=".length();  

  24.                             endIndex = queryString.indexOf("&", startIndex);  

  25.                             if(endIndex==-1) {//Client-Charset是最后一个参数  

  26.                                 int sessionidIndex = queryString.indexOf(";", startIndex);//去掉基于URL的SessionID  

  27.                                 if(sessionidIndex!=-1) {  

  28.                                     endIndex = sessionidIndex;  

  29.                                 } else {  

  30.                                     endIndex = queryString.length();  

  31.                                 }  

  32.                             }  

  33.                         }  

  34.                         if(startIndex<endIndex) {  

  35.                             clientEncoding = queryString.substring(startIndex, endIndex);  

  36.                             outParam.put("point","自定义HTTP查询参数");  

  37.                         }  

  38.                     }  

  39.                 }  

  40.             }  

  41.             if(clientEncoding==null || clientEncoding.trim().equals("")) {  

  42.                 clientEncoding = defaultEncoding;  

  43.                 outParam.put("point","服务端配置");  

  44.             }  

  45.               

  46.         }  

  47.         return clientEncoding;  

  48.     }  

 

设置编码方式代码  收藏代码

  1. if (encoding != null) {  

  2.             try {  

  3.                 request.setCharacterEncoding(encoding);//注:被强制认为是GBK编码,好处在于客户端在提交GET请求时不再需要做URLEncode处理了。不好的是,如果客户端提交以UTF-8的编码,则编码出错了。  

  4.                 //http://www.junlu.com/msg/125726.html  

  5.             } catch (Exception e) {  

  6.                 log.error("Error setting character encoding to '" + encoding  

  7.                         + "' - ignoring.", e);  

  8.             }  

  9.         }  

 

测试用例

/modifyListener_test.htm?nick=繁體昵稱衝頂&mobile=13812345678
/modifyListener_test.htm?nick=%B7%B1%F3%77%EA%C7%B7%51%D0%6E%ED%94&mobile=13812345678&Client-Charset=GBK
/modifyListener_test.htm?nick=%E7%B9%81%E9%AB%94%E6%98%B5%E7%A8%B1%E8%A1%9D%E9%A0%82&mobile=13812345678&Client-Charset=UTF-8


/modifyListener_test.htm?nick=涛&mobile=13812345678
/modifyListener_test.htm?nick=%CC%CE&mobile=13812345678&Client-Charset=GBK
/modifyListener_test.htm?nick=%CC%CE&mobile=13812345678
/modifyListener_test.htm?nick=%E6%B6%9B&mobile=13812345678&Client-Charset=UTF-8
/modifyListener_test.htm?nick=%E6%B6%9B&mobile=13812345678  //出错:输入是UTF-8,却被服务器强制为GBK (###nick=娑?,mobile=13812345678)
/modifyListener_test.htm?nick=%E6%B6%9B&mobile=13812345678&Client-Charset=UTF-8;12345
/modifyListener_test.htm?Client-Charset=UTF-8&nick=%E6%B6%9B&mobile=13812345678;12345 //nick=涛,mobile=13812345678;12345


/modifyListener_test.htm?nick=%E6%B6%9B&mobile=13812345678
并设置包头:
Content-Type:    text/html; charset=UTF-8

Content-Type:    charset=UTF-8
//协商或配置的编码:UTF-8,协商源:HTTP标准

 

问题答复:

Passport有一个全局的Filter,强制所有的HTTP请求的编码为GBK,所以支持不了URLEncode(UTF-8)。我想了这么些办法,都不行:
1、    把这个全局的Filter去掉,不强制为GBK,现有线上的那些没有编码的东西支持不了。
这样设置,对于那些没有编码的数据,比如:http://localhost/modifyListener_test.htm?nick=繁體昵稱衝頂&mobile=13812345678 提取的nick则会出错。因此会影响线上其他地方。

2、    手动从GBK再转UTF-8,部分数据能支持,有些不支持。(GBK和UTF-8字符集毕竟不是包含与被包含的关系,其中有冲突的部分)
New String(nick.getBytes(“GBK”),”UTF-8”)  对于http://localhost/modifyListener_test.htm?nick=繁體昵稱衝頂&mobile=13812345678能转换出“繁體昵稱衝頂”;但对于
http://localhost/modifyListener_test.htm?nick=涛&mobile=13812345678  其中“波涛”的“涛”则转换失败。

现在一个可行的解决办法是通过HTTP头协商,需要麻烦你那边在请求中加一个参数:
1、    在HTTP头部增加参数:Content-Type,并设置数值:charset=UTF-8   (备注:在HTTP头里设置Client-Charset参数,数值为UTF-8也行。但前提是Content-Type没被设置为其他)
这样设置后,nick就可以支持URLEncode(UTF-8)了。


2、    对于动态script标签的请求,由于无法设置HTTP头,后台支持查询参数:Client-Charset
比如:这样提交HTTP请求:  nick=%E6%B6%9B&mobile=13812345678&Client-Charset=UTF-8

本文转载自:http://blog.csdn.net/zklxuankai/article/details/7665244

Zero零_度
粉丝 69
博文 1267
码字总数 263854
作品 0
程序员
私信 提问
关于Servlet出现乱码问题

一般的处理乱码的方式都是用: request.setCharacterEncoding("GBK") 但是这种方法只对POST方法提交的表单才有效果。 网上资料显示:自从Tomcat5.x开始,GET和POST方法提交的信息,Tomcat采用...

凡尘里的一根葱
2015/09/30
27
0
Tomcat下java web的编码问题

/ 关于java web中文编码问题,若想刨根问底,强烈建议阅读《深入分析java web技术内幕》第3章/ 一,请求处理 1,GET请求 方式1:修改tomcat配置文件的Connector节点 <Connector port="8080"...

NO17
2016/02/18
57
0
jsp乱码问题

jsp乱码一直是一个困扰我的问题,今天经过百度找到了比较有效的解决方式,总结如下: 第一步:配置编码过滤器,在doFilter()中设置request.setCharacterEncoding("UTF-8");这种过滤一般只是对...

学习的小猪
2014/03/26
0
0
解决Servlet从前台接值时乱码的方法

用GET方式提交(经测,POST也可以,原因很简单): String name = request.getParameter("name");name = new String(name.getBytes("ISO-8859-1"),"UTF-8"); 用POST方式提交: request.setC......

flying-tomato
2015/06/30
544
0
Java Web中文乱码问题解决

一、为什么会出现中文乱码问题: java内核和class文件是基于unicode码的,这使Java程序具有良好的跨平台性,但也导致在Java和JSP文件在编译时以及Java程序与其他媒介交互时等情况下产生中文乱...

ws199358
2016/09/13
20
0

没有更多内容

加载失败,请刷新页面

加载更多

OSChina 周五乱弹 ——不知道假装开心,装的像么

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @巴拉迪维 :天黑了 你很忧愁, 你说世界上, 找不到四块五的妞, 行走在凌晨两点的马路上, 你疲倦地拿着半盒黄鹤楼。#今日歌曲推荐# 《四块...

小小编辑
今天
2.1K
16
64.监控平台介绍 安装zabbix 忘记admin密码

19.1 Linux监控平台介绍 19.2 zabbix监控介绍 19.3/19.4/19.6 安装zabbix 19.5 忘记Admin密码如何做 19.1 Linux监控平台介绍: 常见开源监控软件 ~1.cacti、nagios、zabbix、smokeping、ope...

oschina130111
昨天
69
0
当餐饮遇上大数据,嗯真香!

之前去开了一场会,主题是「餐饮领袖新零售峰会」。认真听完了餐饮前辈和新秀们的分享,觉得获益匪浅,把脑子里的核心纪要整理了一下,今天和大家做一个简单的分享,欢迎感兴趣的小伙伴一起交...

数澜科技
昨天
32
0
DNS-over-HTTPS 的下一代是 DNS ON BLOCKCHAIN

本文作者:PETER LAI ,是 Diode 的区块链工程师。在进入软件开发领域之前,他主要是在做工商管理相关工作。Peter Lai 也是一位活跃的开源贡献者。目前,他正在与 Diode 团队一起开发基于区块...

红薯
昨天
116
0
CC攻击带来的危害我们该如何防御?

随着网络的发展带给我们很多的便利,但是同时也带给我们一些网站安全问题,网络攻击就是常见的网站安全问题。其中作为站长最常见的就是CC攻击,CC攻击是网络攻击方式的一种,是一种比较常见的...

云漫网络Ruan
昨天
31
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部