Scripts 学盟

标题: 关于 Tomcat 上的应用中使用 GET 方式提交参数的那些事 [打印本页]

作者: Alvin    时间: 2011-5-5 16:50:02     标题: 关于 Tomcat 上的应用中使用 GET 方式提交参数的那些事

我们都知道,在 Tomcat 默认的配置情况下, 使用 request.setCharacterEncoding 对于使用 GET 方式提交的参数是无效的。
这个问题可以说是困扰哦。。。
好多人好多时候,明明加了请求过滤器,给 request.setCharacterEncoding 设置上一千遍。。。
request.getParameter(...) 还是得到一堆看不懂的符号。
如何是好哇....




呵呵,偷偷告诉你,
可以打开 %TOMCAT_HOME%\conf\server.xml
在 HTTP 连接器的配置节点中,加入一个属性  URIEncoding="UTF-8"
<Connector port="80" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" URIEncoding="UTF-8" />
当然了。。。如果你的项目中不是应用 UTF-8 编码格式来传递请求数据的,就不要写上 "UTF-8" 啦。。。写 gbk, big5 .... 你懂的啦。
再看一下,是不是大功告破,问题解决了呢。




一般情况下,这么也就把问题给解决了哈。。。
但是有些人有时候,还是又郁闷了一把啊。。。他的 Tomcat 里要布署多个应用啊,有些是应用 UTF-8, 有些是 GBK, 还有些是韩文,日文,徳文,法文。。。什么什么文的一大堆啊
使用了各种不同的各地区语言专用编码啊。。。
写上 URIEncoding="UTF-8", GBK 项目挂了啊
写上 URIEncoding="GBK", UTF-8 项目挂了啊
。。。
伤得起么,伤得起么




呵呵,再偷偷告诉你,
再打开 %TOMCAT_HOME%\conf\server.xml
在 HTTP 连接器的配置节点中,不写 URIEncoding="xxx" 了啊,写 useBodyEncodingForURI="true" 啊
<Connector port="80" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" useBodyEncodingForURI="true" />
马上测试一下哈。。。
request.setCharacterEncoding(xxx) 是不是对 GET 方式提交的参数也起作用了哈




对于,绝大部分的人来说,这是非常不错的解决办法了呀
可是,还有那么很小一部分人 ,还是在郁闷呐。。。
他购买了虚拟主机啊,服务器不是自个完全控制啊。。。 tomcat 的配置没法改啊。。。
什么 URIEncoding...
什么 useBodyEncodingForURI...
都是浮云啊

这没法活了呀。。。



难道回去修改代码,把所有接收 GET 提交的参数的地方都加上
parameterValue = new String(parameterValue.getBytes("iso-8859-1"), xxxx);
唉。。。改吧。。。




