Servlet中文乱码解决方案详解

本文提供了一种通过自定义过滤器解决Servlet项目中POST和GET请求中文乱码问题的方法,并附带了完整的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

    中文乱码问题一直是web开发中让人头痛的问题,但是好在掌握原理后,解决的方案很简单,一般情况下发生在servlet开发中无外乎request和response乱码问题,下面是一个讲的比较好的博文链接,在此可以解决你可能遇到的几乎全部的问题。
        http://blog.csdn.net/xiazdong/article/details/7217022
    当然还可以通过过滤器的方式解决中文乱码的问题,然而仅仅是servlet的开发,不会使用到其他的框架,也就不会用到诸如Struts2和Spring中能够解决乱码的过滤器。这个时候就需要手写。以下的过程将会给出一个比较好用的过滤器解决方案,而且分为post方式和get方式的不同解决思路。
    对于post中文乱码解决会相对容易一些,对于get方式,由于通过request获取参数值进行修改,不好将修改后的值放到原来的参数中,这个时候就要借助javax.servlet.http.HttpServletRequestWrapper这个类进行间接修改。
    本文将通过Servlet规范中所引入的filter,因为其拦截模式能在request到达servlet的服务方法之前拦截HttpServletRequest对象,而在服务方法转移控制后又能拦截HttpServletResponse对象。你可以使用filter来实现特定的任务,比如验证用户输入,中文乱码解决,以及压缩web内容。但有时候HttpServletRequest对象的参数不能直接更改,因为java.util.Map所包装的HttpServletRequest对象的参数是不可改变的,强行更改就会报java.lang.IllegalStateException: No modifications are allowed to a locked ParameterMap异常,这个时候就会通过间接更改值的方式解决这个问题,下面将给出所谓的中文乱码解决方案的过滤器。

    首先要在web.xml(java web项目中的配置文件)中一贯的配置过滤器,比如可以通过以下方式进行:

web.xml(仅仅是过滤器的配置)

<!-- 配置字符过滤器 -->
	<filter>
		<filter-name>encodeFilter</filter-name>
		<filter-class>com.steven.util.EncodeFilter</filter-class>
	</filter>
	<!-- 配置字符过滤器的URL映射 -->
	<filter-mapping>
		<filter-name>encodeFilter</filter-name>
		<url-pattern>*</url-pattern>
	</filter-mapping>
加入以上配置后(在web.xml中遵循先进行过滤器的配置,然后再是servlet的配置),就需要通过一个过滤器EncodeFilter.java来完成,下面给出代码,
EncodeFilter.java

package com.steven.util;

import java.io.IOException;
import java.util.Enumeration;
import java.util.HashMap;
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;

/**
 * 主要实现数据编码的过程,分为post和get的request编码
 * 
 * @author Steven
 * 
 */
public class EncodeFilter implements Filter {

	@Override
	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		// 拆箱获取请求对象
		HttpServletRequest req = (HttpServletRequest) request;
		// 获取请求的方式
		String method = req.getMethod();
		// 判断请求的方式
		if (method.equals("POST")) {
			req.setCharacterEncoding("utf-8");
			// 继续访问
			chain.doFilter(req, response);
		} else {
			Map map = new HashMap();
			// 如果是GET请求
			// 获取请求对象的所有参数的键的集合
			Enumeration<String> names = req.getParameterNames();
			// 遍历键的集合
			while (names.hasMoreElements()) {
				// 根据键获取请求中的每个参数的值
				String key = names.nextElement();
				String[] values = req.getParameterValues(key);
				// 将每个参数的值进行字符串重构
				for (int i = 0; i < values.length; i++) {
					values[i] = new String(values[i].getBytes("iso-8859-1"),
							"utf-8");
					// 将进行重新编码后的数据放到map中
					map.put(key, values[i]);
				}

			}
			// 此步骤是通过包装类进行对req.getParameterMap() map中的数据间接设置
			ParameterRequestFilterWrapper reqWrapper = new ParameterRequestFilterWrapper(
					req, map);
			// 继续执行过滤器
			chain.doFilter(reqWrapper, response);
		}
	}

	@Override
	public void init(FilterConfig arg0) throws ServletException {
		// TODO Auto-generated method stub

	}

	@Override
	public void destroy() {
		// TODO Auto-generated method stub

	}
}
     当然在处理get方式的中文乱码时候,要用到前面所述的包装类,这个包装类继承自HttpServletRequestWrapper,然后复写了其中的相应方法,然后就可以完成request中get方式的乱码解决方案。下面给出ParameterRequestFilterWrapper.java的代码,
ParameterRequestFilterWrapper.java

package com.steven.util;

import java.util.Enumeration;
import java.util.Map;
import java.util.Vector;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

/**
 * 这个类主要用来修改req.getParameterMap()中上锁的数据,直接通过req.getParameterMap().put(key,value)
 * 会报异常 java.lang.IllegalStateException: No modifications are allowed to a
 * locked ParameterMap, 所以通过这种方式间接修改数据
 * 
 * @author Steven
 * 
 */
// 为了让编译器不报警告
@SuppressWarnings("unchecked")
public class ParameterRequestFilterWrapper extends HttpServletRequestWrapper {
	// 接收传过来的新的参数
	private Map params;

	/**
	 * 必须的构造
	 * 
	 * @param request
	 */
	public ParameterRequestFilterWrapper(HttpServletRequest request) {
		super(request);
	}

	/**
	 * 用来进行间接修改传入的map中key所对应的value的构造
	 * 
	 * @param request
	 * @param newParames
	 */
	public ParameterRequestFilterWrapper(HttpServletRequest request,
			Map newParames) {
		this(request);
		this.params = newParames;
	}

	/**
	 * 复写获取key的方法
	 */
	@Override
	public Enumeration getParameterNames() {
		Vector names = new Vector(params.keySet());
		return names.elements();
	}

	/**
	 * 复写获取多值values的方法
	 */
	@Override
	public String[] getParameterValues(String name) {
		Object v = params.get(name);
		if (v == null) {
			return null;
		} else if (v instanceof String[]) {
			return (String[]) v;
		} else if (v instanceof String) {
			return new String[] { (String) v };
		} else {
			return new String[] { v.toString() };
		}
	}

	/**
	 * 复写获取值value的方法
	 */
	@Override
	public String getParameter(String name) {
		Object v = params.get(name);
		if (v == null) {
			return null;
		} else if (v instanceof String[]) {
			String[] strArr = (String[]) v;
			if (strArr.length > 0) {
				return strArr[0];
			} else {
				return null;
			}
		} else if (v instanceof String) {
			return (String) v;
		} else {
			return v.toString();
		}
	}

}
这个时候过滤器的已经实现。

    注:这个过滤器可以用在写servlet项目的时候,配置完web.xml,然后将两个类添加到项目中,注意包名,然后你就可以很easy的解决中文乱码的post和get方式。
    接下来我将具体通过一个项目来讲解servlet中MVC的进阶方式的编写实例,这个项目中当然会引进这个过滤器带来的好处,然而这个项目会有很多可以学习的东西和可以和我讨论的东西,我会继续秉着求知若饥,虚心若愚的心态完成我对技术人生的探讨。


    在此恭祝大家学习愉快!



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值