使用过滤器Filter解决Java系统中中文乱码的问题

在JavaWeb系统的开发过程中,中文乱码是很头疼的问题,如何解决中文乱码成了一个很棘手的问题。

其实解决中文乱码问题的核心思想还是编码的转换,即把字符串从一种编码方式转换成另一种编码方式,如:把字符串从ISO-8859-1这种编码转换成UTF-8。

对于这种实现,我们经常地做法如下:

String value = "2121fafsdfsdfsdfsd中文";
value = new String(value.getBytes("iso8859-1"),"UTF-8");

这种解决方案如果要是在每个java类中去操作的话会很烦人的,万一需要变一种编码方式(当然这种情况极少出现,几乎不可能)的话,需要修改的地方太多,不便于后期的维护。要是能够采用一种统一的解决方案来解决这个问题的话,将会起到事半功倍的效果。

那么,我们该如何实现统一的解决方案呢?这时,过滤器就派上用场了。

思路就是我们可以做一个过滤器,对所有的请求进行统一的编码转换。实现方式如下:

方式一:使用包装类的形式解决

首先编写过滤器:

package com.ygp.filter;

import java.io.IOException;

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.HttpServletResponse;

import org.apache.log4j.Logger;

/**
 * @function:设置系统统一的编码方式为UTF-8,解决中文乱码问题
 * @author yankunpeng
 * @date 2015-1-27下午03:19:29
 * @mailto [email protected]
 */
public class MyEncodingFilter implements Filter {
    private static final Logger log = Logger.getLogger(MyEncodingFilter.class);
    private String encoding;
    private FilterConfig filterConfig;

    public void setEncoding(String encoding) {
        this.encoding = encoding;
    }

    public void doFilter(ServletRequest req, ServletResponse rsp,
            FilterChain chain) throws IOException, ServletException {
        log.info("进入" + log.getName() + "的doFilter方法");
        log.info("开始执行过滤器MyEncodingFilter.............");
        log.info("encoding:" + encoding);
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) rsp;

        // 解决post中文乱码问题
        request.setCharacterEncoding(encoding);
        response.setCharacterEncoding(encoding);
        response.setContentType("text/html;charset=" + encoding);

        // 解决GET中文乱码问题
        MyHttpServletRequestWrapper myRequest = new MyHttpServletRequestWrapper(
                request);
        // 传递给目标servlet或jsp的实际上时包装器对象的引用,而不是原始的HttpServletRequest对象
        chain.doFilter(myRequest, response);

        log.info("离开" + log.getName() + "的doFilter方法");
    }

    public void init(FilterConfig filterConfig) throws ServletException {
        log.info("进入" + log.getName() + "的init方法");
        log.info("开始初始化过滤器MyEncodingFilter.............");
        this.filterConfig = filterConfig;
        String encoding = filterConfig.getServletContext().getInitParameter(
                "encoding");
        if (encoding != null && encoding.trim().length() != 0) {
            this.encoding = encoding;
        }

        log.info("encoding:" + encoding);
        log.info("离开" + log.getName() + "的init方法");
    }

    public void destroy() {
        log.info("进入" + log.getName() + "的destroy方法");
        log.info("开始销毁过滤器MyEncodingFilter.............");
        System.out.println(filterConfig.getFilterName() + "被销毁");
        encoding = null;
        filterConfig = null;
        log.info("离开" + log.getName() + "的destroy方法");
    }
}

实现我们的包装类:

package com.ygp.filter;

import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;

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

import org.apache.log4j.Logger;

/**
 * @function:设置系统统一的编码方式为UTF-8,解决中文乱码问题
 * @author yankunpeng
 * @date 2015-1-27下午03:19:29
 * @mailto [email protected]
 */
public class MyHttpServletRequestWrapper extends HttpServletRequestWrapper {
    private static final Logger log = Logger
            .getLogger(MyHttpServletRequestWrapper.class);

    private String encoding = "UTF-8";
    private HttpServletRequest request;

    public MyHttpServletRequestWrapper(HttpServletRequest request) {
        super(request);
        this.request = request;
    }

    /**
     * 获得被装饰对象的引用和采用的字符编码
     * 
     * @param request
     * @param encoding
     */
    public MyHttpServletRequestWrapper(HttpServletRequest request,
            String encoding) {
        super(request);
        this.encoding = encoding;
        this.request = request;
    }

