关于Filter解决全网乱码问题的总结 --- 包装类 编解码 过滤器

中国的程序猿在编程过程中免不了要解决乱码问题,针对不同的提交方式有不同的解决方式。这两天刚好在学这个知识点,在此做一个简单的小结。

首先要明白乱码出现的原因:

乱码出现的根本原因是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

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值