中国的程序猿在编程过程中免不了要解决乱码问题,针对不同的提交方式有不同的解决方式。这两天刚好在学这个知识点,在此做一个简单的小结。
首先要明白乱码出现的原因:
乱码出现的根本原因是http协议不支持中文在网络中进行传输,所以前端在提交数据的时候会做一个封装。由于get/post请求的传输机制不一样,所以针对乱码的解决也不一样。
get请求:
get请求提交的数据直接跟在url后面,浏览器会对其中的中文进行编码。一般常见编码方式为utf-8,当我们的服务端接收到数据的时候会自动对此进行解码。以tomcat为例其默认解码的方式是iso8850-1,这样中文字符经过utf-8的编码-ISO8859-1解码,编解码的码表不一致,就会出现乱码。针对这种问题一般有两种解决方法。
第一种修改配置文件
更改tomcat的配置文件,这种方式理论上可行但实际开发很少用。
第二种手动解码
Map<String, String[]> map = request.getParameterMap();
for (String key : map.keySet()) {
String[] values = map.get(key);
// 判断取出字符数组是否为空
if (values != null && values.length != 0) {
// 遍历字符数组进行编码解码
for (int i = 0; i < values.length; i++) {
try {
// 合理利用getByte和new String()的功能
values[i] =
//先编码再解码!!!
new String( values[i].getBytes("iso8859-1"),"utf-8");
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
post请求
post请求提交的数据实在请求体里面,sun公司给我们提供了一个api;
可以直接设计请求体的编码格式。
//可以直接设计post请求的请求体编码为utf-8
request.setCharacterEncoding("utf-8");
以上两种方法虽然可以解决问题但是当提交的数据比较多是,这样解码也是不可行的,所以实际开发中我们需要利用filter过滤器进行设置。编码的根本原因是request对象在起作用,所以我们需要重写request对象的相关方法,这种方式叫做包装。
第一步:自定义一个类继承包装类HttpServletRequestWrapper,如果直接实现ServletRequest接口需要重写太多的抽象方法,所以sun公司提供了一个包装类给程序猿使用.
class MyRequest extends HttpServletRequestWrapper {
private HttpServletRequest request;//原生态的request,需要在此基础上封装!!
private boolean flag = true;// 定义一个开关标记
public MyRequest(HttpServletRequest request) {
super(request);//传递过来request给了父类
// TODO Auto-generated constructor stub
this.request = request;
}
}
第二步:根据实际的获得请求参数的三个api,
getParameter(String name);
getParameterValues(String name);
Map getParameterMap();
分析这三个api发现,只要重写getParameterMap(),其他的都可以从这个转换结果中获得。
// 找接口 中间类 Wrapper 包装类 加强 paramter 默认iso-8859-1 继//承 HttpServletRequestWrapper 加强 getParameterXX sun 公司 设计类
class MyRequest extends HttpServletRequestWrapper {
private HttpServletRequest request;// 获取 为加强 request 对象
private boolean flag = false;
public MyRequest(HttpServletRequest request) {
super(request);
// TODO Auto-generated constructor stub
this.request = request;
}
@Override
public String getParameter(String name) {
// 首先获取请求方式 ... key 表单 input name 对应属性值 value 表单用户提交信息数据 String[]
Map<String, String[]> map = getParameterMap();
if (map != null && map.size() != 0) {
String[] values = map.get(name);
if (values != null && values.length != 0) {
return values[0];
}
}
return super.getParameter(name);
}
@Override
public String[] getParameterValues(String name) {
Map<String, String[]> map = getParameterMap();
if (map != null && map.size() != 0) {
String[] values = map.get(name);
if (values != null && values.length != 0) {
return values;
}
}
return super.getParameterValues(name);
}
@Override
public Map getParameterMap() {
// get/post
String method = request.getMethod();
if ("post".equalsIgnoreCase(method)) {
try {
request.setCharacterEncoding("utf-8");
return request.getParameterMap();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
// 后续代码调用 getParameter getParameterValues 重复调用 getParameterMap
// 引入标记 开关 boolean 1--100 素数 双色球 6 1 1-33 6个红球 01 02 ...33 08
if ("get".equalsIgnoreCase(method)) {
if (!flag) {
// 必须要获取 map 遍历map 将 String[] 值获取 每一个数组元素都要 先编码后解码
Map<String, String[]> map = request.getParameterMap();// 原始request 获取数据 iso-88590-1解码
if (map != null && map.size() != 0) {
for (String key : map.keySet()) {
// 每一次循环 获取 map key
String[] values = map.get(key);
if (values != null && values.length != 0) {
// 先编码 后解码 forIn 简化查询
for (int i = 0; i < values.length; i++) {
try {
values[i] = new String(values[i].getBytes("iso-8859-1"), "utf-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
}
}
}
flag = true;
return map;
}
}
return super.getParameterMap();// 其他的请求
}
}
在dofilte()方法中的使用
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
// TODO Auto-generated method stub
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
// 过滤器业务方法编写 默认 拦截后续资源的访问的
// 重写getParameter 方法!
// 思想: 自己编写 HttpServletRequest接口实现类 覆盖getParameter 方法 自己定义解码 utf-8
MyRequest myrequest = new MyRequest(request);// 构造方法注入 对象
// perperties xml
response.setContentType("text/html;charset=utf-8");
// class MYRequest implements HttpServletRequest /{ getParamter getParameterValue getParam..Map}
// 自己定义request 具备 getParameter系统方法 重写 保留 request其他api 的使用
chain.doFilter(myrequest, response);// request response 传递下去 ... 将request response 对象传递后续 servlet /jsp
}