    /**
     * 实际上就是调用被包装的请求对象的getParameter方法获得参数,然后再进行编码转换
     */
    public String getParameter(String name) {
        String value = this.request.getParameter(name);
        value = ((value == null) ? null : convert(value));
        return value;
    }

    public String convert(String parameter) {
        log.info("编码转换之前:" + parameter);
        String value = "";
        try {
            if (this.request.getMethod().equalsIgnoreCase("GET")) {
                value = new String(parameter.trim().getBytes("ISO-8859-1"),
                        encoding);
            } else {
                value = parameter;
            }
        } catch (UnsupportedEncodingException e) {
            log.info(e);
        }

        return value;
    }

    @Override
    public String[] getParameterValues(String name) {
        String[] values = this.request.getParameterValues(name);
        String[] newValues = new String[values.length];
        // 判断是否是GET
        if (request.getMethod().equalsIgnoreCase("GET")) {
            for (int i = 0; i < values.length; i++) {
                try {
                    if (values[i] != null) {
                        newValues[i] = new String(values[i].getBytes(), request
                                .getCharacterEncoding());
                    } else {
                        newValues[i] = null;
                    }
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
            }
            return newValues;
        } else {
            return values;
        }
    }

    // 重构方法
    @SuppressWarnings("unchecked")
    @Override
    /**
     * 此方法是struts2的模型驱动需要使用的方法,所以需要重写
     */
    public Map getParameterMap() {
        try {
            if (!this.request.getMethod().equals("GET")) {// 判断是否是get请求方式
                return this.request.getParameterMap();
            }

            Map map = this.request.getParameterMap(); // 接受客户端的数据
            Map newmap = new HashMap();
            for (Map.Entry entry : map.entrySet()) {
                String name = entry.getKey();
                String values[] = entry.getValue();

                if (values == null) {
                    newmap.put(name, new String[] {});
                    continue;
                }
                String newvalues[] = new String[values.length];
                for (int i = 0; i < values.length; i++) {
                    String value = values[i];
                    value = new String(value.getBytes("iso8859-1"),
                            this.request.getCharacterEncoding());
                    newvalues[i] = value; // 解决乱码后封装到Map中
                }

                newmap.put(name, newvalues);
            }

            return newmap;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

最后是我们的配置文件web.xml:


    <context-param>
        <description>全局编码 description>
        <param-name>encodingparam-name>
        <param-value>UTF-8param-value>
    context-param>
    
    <filter>
        <filter-name>myEncodingFilterfilter-name>
        <filter-class>com.ygp.filter.MyEncodingFilterfilter-class>
    filter>
    <filter-mapping>
        <filter-name>myEncodingFilterfilter-name>
        <url-pattern>/*url-pattern>
    filter-mapping>

方式二:使用动态代理的方式解决

首先使用动态代理实现我们的过滤器:

package com.ygp.filter;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
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;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;

public class CharacterEncodingFilter implements Filter {
    private static final Logger log = Logger
            .getLogger(CharacterEncodingFilter.class);
    private String encoding = "UTF-8";// 这里定义的事默认值,如果web.xml中没有配置,则取这个默认值,否则取配置的值
    private String old_encoding = "ISO-8859-1";
    private FilterConfig filterConfig;

    public void setEncoding(String encoding) {
        this.encoding = encoding;
    }

    public void doFilter(ServletRequest req, ServletResponse resp,
            FilterChain chain) throws IOException, ServletException {
        log.info("进入" + log.getName() + "的doFilter方法");
        log.info("开始执行过滤器CharacterEncodingFilter.............");
        log.info("encoding:" + encoding);
        final HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;

        // 解决post中文乱码问题
        request.setCharacterEncoding(encoding);
        response.setCharacterEncoding(encoding);
        response.setContentType("text/html;charset=" + encoding);

        // 解决get请求的中文乱码.放行将代理对象带过去,将会拦截对getParameter,getParameterValues,getParameterMap的访问,转正常了,再返回给浏览器
        chain.doFilter((ServletRequest) Proxy.newProxyInstance(this.getClass()
                .getClassLoader(), request.getClass().getInterfaces(),
                new InvocationHandler() {

                    @SuppressWarnings("unchecked")
                    public Object invoke(Object proxy, Method method,
                            Object[] args) throws Throwable {
                        String methodname = method.getName(); // 拿到当前的方法

                        if (methodname.equals("getParameter")) {
                            // 执行request.getParameter获取结果
                            String value = (String) method
                                    .invoke(request, args);
                            // 判断是否是GET
                            if (request.getMethod().equalsIgnoreCase("GET")) {
                                try {
                                    if (value != null) {
                                        value = new String(value
                                                .getBytes(old_encoding),
                                                request.getCharacterEncoding());// 转换编码返回
                                    }
                                } catch (UnsupportedEncodingException e) {
                                    e.printStackTrace();
                                }
                            }

                            return value;
                        }

                        if (methodname.equals("getParameterValues")) {
                            String[] values = (String[]) method.invoke(request,
                                    args); // 执行request.getParameterValues获取结果
                            String[] newValues = new String[values.length];
                            // 判断是否是GET
                            if (request.getMethod().equalsIgnoreCase("GET")) {
                                for (int i = 0; i < values.length; i++) {
                                    try {
                                        if (values[i] != null) {
                                            newValues[i] = new String(values[i]
                                                    .getBytes(), request
                                                    .getCharacterEncoding());
                                        } else {
                                            newValues[i] = null;
                                        }
                                    } catch (UnsupportedEncodingException e) {
                                        e.printStackTrace();
                                    }
                                }
                                return newValues;
                            } else {
                                return values;
                            }
                        }

                        if (methodname.equals("getParameterMap")) {
                            try {
                                // 执行request.getParameterMap获取结果
                                Map map = (Map) method
                                        .invoke(request, args);
                                Map newmap = new HashMap();

                                // 判断是否是GET
                                if (request.getMethod().equalsIgnoreCase("GET")) {
                                    for (Map.Entry entry : map
                                            .entrySet()) {
                                        String name = entry.getKey();
                                        String values[] = entry.getValue();

                                        if (values == null) {
                                            newmap.put(name, new String[] {});
                                            continue;
                                        }
                                        String newvalues[] = new String[values.length];
                                        for (int i = 0; i < values.length; i++) {
                                            String value = values[i];
                                            value = new String(
                                                    value
                                                            .getBytes(old_encoding),
                                                    request
                                                            .getCharacterEncoding());
                                            newvalues[i] = value; // 解决乱码后封装到Map中
                                        }

                                        newmap.put(name, newvalues);
                                    }

                                    return newmap;
                                } else {
                                    return map;
                                }
                            } catch (Exception e) {
                                throw new RuntimeException(e);
                            }
                        }

                        // 交给request执行请求
                        return method.invoke(request, args);
                    }
                }), response);

        log.info("离开" + log.getName() + "的doFilter方法");
    }

    public void init(FilterConfig filterConfig) throws ServletException {
        log.info("进入" + log.getName() + "的init方法");
        log.info("开始初始化过滤器CharacterEncodingFilter.............");
        this.filterConfig = filterConfig;
        String encoding = filterConfig.getServletContext().getInitParameter(
                "encoding");
        if (encoding != null && encoding.trim().length() != 0) {
            this.encoding = encoding;
        }

        log.info("encoding:" + encoding);
        log.info("离开" + log.getName() + "的init方法");
    }

    public void destroy() {
        log.info("进入" + log.getName() + "的destroy方法");
        log.info("开始销毁过滤器CharacterEncodingFilter.............");
        System.out.println(filterConfig.getFilterName() + "被销毁");
        encoding = "UTF-8";
        filterConfig = null;
        log.info("离开" + log.getName() + "的destroy方法");
    }
}

最后是配置文件web.xml配置:


    <context-param>
        <description>全局编码 description>
        <param-name>encodingparam-name>
        <param-value>UTF-8param-value>
    context-param>
    
    <filter>
        <filter-name>characterEncodingFilterfilter-name>
        <filter-class>com.ygp.filter.CharacterEncodingFilterfilter-class>
    filter>
    <filter-mapping>
        <filter-name>characterEncodingFilterfilter-name>
        <url-pattern>/*url-pattern>
    filter-mapping>

使用包装类和动态代理的方式均可以实现我们的功能。

你可能感兴趣的:(Java)