【安卓笔记】android客户端向tomcat服务器发送请求中文乱码问题解决

时间:2022-10-30 13:22:19
android客户端请求服务端的url地址中含有中文时将会产生中文乱码问题。 产生乱码的原因有主要以下几个方面: ------------------------------------------------------------------------------------------------     1.当以get方式请求服务端的资源时,没有对url中的中文进行编码。     2.忽略了tomcat默认的编码格式(iso8859-1)。     3.servlet没有对request和response设置正确的编码格式。     4.servlet没有处理get请求方式中的乱码问题。 ------------------------------------------------------------------------------------------------- 解决方案 步骤: 1、客户端对url中中文参数进行编码(使用URLEncoder类)。 这里采用的是最原始的java.net包中提供的URL,HTTPURLConnection类。 请求数据全部封装到map中。 get请求:
/**
* 以get方式向服务端发送请求,并将服务端的响应结果以字符串方式返回。如果没有响应内容则返回空字符串
*
* @param url 请求的url地址
* @param params 请求参数
* @param charset url编码采用的码表
* @return
*/
public static String getDataByGet(String url,Map<String,String> params,String charset)
{
if(url == null)
{
return "";
}
url = url.trim();
URL targetUrl = null;
try
{
if(params == null)
{
targetUrl = new URL(url);
}
else
{
StringBuilder sb = new StringBuilder(url+"?");
for(Map.Entry<String,String> me : params.entrySet())
{
// 解决请求参数中含有中文导致乱码问题
sb.append(me.getKey()).append("=").append(URLEncoder.encode(me.getValue(),charset)).append("&");
}
sb.deleteCharAt(sb.length()-1);
targetUrl = new URL(sb.toString());
}
Log.i(TAG,"get:url----->"+targetUrl.toString());//打印log
HttpURLConnection conn = (HttpURLConnection) targetUrl.openConnection();
conn.setConnectTimeout(3000);
conn.setRequestMethod("GET");
conn.setDoInput(true);
int responseCode = conn.getResponseCode();
if(responseCode == HttpURLConnection.HTTP_OK)
{
return stream2String(conn.getInputStream(),charset);
}
} catch (Exception e)
{
Log.i(TAG,e.getMessage());
}
return "";
}
post请求:
/**
* 以post方式向服务端发送请求,并将服务端的响应结果以字符串方式返回。如果没有响应内容则返回空字符串
* @param url 请求的url地址
* @param params 请求参数
* @param charset url编码采用的码表
* @return
*/
public static String getDataByPost(String url,Map<String,String> params,String charset)
{
if(url == null)
{
return "";
}
url = url.trim();
URL targetUrl = null;
OutputStream out = null;
try
{
targetUrl = new URL(url);
HttpURLConnection conn = (HttpURLConnection) targetUrl.openConnection();
conn.setConnectTimeout(3000);
conn.setRequestMethod("POST");
conn.setDoInput(true);
conn.setDoOutput(true);

StringBuilder sb = new StringBuilder();
if(params!=null && !params.isEmpty())
{
for(Map.Entry<String,String> me : params.entrySet())
{
// 对请求数据中的中文进行编码
sb.append(me.getKey()).append("=").append(URLEncoder.encode(me.getValue(),charset)).append("&");
// sb.append(me.getKey()).append("=").append(me.getValue()).append("&");//测试发现也可用
}
sb.deleteCharAt(sb.length()-1);
}
byte[] data = sb.toString().getBytes();
conn.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
conn.setRequestProperty("Content-Length", String.valueOf(data.length));
out = conn.getOutputStream();
out.write(data);

Log.i(TAG,"post:url----->"+targetUrl.toString());//打印log

int responseCode = conn.getResponseCode();
if(responseCode == HttpURLConnection.HTTP_OK)
{
return stream2String(conn.getInputStream(),charset);
}
} catch (Exception e)
{
Log.i(TAG,e.getMessage());
}
return "";
}
stream2String方法(将流对象中的数据转化为字符串):
/**
* 将输入流对象中的数据输出到字符串中返回
* @param in
* @return
* @throws IOException
*/
private static String stream2String(InputStream in,String charset) throws IOException
{
if(in == null)
return "";
byte[] buffer = new byte[1024];
ByteArrayOutputStream bout = new ByteArrayOutputStream();
int len = 0;
while((len = in.read(buffer)) !=-1)
{
bout.write(buffer, 0, len);
}
String result = new String(bout.toByteArray(),charset);
in.close();
return result;
}
测试时,我们也确实发现对get请求中url中的中文进行了编码:
【安卓笔记】android客户端向tomcat服务器发送请求中文乱码问题解决
2、服务端对request和response设置正确的编码格式。首先在servlet中加上这几行代码.
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");
这还没有完,以上仅处理了post请求的乱码问题,当用户以get方式请求时仍然有乱码。所以你还需要加上这行代码:
if(req.getMethod().equalsIgnoreCase("GET"))
{
name = new String(name.getBytes("iso8859-1"),"utf-8");
}
之所以要判断一下请求的方式是是否为get,是因为如果请求方式为post的话,又会变成乱码了,当然,如果你在servlet中对doPost和doGet分别进行乱码处理,那就不用判断了。只是大多数人更喜欢这样写:
public class xxxServlet extends HttpServlet
{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException
{
//TODO
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException
{
this.doGet(req, resp);
}
}
此时一定要在doget方法中加上判断.当然你还有另一种选择,那就是过滤器,配置如下所示的过滤器即可处理上述的乱码。编码格式在web.xml中手动配置,避免硬编码。(context-param中配置)
package cn.chd.edu.filter;

import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class CharacterEncodingFilter implements Filter
{
private static String charset = "iso8859-1";//默认编码

public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException
{
System.out.println("filter running...");

final HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
req.setCharacterEncoding(charset);
resp.setCharacterEncoding(charset);
resp.setContentType("text/html;charset="+charset);

chain.doFilter((ServletRequest) Proxy.newProxyInstance(CharacterEncodingFilter.class.getClassLoader(), req.getClass().getInterfaces(),new InvocationHandler()
{
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable
{
if(!method.getName().equals("getParameter"))//拦截getParameter方法
{
return method.invoke(req, args);
}
if(!req.getMethod().equalsIgnoreCase("get"))//拦截get请求
{
return method.invoke(req, args);
}
String value = (String) method.invoke(req, args);
if(value == null)
return null;
return new String(value.getBytes("iso8859-1"),charset);
}
}),resp);
}

public void init(FilterConfig filterConfig) throws ServletException
{
String temp = filterConfig.getServletContext().getInitParameter("charset");
if(temp != null)
charset = temp;
}
public void destroy()
{

}
}
对过滤器不熟悉的参考这篇文章:filter详解