request.setCharacterEncoding 关于编码 概述

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. return clientEncoding;
  47. }

设置编码方式代码  

  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

时间: 2024-09-30 00:23:30

request.setCharacterEncoding 关于编码 概述的相关文章

request.setcharacterencoding()和request.setcontenttype(“html/css;charset”)的格式区别

1.request.setCharacterEncoding()是设置从request中取得的值或从数据库中取出的值 指定后可以通过getParameter()则直接获得正确的字符串,如果不指定,则默认使用iso8859-1编码.值得注意的是在执行setCharacterEncoding()之前,不能执行任何getParameter().而且,该指定只对POST方法有效,对GET方法无效.分析原因,应该是在执行第一个getParameter()的时候,Java将会按照编码分析所有的提交内容,而后

request,response,URL编码,路径专题

一.Response 1.Resonse的继承结构: ServletResponse--HttpServletResponse 2.Response代表响应,于是响应消息中的 状态码.响应头.实体内容都可以由它进行操作,由此引伸出如下实验: 3.利用Response输出数据到客户端 response.getOutputStream().write("中文".getBytes())输出数据,这是一个字节流,是什么字节输出什么字节,而浏览器默认用平台字节码打开服务器发送的数据,如 果服务器

response.setContentType与 request.setCharacterEncoding 区别

1.request.setCharacterEncoding()是设置从request中取得的值或从数据库中取出的值的编码 2.response.setContentType指定 HTTP 响应的编码,同时指定了浏览器显示的编码. 3.response.setCharacterEncoding设置HTTP 响应的编码,如果之前使用response.setContentType设置了编码格式,则使用response.setCharacterEncoding指定的编码格式覆盖之前的设置. 与resp

解决为什么已经设置了request.setCharacterEncoding(&quot;utf-8&quot;);POST请求仍然乱码的问题

request.setCharacterEncoding("utf-8");应该在获取请求参数之前设置 在 http://bbs.csdn.net/topics/380124606 和 http://bbs.csdn.net/topics/370125113 找到的答案 由于POST传来数据,Tomcat默认以ISO-8859-1编码成单字节数据,若没有进行请求编码设置或重新编码操作,那么中文字符会在jsp页面中输出???,出现类似多个?形式的乱码现象. 测试发现,尽管jsp页面con

request.setCharacterEncoding(&quot;utf-8&quot;);

request.setCharacterEncoding("utf-8");不加这句话时,从input控件得到值要用new String(request.getParameter("").getBytes("ISO-8859-1"),"utf-8")方法,而从 a href=""中得到值直接用request.getParameter("")方法:而加入了这句话后,从input控件得到值直

网络编码概述

网络编码概述  网络编码,是指一种融合了路由和编码的信息交换技术,其核心思想,是在网络中的各个节点上,对各条信道上收到的信息进行线性或者非线性的处理,然后转发给下游节点,中间节点扮演着编码器或信号处理器的角色.网络编码已经被证明可以极大地提高网络的吞吐量和可靠性,可以分为流内网络编码与流间网络编码两类.其中,流间网络编码是指网络节点将不同的数据包编码进行收集和整理组合,之后通过广播的形式发送出去,从而有效提高数据包单次传输时的信息量,减少信息的传输次数,从而提高网络吞吐量:流内网络编码是指网络节

译-BMC Remedy Action Request System权限控制概述

原文链接:Access control overview 说明: BMC Remedy Action Request System是BMC ITSM产品平台,简称AR 或者Remedy,可实现基于ITIL标准的整个IT管理流程的实施定制.该平台可实现多种权限级别的管理,包括人员.组.角色,以及表.字段.行级别等.本文可以用作其他对权限要求比较精细的系统参考. 为了便于理解,部分名词翻译如下: Server:服务器Form (or table):表单Field (or column):字段Acti

转:urllib.request.urlopen字符编码报错

错误内容:UnicodeEncodeError: 'ascii' codec can't encode characters in position 28-29: ordinal not in range(128) 1.以为是代码错误,检查tab符,并没有问题, 2.将代码粘贴到空白项目中去,发现还是不对. 3.百度:http://blog.csdn.net/olanlanxiari/article/details/48201231 1.Python在安装时,默认的编码是ascii,当程序中出现

字符编码概述

1 字符编码是什么? 我们知道,计算机数据只能是二进制的,数值类型的数据转换成二进制很简单,我们已经了解了,但字符类型如何转换成二进制呢?这就需要使用字符编码! 在编码表中,每个字符都有对应的编码,编码是整数,最终在计算机中存储的是字符的编码,而不是字符本身(因为计算机数据都是二进制数值,所以字符本身是无法存储的). 当我们存储字符’A’时,其实是通过编码表找到’A’字符对应的编码,然后把编码存储在计算机中.即存储的是65. 当我们读取字符时,其实读取的也是字符的编码,然后使用编码再去编码表中查