且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

小议Servlet接收post和get混合提交中文乱码问题

更新时间:2022-10-12 23:00:47

    网上有很多讲解决Servlet中文乱码的问题,一般的解决方案是加一个过滤器,在doFilter方法中加入:


  1. request.setCharacterEncoding("UTF-8"); 

可是这样并不能解决GET方式传递的数据。如果你能修改tomcat的配置文件,你可以把网址的编码设为UTF-8(或其它):在server.xml的<Connector> 加入 URIEncoding="UTF-8"。当然,更大的可能性是你没有权限修改这个文件,或者有多个网站,但使用了不同的编码。所以需要在doFilter中判断是get还是post后再作相应的处理


  1. if(httpServletRequest.getMethod().toLowerCase().equals("get")){ 
  2.             for(String[] strs : request.getParameterMap().values()){ 
  3.                 for(int i = 0; i < strs.length; i++){ 
  4.                     strs[i] = new String(strs[i].getBytes("ISO-8859-1"), "UTF-8"); 
  5.                     System.out.println(strs[i]); 
  6.                 } 
  7.             } 
  8.         } 
  9.         else
  10.             request.setCharacterEncoding("UTF-8"); 
  11.         } 

这样看起来似乎是完美了,但是实际应用中,经常使用到混合POST和GET方式提交。如用POST方式提交一个单表到www.xxx.com/deal?page=2。如果使用上述的过滤器,自然是按POST方式进行处理,那通过网址传过来的中文数据就会乱码了。

好在可以得到QueryString,似乎只要把QueryString中的出现的参数处理一下就行了(先忽略重复name的问题):


  1. HttpServletRequest httpServletRequest = (HttpServletRequest) request; 
  2. String[] expressions = httpServletRequest.getQueryString().split("&"); 
  3.         for(String expression : expressions){ 
  4.             String[] parts = expression.split("="); 
  5.             if(parts.length == 2){ 
  6.                 request.getParameterMap().put(parts[0], new String[]{ decode(parts[1])}); 
  7.             } 
  8.         } 

运行下。。。OMG。。。java.lang.IllegalStateException: No modifications are allowed to a locked ParameterMap。原来这个Map是不能添加值的。可是第一个过滤器中我却成功修改了值,所以产生了第一种方案,我不用put,我去改values。

 


  1. public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { 
  2.         request.setCharacterEncoding("UTF-8"); //这句得在下面那个强制转换之前,不知道为什么。这句用来处理post的情况
  3.          
  4.         HttpServletRequest httpServletRequest = (HttpServletRequest) request; 
  5.         
  6. //建立一个ArrayList用来存所有的Get方式提交的name对应在Parameter里的value 
  7.         ArrayList<String> queryValues = new ArrayList<String>(); 
  8.         Map<String, String[]> map = request.getParameterMap(); 
  9.         String query = httpServletRequest.getQueryString(); 
  10.         if(query != null){ 
  11.             String[] expressions = query.split("&"); 
  12.             for(String expression : expressions){ 
  13.                 String[] parts = expression.split("="); 
  14.                 if(parts.length == 2){ 
  15.                     String[] values = map.get(parts[0]); 
  16.                     for(String value : values){ 
  17.                         queryValues.add(value); 
  18.                     } 
  19.                      
  20.                 } 
  21.             } 
  22.         } 
  23.  
  24. //遍历value,如果是get方式提交的(存在于queryValues中),就转一下编码
  25.         for(String[] strs : request.getParameterMap().values()){ 
  26.             for(int i = 0; i < strs.length; i++){ 
  27.                 for(String qStr : queryValues){ 
  28.                     if(qStr.equals(strs[i])){ 
  29.                         strs[i] = new String(qStr.getBytes("ISO-8859-1"), "UTF-8"); 
  30.                         //ISO-8859-1是tomcat中默认的,UTF-8是urlencode的编码
  31. break
  32.                     } 
  33.                 } 
  34.             } 
  35.         } 
  36.  
  37.         chain.doFilter(request, response); 
  38.     } 

这样做蛮复杂的,效率又不高。如果post和get中有相同的name,就会出错,可以稍加修改:


  1. public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { 
  2.         request.setCharacterEncoding("UTF-8"); 
  3.          
  4.         HttpServletRequest httpServletRequest = (HttpServletRequest) request; 
  5.          
  6.         ArrayList<String> queryValues = new ArrayList<String>(); 
  7.         Map<String, String[]> map = request.getParameterMap(); 
  8.         String query = httpServletRequest.getQueryString(); 
  9.         if(query != null){ 
  10.             String[] expressions = query.split("&"); 
  11.             for(String expression : expressions){ 
  12.                 String[] parts = expression.split("="); 
  13.                 if(parts.length == 2){ 
  14.                     /*String[] values = map.get(parts[0]); 
  15.                     for(String value : values){ 
  16.                         queryValues.add(value); 
  17.                     }*/ 
  18. //将上面这段修改为
  19.                     String str = URLDecoder.decode(parts[1], "UTF-8"); 
  20.                     System.out.println(str); 
  21.                     queryValues.add(new String(str.getBytes("UTF-8"), "ISO-8859-1")); 
  22.                 } 
  23.             } 
  24.         } 
  25.  
  26.         for(String[] strs : request.getParameterMap().values()){ 
  27.             for(int i = 0; i < strs.length; i++){ 
  28.                 for(String qStr : queryValues){ 
  29.                     if(qStr.equals(strs[i])){ 
  30.                         strs[i] = new String(qStr.getBytes("ISO-8859-1"), "UTF-8"); 
  31.                         break
  32.                     } 
  33.                 } 
  34.             } 
  35.         } 
  36.  
  37.         chain.doFilter(request, response); 
  38.     } 

另一种方案是,把parameter中的成员都放到Attribute中,然后把QueryString中的成员也放到Attribute中,覆盖了parameter中的GET方式提交的成员。缺点是,数据得用getAttribute来读了...




本文转自 dogegg250 51CTO博客,原文链接:http://blog.51cto.com/jianshusoft/660824,如需转载请自行联系原作者