呵呵,最后再偷偷告诉你
这里有个过滤器,用下面的过滤器过滤请求
不配置 URIEncoding, useBodyEncodingForURI 都可以修正 request.setCharacterEncoding(...) 对 GET 方式提交的参数无效的问题
过滤器代码如下:
  1. package org.iscripts.common.web;

  2. import java.io.*;
  3. import java.util.*;

  4. import javax.servlet.*;
  5. import javax.servlet.http.*;

  6. /**
  7. * @author 林俊海(ialvin.cn) 广东·普宁·里湖
  8. */
  9. public class FixedEncodingForURI implements Filter {

  10.   public void doFilter(ServletRequest req, ServletResponse response,
  11.       FilterChain chain) throws IOException, ServletException {
  12.     HttpServletRequest request = (HttpServletRequest)req;
  13.     request = new RequestWrapper(request);
  14.     chain.doFilter( request, response );
  15.   }

  16.   public void destroy() { }
  17.   public void init(FilterConfig filterConfig) throws ServletException { }
  18. }

  19. class RequestWrapper extends HttpServletRequestWrapper {
  20.   private String characterEncoding = null;
  21.   private Map<String, String[]> parameterMap = null;

  22.   public RequestWrapper(HttpServletRequest request) {
  23.     super(request);
  24.     this.characterEncoding = request.getCharacterEncoding();
  25.   }

  26.   @Override
  27.   public String getParameter(String name) {
  28.     String[] values = this.getParameterValues(name);
  29.     if (values.length < 1) return "";
  30.     return values[0];
  31.   }

  32.   @Override
  33.   public String[] getParameterValues(String name) {
  34.     String[] values = this.getParameterMap().get(name);
  35.     return values == null ? new String[0] : values;
  36.   }
  37.   
  38.   @Override
  39.   public Enumeration<String> getParameterNames() {
  40.     return new Enumeration_<String>( this.getParameterMap().keySet().iterator() );
  41.   }

  42.   @Override
  43.   @SuppressWarnings("unchecked")
  44.   public Map<String, String[]> getParameterMap() {
  45.     if (parameterMap != null) return parameterMap;
  46.     parameterMap = new HashMap<String, String[]>();
  47.     try {
  48.       super.setCharacterEncoding("iso-8859-1");
  49.       Map<String, String[]> map = super.getParameterMap();
  50.       super.setCharacterEncoding(characterEncoding);
  51.       if (map == null) return parameterMap;
  52.       for (String key : map.keySet()) {
  53.         String[] values = map.get(key);
  54.         key = RequestWrapper.reDecode(key, this.getCharacterEncoding());
  55.         values = RequestWrapper.reDecode(values, this.getCharacterEncoding());
  56.         parameterMap.put(key, values);
  57.       }
  58.     } catch (UnsupportedEncodingException e) {
  59.       throw new RuntimeException(e);
  60.     }
  61.     return parameterMap;
  62.   }

  63.   @Override
  64.   public String getCharacterEncoding() {
  65.     return characterEncoding;
  66.   }

  67.   @Override
  68.   public void setCharacterEncoding(String characterEncoding) {
  69.     this.characterEncoding = characterEncoding;
  70.   }

  71.   // ---------- private ----------
  72.   private static String[] reDecode(String[] strs, String charset) {
  73.     if (strs == null) return new String[0];
  74.     String[] values = new String[strs.length];
  75.     for (int i=0, length=strs.length; i<length; i++)
  76.       values[i] = RequestWrapper.reDecode(strs[i], charset);
  77.     return values;
  78.   }

  79.   private static String reDecode(String str, String charset) {
  80.     if (str == null) return "";
  81.     if ("iso-8859-1".equalsIgnoreCase(charset)) return str;
  82.     try {
  83.       return new String(str.getBytes("iso-8859-1"), charset);
  84.     } catch (UnsupportedEncodingException e) {
  85.       throw new RuntimeException(e);
  86.     }
  87.   }
  88. }

  89. class Enumeration_<E> implements Enumeration<E> {
  90.   private Iterator<E> iterator = null;
  91.   Enumeration_(Iterator<E> iterator) {
  92.     this.iterator = iterator;
  93.   }
  94.   
  95.   public boolean hasMoreElements() {
  96.     return iterator.hasNext();
  97.   }

  98.   public E nextElement() {
  99.     return iterator.next();
  100.   }
  101. }
复制代码
原理很简单,request 来到这个过滤器中,会被包装了一下
request.getParameter
request.getParameterValues
request.getParameterNames
request.getParameterMap
这四个方法会被重写。  所以后面就.... 大家懂的啦.

不过,注意哦,使用这个过滤器后仍然需要 request.setCharacterEncoding
也就是说,它只是修正在 tomcat 服务中 request.setCharacterEncoding 对 GET 方式提交的参数无效的问题.
如果你使用另一个过滤器 B 来完成 request.setCharacterEncoding 的工作,那么这个过滤器在过滤器链的次序中,必须在 B 的前面。


---------------------------
哈哈,这下可以了吧,如果你能配置 tomcat , 那么,你可以配置下 useBodyEncodingForURI="true"

如果你没有权限去配置 tomcat,那么,在应用中加上这个过滤器

当然,为了增加应用发布后的兼容性,并且降低配置来配置去的麻烦,可以统一就加上这个过滤器,哈哈。。。。

--------------------------
附:这里还有个视频,关于提交参数的编码问题
http://www.iscripts.org/bbs/viewthread.php?tid=98
作者: Yisin    时间: 2011-5-7 21:17:42

不会Java
作者: 那个谁    时间: 2011-5-12 16:36:08

表示什么乱码都是浮云的。路过。。。
作者: Alvin    时间: 2011-5-15 04:35:41


浮云




欢迎光临 Scripts 学盟 (http://www.iscripts.org/) Powered by Discuz! X2