关于使用httpclient传递json数据乱码的问题


首先由此链接 http://www.cnblogs.com/soundcode/p/6560947.html的文章得到的启发


今天用httpclient传输json数据,服务端接受数据 中文乱码,下面分别贴上修改前与修改后的代码以及原因分析

(1)修改前:

client端

	public String sendHttpPost(String httpUrl, String data) {
		
		// 创建post请求
		HttpPost httpPost = new HttpPost(httpUrl);
		StringEntity entity;
		try {
			entity = new StringEntity(data);
			entity.setContentEncoding("UTF-8");
			entity.setContentType("application/json");
			httpPost.setEntity(entity);
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return sendHttpPost(httpPost);
	}

private String sendHttpPost(HttpPost httpPost) {

		CloseableHttpClient httpClient = null;
		CloseableHttpResponse response = null;
		HttpEntity entity = null;
		String responseContent = null;

		// 创建默认的httpclient实例
		httpClient = HttpClients.createDefault();
		httpPost.setConfig(requestConfig);
		httpPost.setHeader("Accept","aplication/json");
		httpPost.addHeader("Content-Type","application/json;charset=UTF-8");
		// 执行请求
		try {
			logger.info("开始同步数据");
			response = httpClient.execute(httpPost);
			entity = response.getEntity();
			responseContent = EntityUtils.toString(entity, "UTF-8");
			logger.info("数据同步结果:" + responseContent);
		} catch (IOException e) {
			logger.error("同步数据出错:" + e.toString());
			e.printStackTrace();
		} finally {
			try {
				if (response != null) {
					response.close();
				}
				if (httpClient != null) {
					httpClient.close();
				}

			} catch (Exception e2) {
				logger.error("流关闭出错:" + e2.toString());
			}

		}
		return responseContent;
	}
(2)修改后

client端

	public String sendHttpPost(String httpUrl, String data) {
			
		// 创建post请求
		HttpPost httpPost = new HttpPost(httpUrl);
		StringEntity entity;
		entity = new StringEntity(data,"UTF-8");
		entity.setContentType("application/json");
		//entity.setContentType(new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));//用这个跟上面一行那个结果一样,可以查看源码
		httpPost.setEntity(entity);
		
		return sendHttpPost(httpPost);
	}

	private String sendHttpPost(HttpPost httpPost) {

		CloseableHttpClient httpClient = null;
		CloseableHttpResponse response = null;
		HttpEntity entity = null;
		String responseContent = null;

		// 创建默认的httpclient实例
		httpClient = HttpClients.createDefault();
		httpPost.setConfig(requestConfig);
		httpPost.setHeader("Accept","aplication/json");
		
		httpPost.addHeader("Content-Type","application/json;charset=UTF-8");
	}

 

服务端 代码

	//服务端 代码 通过红色字体的代码接受数据
	public Map<String, Object> getRequestPostParams(HttpServletRequest request) throws BusinessException {
		try {
			//接收数据
			StringBuffer sb = new StringBuffer() ;
			InputStream is = request.getInputStream(); 
			InputStreamReader isr = new InputStreamReader(is, "utf-8");   
			BufferedReader br = new BufferedReader(isr); 
			String s = "" ; 
			while((s=br.readLine())!=null){ 
				
				sb.append(s) ; 
			} 
			String strData = sb.toString();
			
			if (null == strData || "".equals(strData)) {
				return new HashMap<String, Object>();
			}
			Map<String, Object> params = this.parseJSON2Map(strData);
			return params;
			
		} catch(Exception e) {
			throw new BusinessException(BusinessException.ERROR_INNER, "参数转换错误!");
		}
	}


下面来解释原因:

看到这里  发现了client端的不同的吧,没错 只有一行代码不一样


entity = new StringEntity(data,"UTF-8");

就是这行代码,因为构造方法的不同造成的

本来参考了 http://www.cnblogs.com/soundcode/p/6560947.html这个博客的文章把问题解决了,但是我发现 我自己的代码明明也设置额编码 为什么会出现乱码呢,于是我就去看源代码的实现,差异在哪里? 下面贴上源代码


	 public StringEntity(final String string, final ContentType contentType) throws UnsupportedCharsetException {
			
		super();
		Args.notNull(string, "Source string");
		Charset charset = contentType != null ? contentType.getCharset() : null;
		if (charset == null) {
		    charset = HTTP.DEF_CONTENT_CHARSET;
		}
		try {
		    this.content = string.getBytes(charset.name());
		} catch (final UnsupportedEncodingException ex) {
		    // should never happen
		    throw new UnsupportedCharsetException(charset.name());
		}
		if (contentType != null) {
		    setContentType(contentType.toString());
		}
		
	}


然后就发现,在new StringEntity的时候,就已经将数据根据编码进行了处理,也就是说,如果你调用 new StringEntity(String string)此构造方法,就会使用其默认的编码进行转码(ISO-8859-1),无论你后面设置多少次(


entity.setContentEncoding("UTF-8");


或者


httpPost.addHeader("Content-Type","application/json;charset=UTF-8");


 

都不会改变字符串已经被按转码变成Byte[]数组的事实,当然在请求中设定传输编码格式还是要做的。

其实说这么多 ,解决问题的关键就一句话,在new StringEntity()的时候指定编码就解决了,因为在new的同时已经做了字符串的转码操作

之所以说这么多,是想告诉自己,问题解决了固然是好,但应该知道为什么这么做,多看源码,多问自己为什么,仅此共勉。


本人也是刚毕业的小菜鸟一个,有不足之处欢迎补充,谢谢!






评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值