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方式向服務端發送請求,並將服務端的響應結果以字串方式返回。如果沒有響應內容則返回Null 字元串 * * @param url 請求的url地址 * @param params 請求參數 * @param charset url編碼採用的碼錶 * @return */ public static String getDataByGet(String url,Map 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 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方式向服務端發送請求,並將服務端的響應結果以字串方式返回。如果沒有響應內容則返回Null 字元串 * @param url 請求的url地址 * @param params 請求參數 * @param charset url編碼採用的碼錶 * @return */ public static String getDataByPost(String url,Map 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 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中的中文進行了編碼:
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詳解