`
eyesmore
  • 浏览: 364775 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

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").

 

 

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

private String negotiateCharacterEncoding(HttpServletRequest request,Map<String,String> outParam) {
		String clientEncoding = request.getCharacterEncoding();//HTTP标准:客户端声称的编码(但是目前大多数浏览器并未实施该标准)
		outParam.put("point","HTTP标准");
		//协商过程:
		//1. 通过HTTP标准指定客户端编码;(在HTTP头中设置:Content-Type	=[text/html; charset=UTF-8])
		//2. 通过自定义HTTP头(Client-Charset)指定客户端编码;
		//3. 通过自定义HTTP查询参数(Client-Charset)指定客户端编码(只针对HTTP-GET方法)。(以免动态script标签发起请求时设置不了HTTP头;编码数值都是英文字符,提取编码数值跟编码无关。)
		//4. 如果所有的协商都没有,那么服务端强制使用配置:defaultEncoding
		//5. 如果服务端没有配置defaultEncoding,那么使用容器默认的ISO-8...(如果上述指定的编码不被支持,那么依然使用容器默认的)
		if(clientEncoding==null || clientEncoding.trim().equals("")) {
			clientEncoding = request.getHeader("Client-Charset");
			outParam.put("point","自定义HTTP头");
			if(clientEncoding==null || clientEncoding.trim().equals("")) {
//				clientEncoding = request.getParameter("Client-Charset");//不能通过该方式提取Client-Charset参数
//request.setCharacterEncoding(encoding);发挥作用的前提是:调用setCharacterEncoding之前不能执行任何request.getParameter
				if("GET".equalsIgnoreCase(request.getMethod())) {
					String queryString = request.getQueryString();
					if(queryString!=null && !queryString.equals("")) {
						//定位参数[Client-Charset]的起始和终止位置
						int startIndex = queryString.indexOf("Client-Charset=");
						int endIndex = -1;
						if(startIndex!=-1) {
							startIndex = startIndex+"Client-Charset=".length();
							endIndex = queryString.indexOf("&", startIndex);
							if(endIndex==-1) {//Client-Charset是最后一个参数
								int sessionidIndex = queryString.indexOf(";", startIndex);//去掉基于URL的SessionID
								if(sessionidIndex!=-1) {
									endIndex = sessionidIndex;
								} else {
									endIndex = queryString.length();
								}
							}
						}
						if(startIndex<endIndex) {
							clientEncoding = queryString.substring(startIndex, endIndex);
							outParam.put("point","自定义HTTP查询参数");
						}
					}
				}
			}
			if(clientEncoding==null || clientEncoding.trim().equals("")) {
				clientEncoding = defaultEncoding;
				outParam.put("point","服务端配置");
			}
			
		}
		return clientEncoding;
	}

 

if (encoding != null) {
			try {
				request.setCharacterEncoding(encoding);//注:被强制认为是GBK编码,好处在于客户端在提交GET请求时不再需要做URLEncode处理了。不好的是,如果客户端提交以UTF-8的编码,则编码出错了。
				//http://www.junlu.com/msg/125726.html
			} catch (Exception e) {
				log.error("Error setting character encoding to '" + encoding
						+ "' - ignoring.", e);
			}
		}
 

测试用例

/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

分享到:
评论

相关推荐

    java 的乱码教程

    首先,说说JSP/Servlet中的几个编码...charset=UTF-8"、request.setCharacterEncoding("UTF- 8")和response.setCharacterEncoding("UTF-8"),其中前两个只能用于JSP中,而后两个可以用于JSP和 Servlet中。 。。。。。

    用户管理系统(ums)

    request.setCharacterEncoding("GB18030"); //调用业务逻辑 UserDAO userDAO = new UserDAO(); // 返回的list值 ArrayList list=userDAO.queryAll(); //重点。。。HttpSession的用处??? HttpSession...

    JSP对浏览器发送来的数据进行重新编码的两种方式

    charset=GB18030″、request.setCharacterEncoding(“GB18030”)和 response.setCharacterEncoding(“GB18030”),其中前两个只能用于JSP中,而后两个可以用于JSP和Servlet 中。 这里,我们只谈一

    全文修改编码

    全文修改编码,request.setCharacterEncoding("gb2312"); 或者单个修改 out.print("用户名:"+new String(request.getParameter("name").getBytes("iso-8859-1"),"gb2312")+" ");

    web程序开发中的URL乱码解决方案

    在服务器端/后台/后台程序中设置请求流和响应流的编码方式和页面上的编码方式一致:request().setCharacterEncoding("utf-8");response().setCharacterEncoding("ut f-8");response().setContentType("text/html;...

    android和服务器的URLEncodedUtils乱码编码问题的解决方案

    在android开发中我们常常遇到与到乱码问题...这两中方式来确定编码方式服务器端有request.setCharacterEncoding(“UTF-8”);response.setCharacterEncoding(“UTF-8”);来确定响应的编码格式。这样一般是不会出现乱码,

    乱码问题解决方案

    一、有关中文乱码: mysql部分: url配置:jdbc:mysql://localhost:3306/XXX?useUnicode=true&... request.setCharacterEncoding("utf-8"); *在html或者jsp界面更改为UTF-8 ;charset=utf-8" %/&gt;

    JSP 开发中过滤器filter设置编码格式的实现方法

    在你复制粘贴了无数次request.setCharacterEncoding(“gb2312”);后,有没有想要一劳永逸的方法呢?能不能一次性修改所有请求的编码呢? 用Filter吧,它的名字是过滤器, 代码如下: import java.io.IOException...

    JSP读取ORACLE数据乱码问题

    在从oracle数据库中读取数据时出现乱码,但是通过pl/sql developer查询正常。...使用过滤器进行编码转换,request.setCharacterEncoding(gb2312),能够使传参时编码转换成中文,但是从数据库中读来的中文却显示为乱码。

    fckeditor for jsp 的jar包

    },在ConnectorServlet.java的doGet与doPost的开头部分加入request.setCharacterEncoding(encoding);将请求的字符集编码设置成项目中的编码,在ConnectorServlet.java和SimpleUploaderServlet.java两个文件中的...

    解决中文乱码的几种解决方法(推荐)

    首先说明我的特殊情况: ...3. 设置 request.setCharacterEncoding(“UTF-8”); 4. 设置了ServletFileUpload .setHeaderEncoding(“UTF-8”); 5.Tomcat 的配置下面 server.xml 也已经设置了 URIEncoding=”U

    计算机基础课程教学平台+毕业设计+源代码

    request.setCharacterEncoding("GB18030"); //取到表单中用户填写的username,userpassword,userClass参数的值 String username = request.getParameter("username"); String userpassword = request....

    jspSmartUpload.jar

    同时为了解决中文乱码问题,在后台servlet的doPost()或者doGet()方法体的前几行,写request.setCharacterEncoding("GBK");(因为该组件内部使用GBK编码,所以如果使用utf-8的话,反而从表单中会获取中文乱码)...

    jsp页面提交乱码问题

    jsp页面跳转到后台乱码 还需要在html中指定编码格式。 ; charset=gb2312" /&gt; &lt;title&gt;title 解决方法是要在jsp最前面加上一条java语句,设置请求的字符编码。... request.setCharacterEncoding("gb2312"); %&gt;

    response响应数据变成???&使用jquery发送带中文参数数据的get请求得到响应数据乱码解决过程

    request请求数据设置编码使用:request.setCharacterEncoding(“UTF-8”); response响应数据设置编码使用:response.setContentType(“text/html; charset=UTF-8”);点击按钮,发送请求,响应回来的数据还是显示”???...

    ajax中文乱码问题解决方案

    ajax中文乱码问题在中文中经常会出现这种问题,其实只要稍加注意就不会出现ajax中文乱码这回事情了,注意前后台编码一致.你用的是中文.而ajax传输数据的时候... request.setcharacterencoding(“gb2312”); 还有一个更

    jsp和servlet操作mysql中文乱码问题的解决办法

    2、如果乱码是在servlet中出现的,则有两种方法:一种是在每个servlet中doget和doPost方法头部加上request.setCharacterEncoding(“UTF-8″);第二种最保险,一劳永逸,是专门写一个过滤器类,也称国际化,类名为...

    彻底解决fckeditor(jsp版)上传中文图片乱码问题

    },在ConnectorServlet.java的doGet与doPost的开头部分加入request.setCharacterEncoding(encoding);将请求的字符集编码设置成项目中的编码,在ConnectorServlet.java和SimpleUploaderServlet.java两个文件中的...

    session

    session机制代码实现 public class SessionA extends HttpServlet { @Override ... request.setCharacterEncoding("utf-8"); //设置响应编码格式 response.setContentType("text/html;charse

Global site tag (gtag.js) - Google Analytics