中文乱码问题一直是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异常,这个时候就会通过间接更改值的方式解决这个问题,下面将给出所谓的中文乱码解决方案的过滤器。
EncodeFilter.java
ParameterRequestFilterWrapper.java
注:这个过滤器可以用在写servlet项目的时候,配置完web.xml,然后将两个类添加到项目中,注意包名,然后你就可以很easy的解决中文乱码的post和get方式。
接下来我将具体通过一个项目来讲解servlet中MVC的进阶方式的编写实例,这个项目中当然会引进这个过滤器带来的好处,然而这个项目会有很多可以学习的东西和可以和我讨论的东西,我会继续秉着求知若饥,虚心若愚的心态完成我对技术人生的探讨。
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的进阶方式的编写实例,这个项目中当然会引进这个过滤器带来的好处,然而这个项目会有很多可以学习的东西和可以和我讨论的东西,我会继续秉着求知若饥,虚心若愚的心态完成我对技术人生的探讨。
在此恭祝大家学习愉快!