使用filter和装饰者解决get和post提交乱码问题(增强getParameter, getParameterValues, getParameterMap )

Posted yyhl

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用filter和装饰者解决get和post提交乱码问题(增强getParameter, getParameterValues, getParameterMap )相关的知识,希望对你有一定的参考价值。

2018-06-22

小白的学习总结:希望可以帮助大家,也希望自己可以变得更加美好.

测试代码:

package com.itheima.web.servlet;

import java.io.IOException;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


public class RegServlet extends HttpServlet {
    
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String username = request.getParameter("username");
        System.out.println(username);
        String[] hobbys = request.getParameterValues("hobby");
        for (String hobby : hobbys) {
            System.out.println(hobby);
        }
        //刚刚的方法只增强了getParameter方法,为增强getParameterValues方法
//        String[] values = request.getParameterValues("username");
//        System.out.println(values[0]);//张三,
//        下述方法包含getParameterValues和getParameter这两个方法
//        Map<String, String[]> map = request.getParameterMap();
//        String[] values = map.get("username");
//        System.out.println(values[0]);
        
    }

    
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

}
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
	<form action="${pageContext.request.contextPath }/regServlet" method="get">
		用户名:<input type="text" name="username"><br>
		爱好1:<input type="text" name="hobby"><br>
		爱好2:<input type="text" name="hobby"><br>
		<input type="submit" value="提交">
		
	</form>
</body>
</html>

 //过滤器和装饰者

 

package me.gacl.web.filter;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Enumeration;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

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;

/**
 * Servlet Filter implementation class EncodingFilter
 */
public class EncodingFilter implements Filter {
    public void destroy() {

    }

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        // 1.强转:是为了使其方法增多
        HttpServletRequest req = (HttpServletRequest) request;
        // 2.处理业务
        // req.setCharacterEncoding("UTF-8");//处理post提交方式乱码
        // 如下方法,虽然可以解决一个提交数据的编码问题,但是不具有通用性
        /*
         * String username = req.getParameter("username"); username = new
         * String(username.getBytes("ISO-8859-1"),"UTF-8");
         */
        // 装饰者:增强HttpServletRequest接口的getParameter(String name)方法
        MyRequest myReq=new MyRequest(req);
        // 3.放行
        chain.doFilter(myReq, response);
    }

    public void init(FilterConfig fConfig) throws ServletException {
        // TODO Auto-generated method stub
    }
}

// HttpServletRequest增强他的方法
// 装饰者
// 1.书写一个类实现被装饰类相同的接口,或者继承被装饰类的一个子类,选中一个类,ctrl+T查看一个类的继承关系
//实现HttpServletRequest,这个接口方法太多了,
// 翻译:要增强某个接口的方法,实现这个接口,或者继承这个接口的的实现类
class MyRequest extends HttpServletRequestWrapper {
    //public class HttpServletRequestWrapper extends ServletRequestWrapper implements HttpServletRequest
   
    //2.在类中声明一个被包装类类型的变量
    private HttpServletRequest oldRequest;
    //3.编写一个构造方法,给被包装类类型的变量赋值
    public MyRequest(HttpServletRequest request) {
        //调用父类的有参构造
        super(request);
        this.oldRequest=request;
    }
    //4.对于不需要修改的方法,调用被包装类原来的方法
    //5.对于需要修改的方法,编写自己的代码
    /*@Override
    public String getParameter(String name) {
        //name,是uesrname,也是hobby,借助原来的类的方法,获取乱码的张三
        //使用原来的API方法获取请求参数
        String username = oldRequest.getParameter(name);//username,就是乱码的张三
        try {
            username=new String(username.getBytes("ISO-8859-1"), "UTF-8");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return username;
    }*/
    /*@Override
    //xxx 使用xxx,代替uesrname或者hobby或者其他的
    public String getParameter(String xxx) {
        //name,是uesrname,也是hobby,借助原来的类的方法,获取乱码的张三
        //使用原来的API方法获取请求参数,以二进制也可以解决post提交方式乱码
        String XXX = oldRequest.getParameter(xxx);//username,就是乱码的张三
        try {
            XXX=new String(XXX.getBytes("ISO-8859-1"), "UTF-8");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return XXX;
    }*/
    //增强getParameterMap方法
    /**
     * 为何做个标记boolean flag=false;
     * request里边有个全局map.第一次从页面取值存到map里,这时map里是utf-8编码的
     * 第二次就不会从页面取值了,而是从直接从map里取值
     * utf-8->ISO-8859-1->utf-8,这样必然会乱码
     * boolean flag=false,作用就是map只存一次
     */
     boolean flag=false;
    @Override
    public Map<String, String[]> getParameterMap() {
        
        Map<String, String[]> map = oldRequest.getParameterMap();
        try {
            if(!flag){
                Set<Entry<String, String[]>> entrySet = map.entrySet();
                for (Entry<String, String[]> entry : entrySet) {
                    //key不可能乱码,只需解决value的乱码
                    String[] values = entry.getValue();
                    for (int i = 0; i < values.length; i++) {
                        values[i]=new String(values[i].getBytes("ISO-8859-1"),"UTF-8");
                    }
                }
                flag=true;
            }
            
        } catch (Exception e) {
            e.printStackTrace();
        }
        return map;//操作的是引用地址,不用放回
    }
    
    @Override
    //一个name对应多个值
    public String[] getParameterValues(String name) {
        //调用上边的getParameterMap方法
        Map<String, String[]> map = getParameterMap();
        return map.get(name);
    }
    @Override
    //一个name对应一个值
    public String getParameter(String name) {
        Map<String, String[]> map = getParameterMap();
        String[] values = map.get(name);
        return values==null?null:values[0];
    }
    
    
}

 

以上是关于使用filter和装饰者解决get和post提交乱码问题(增强getParameter, getParameterValues, getParameterMap )的主要内容,如果未能解决你的问题,请参考以下文章

javaWeb_全站编码

实现全局同一编码:Filter

使用filter对请求设置编码

Servlet:Requset/Response Encoding and Filter

使用动态代理解决全局乱码

get 乱码解决方案