`
zuiyanwangyue
  • 浏览: 164610 次
  • 性别: Icon_minigender_1
  • 来自: 河北
社区版块
存档分类
最新评论

Tomcat服务器下解决乱码的解决方案

阅读更多

项目中遇到一个情况,就是Tomcat下中文乱码的问题,最开始解决的时候用的是过滤器加修改%tomcat%\conf\server.xml的方式,以便应对Get和Post两种情况下提交表单都不会出现乱码,但是对于系统中使用的某些平台(诸如工作流引擎等),在将URIEncoding="GB2312"加入到server.xml中的Connector配置中之后就不能正常工作了。看来最好是不要改动服务器的配置才好,于是在自定义的过滤器中我分别对Post请求和Get请求做了不同的处理,如果是Post请求则直接调用request.setCharacterEncoding("GBK"),否则如果是Get请求的话需要对Request进行包装才可以解决乱码的问题。

如下是定制过滤器的完整源代码:

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

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.HttpServletRequestWrapper;

import org.apache.commons.lang.StringUtils;
/**
 * 此过滤器是为了解决Tomcat在处理Get和Post不同请求时的中文乱码问题而定制的
 * @author leisure
 */
public class TomcatCharsetEncodingFilter implements Filter{
	private String charsetEncoding="GBK";
	public void destroy() {
	}

	public void doFilter(ServletRequest request, ServletResponse response, 
			FilterChain chain) throws IOException, ServletException {
		HttpServletRequest httpRequest=(HttpServletRequest)request;
		String method=httpRequest.getMethod();
		if("POST".equalsIgnoreCase(method)){
			httpRequest.setCharacterEncoding(charsetEncoding);
		}else{
			httpRequest=new CharsetEncodingFixedRequest(httpRequest);
		}
		chain.doFilter(httpRequest, response);
	}

	public void init(FilterConfig config) throws ServletException {
		String charset=config.getInitParameter("charsetEncoding");
		if(StringUtils.isNotBlank(charset)){
			this.charsetEncoding=charset;
		}
	}
	class CharsetEncodingFixedRequest extends HttpServletRequestWrapper{
		private String fixedCharset="iso8859-1";
		private Map paramMap=new HashMap();
		public CharsetEncodingFixedRequest(HttpServletRequest request) {
			super(request);
			try {
				super.setCharacterEncoding(fixedCharset);
				Enumeration nameEnum=request.getParameterNames();
				while(nameEnum.hasMoreElements()){
					String paramName=(String)nameEnum.nextElement();
					String[] values=request.getParameterValues(paramName);
					if(values.length>0){
						List valueList=new ArrayList();
						for(int i=0;i<values.length;i++){
							String value=values[i];
							valueList.add(encode(request.getCharacterEncoding(),value));
						}
						paramMap.put(paramName, valueList.toArray(new String[valueList.size()]));
					}
				}
				System.out.println();
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}
		}
		
		public String getParameter(String name) {
			String[] values=getParameterValues(name);
			if(values!=null && values.length>0) return values[0];
			else return null;
		}
		
		public String[] getParameterValues(String name) {
			return (String[])paramMap.get(name);
		}
		
		public Map getParameterMap() {
			return this.paramMap;
		}

		public Enumeration getParameterNames() {
			final Iterator it=paramMap.keySet().iterator();
			return new Enumeration(){
				public boolean hasMoreElements() {
					return it.hasNext();
				}

				public Object nextElement() {
					return it.next();
				}
			};
		}

		//
		private String encode(String oldCharset,String src){
			if(StringUtils.isBlank(src)) return src;
			if(StringUtils.isBlank(oldCharset)){
				oldCharset=this.fixedCharset;
			}
			try {
				return new String(src.getBytes(oldCharset),charsetEncoding);
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
				return src;
			}
		}
	}
}

其中在自定义的请求包装类中对请求参数做了一个缓存处理,即后续对getParameter(String paramName)以及其它与请求参数有关的调用不会再对包装的请求进行调用,这主要是为了从根本上保证自定义的请求包装类CharsetEncodingFixedRequest能全权负责与请求参数相关的编码工作。否则在遇到需要对请求进行转发的情况(典型的是在struts的Action类中调用mapping.findForward(String forwardName))时要转发到的目标组件在获取请求参数时依旧会出现乱码,这主要是与tomcat在处理转发时需要对请求重新进行包装以及解包装有关系,如果对这一过程有特别的兴趣可以看看org.apache.catalina.core.ApplicationDispatcher的源码,就会明白此中奥妙了。

相比起修改服务器配置文件的方案来说,配置过滤器更加灵活,可以控制对某些URL进行过滤而对某些则不进行过滤,但是如果是修改了 %tomcat%\conf\server.xml的话,tomcat会对所有的请求都进行指定字符集的编码,这在某些情况下是非常有害的,毕竟ISO8859-1是国际的标准。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics