解决get方法传递URL参数中文乱码问题




应用一:解决tomcat下中文乱码问题(先来个简单的) 

在tomcat下,我们通常这样来解决中文乱码问题:

过滤器代码:


[java] view plain copy

print      ?                
1. package
2.     
3. import
4. import
5. import
6. import
7.     
8. public class ContentTypeFilter implements
9.     
10. private String charset = "UTF-8";    
11. private
12.         
13. public void
14. "被销毁");    
15. null;    
16. null;    
17.     }    
18.     
19. public void
20. throws
21. //设置请求响应字符编码  
22.         request.setCharacterEncoding(charset);    
23.         response.setCharacterEncoding(charset);    
24.             
25.         HttpServletRequest req = (HttpServletRequest)request;    
26.             
27.             
28. "----请求被"+config.getFilterName()+"过滤");    
29. //执行下一个过滤器(如果有的话,否则执行目标servlet)  
30.         chain.doFilter(req, response);    
31.             
32. "----响应被"+config.getFilterName()+"过滤");    
33.     
34.     }    
35.     
36. public void init(FilterConfig config) throws
37. this.config = config;    
38. "charset");      
39. if( charset != null && charset.trim().length() != 0)    
40.             {    
41. this.charset = charset;    
42.             }    
43.     }    
44.     
45. }


package filter;  
  
import java.io.*;  
import javax.servlet.*;  
import javax.servlet.http.*;  
import wrapper.GetHttpServletRequestWrapper;  
  
public class ContentTypeFilter implements Filter {  
  
    private String charset = "UTF-8";  
    private FilterConfig config;  
      
    public void destroy() {  
        System.out.println(config.getFilterName()+"被销毁");  
        charset = null;  
        config = null;  
    }  
  
    public void doFilter(ServletRequest request, ServletResponse response,  
            FilterChain chain) throws IOException, ServletException {  
        //设置请求响应字符编码  
        request.setCharacterEncoding(charset);  
        response.setCharacterEncoding(charset);  
          
        HttpServletRequest req = (HttpServletRequest)request;  
          
          
        System.out.println("----请求被"+config.getFilterName()+"过滤");  
        //执行下一个过滤器(如果有的话,否则执行目标servlet)  
        chain.doFilter(req, response);  
          
        System.out.println("----响应被"+config.getFilterName()+"过滤");  
  
    }  
  
    public void init(FilterConfig config) throws ServletException {  
            this.config = config;  
            String charset = config.getServletContext().getInitParameter("charset");    
            if( charset != null && charset.trim().length() != 0)  
            {  
                this.charset = charset;  
            }  
    }  
  
}

web.xml中过滤器配置:


[html] view plain copy

print      ?                
1. <!--将采用的字符编码配置成应用初始化参数而不是过滤器私有的初始化参数是因为在JSP和其他地方也可能需要使用-->
2. <context-param>
3. <param-name>charset</param-name>
4. <param-value>UTF-8</param-value>
5. </context-param>
6.     
7. <filter>
8. <filter-name>ContentTypeFilter</filter-name>
9. <filter-class>filter.ContentTypeFilter</filter-class>
10. </filter>
11.     
12. <filter-mapping>
13. <filter-name>ContentTypeFilter</filter-name>
14. <url-pattern>/*</url-pattern>
15. </filter-mapping>

<!--将采用的字符编码配置成应用初始化参数而不是过滤器私有的初始化参数是因为在JSP和其他地方也可能需要使用-->  
    <context-param>  
            <param-name>charset</param-name>  
            <param-value>UTF-8</param-value>  
    </context-param>  
  
    <filter>  
        <filter-name>ContentTypeFilter</filter-name>  
        <filter-class>filter.ContentTypeFilter</filter-class>  
    </filter>  
  
    <filter-mapping>  
        <filter-name>ContentTypeFilter</filter-name>  
        <url-pattern>/*</url-pattern>  
    </filter-mapping>

request.setCharacterEncoding(charset); 必须写在第一次使用request.getParameter()之前,这样才能保证参数是按照已经设置的字符编码来获取。
response.setCharacterEncoding(charset);必须写在PrintWriter out = request.getWriter()之前,这样才能保证out按照已经设置的字符编码来进行字符输出。

通过过滤器,我们可以保证在Servlet或JSP执行之前就设置好了请求和响应的字符编码。

但是这样并不能完全解决中文乱码问题:

对于post请求,无论是“获取参数环节”还是“输出环节"都是没问题的;

对于get请求,"输出环节"没有问题,但是"获取参数环节"依然出现中文乱码,所以在输出时直接将乱码输出了。

原因是post请求和get请求存放参数位置是不同的:

post方式参数存放在请求数据包的消息体中。get方式参数存放在请求数据包的请求行的URI字段中,以?开始以param=value&parame2=value2的形式附加在URI字段之后。而request.setCharacterEncoding(charset); 只对消息体中的数据起作用,对于URI字段中的参数不起作用,我们通常通过下面的代码来完成编码转换:


[java] view plain copy

print      ?                
1. String paramValue = request.getParameter("paramName");    
2. paramValue = new String(paramValue.trim().getBytes("ISO-8859-1"), charset);

String paramValue = request.getParameter("paramName");  
paramValue = new String(paramValue.trim().getBytes("ISO-8859-1"), charset);

但是每次进行这样的转换实在是很麻烦,有没有统一的解决方案呢?

解决方案1: 在tomcat_home\conf\server.xml 中的Connector元素中设置URIEncoding属性为合适的字符编码


[plain] view plain copy

print      ?                
1. <Connector port="8080" protocol="HTTP/1.1"     
2.            connectionTimeout="20000"     
3.            redirectPort="8443"     
4.            URIEncoding="UTF-8"    
5.  />

<Connector port="8080" protocol="HTTP/1.1"   
           connectionTimeout="20000"   
           redirectPort="8443"   
           URIEncoding="UTF-8"  
 />

这样做的缺点是,同一个tomcat下的其他应用也将受到影响。而其每次部署时都需要类修改配置也很麻烦。

解决方案2:自定义请求包装器包装请求,将字符编码转换的工作添加到getParameter()方法中


[java] view plain copy

print      ?                
1. package
2.     
3. import
4. import
5.     
6. import
7. import
8.     
9. public class GetHttpServletRequestWrapper extends
10.     
11. private String charset = "UTF-8";    
12.     
13. public
14. super(request);    
15.     }    
16.     
17. /** 
18.      * 获得被装饰对象的引用和采用的字符编码 
19.      * @param request 
20.      * @param charset 
21.      */
22. public
23.             String charset) {    
24. super(request);    
25. this.charset = charset;    
26.     }    
27.     
28. /** 
29.      * 实际上就是调用被包装的请求对象的getParameter方法获得参数,然后再进行编码转换 
30.      */
31. public
32. super.getParameter(name);    
33. null ? null
34. return
35.     }    
36.     
37. public
38. "编码转换之前:"
39. try
40. return new String(target.trim().getBytes("ISO-8859-1"), charset);    
41. catch
42. return
43.         }    
44.     }    
45.     
46. }    
   
package wrapper;  
  
import java.io.UnsupportedEncodingException;  
import java.net.URLDecoder;  
  
import javax.servlet.http.HttpServletRequest;  
import javax.servlet.http.HttpServletRequestWrapper;  
  
public class GetHttpServletRequestWrapper extends HttpServletRequestWrapper {  
  
    private String charset = "UTF-8";  
  
    public GetHttpServletRequestWrapper(HttpServletRequest request) {  
        super(request);  
    }  
  
    /** 
     * 获得被装饰对象的引用和采用的字符编码 
     * @param request 
     * @param charset 
     */  
    public GetHttpServletRequestWrapper(HttpServletRequest request,  
            String charset) {  
        super(request);  
        this.charset = charset;  
    }  
  
    /** 
     * 实际上就是调用被包装的请求对象的getParameter方法获得参数,然后再进行编码转换 
     */  
    public String getParameter(String name) {  
        String value = super.getParameter(name);  
        value = value == null ? null : convert(value);  
        return value;  
    }  
  
    public String convert(String target) {  
        System.out.println("编码转换之前:" + target);  
        try {  
            return new String(target.trim().getBytes("ISO-8859-1"), charset);  
        } catch (UnsupportedEncodingException e) {  
            return target;  
        }  
    }  
  
}
package wrapper;  
  
import java.io.UnsupportedEncodingException;  
import java.net.URLDecoder;  
  
import javax.servlet.http.HttpServletRequest;  
import javax.servlet.http.HttpServletRequestWrapper;  
  
public class GetHttpServletRequestWrapper extends HttpServletRequestWrapper {  
  
    private String charset = "UTF-8";  
  
    public GetHttpServletRequestWrapper(HttpServletRequest request) {  
        super(request);  
    }  
  
    /** 
     * 获得被装饰对象的引用和采用的字符编码 
     * @param request 
     * @param charset 
     */  
    public GetHttpServletRequestWrapper(HttpServletRequest request,  
            String charset) {  
        super(request);  
        this.charset = charset;  
    }  
  
    /** 
     * 实际上就是调用被包装的请求对象的getParameter方法获得参数,然后再进行编码转换 
     */  
    public String getParameter(String name) {  
        String value = super.getParameter(name);  
        value = value == null ? null : convert(value);  
        return value;  
    }  
  
    public String convert(String target) {  
        System.out.println("编码转换之前:" + target);  
        try {  
            return new String(target.trim().getBytes("ISO-8859-1"), charset);  
        } catch (UnsupportedEncodingException e) {  
            return target;  
        }  
    }  
  
}


修改过滤器的doFilter方法 代码如下:


[java] view plain copy

print      ?                
1. public void
2. throws
3. //设置请求响应字符编码  
4.         request.setCharacterEncoding(charset);    
5.         response.setCharacterEncoding(charset);    
6. //新增加的代码          
7.         HttpServletRequest req = (HttpServletRequest)request;    
8.             
9. if(req.getMethod().equalsIgnoreCase("get"))    
10.         {    
11. new
12.         }    
13.             
14. "----请求被"+config.getFilterName()+"过滤");    
15. //传递给目标servlet或jsp的实际上时包装器对象的引用,而不是原始的HttpServletRequest对象  
16.         chain.doFilter(req, response);    
17.             
18. "----响应被"+config.getFilterName()+"过滤");    
19.     
20.     }

public void doFilter(ServletRequest request, ServletResponse response,  
            FilterChain chain) throws IOException, ServletException {  
        //设置请求响应字符编码  
        request.setCharacterEncoding(charset);  
        response.setCharacterEncoding(charset);  
        //新增加的代码          
        HttpServletRequest req = (HttpServletRequest)request;  
          
        if(req.getMethod().equalsIgnoreCase("get"))  
        {  
            req = new GetHttpServletRequestWrapper(req,charset);  
        }  
          
        System.out.println("----请求被"+config.getFilterName()+"过滤");  
        //传递给目标servlet或jsp的实际上时包装器对象的引用,而不是原始的HttpServletRequest对象  
        chain.doFilter(req, response);  
          
        System.out.println("----响应被"+config.getFilterName()+"过滤");  
  
    }

这样一来,在servlet中调用包装器的getParameters方法来获取参数,就已经完成了字符编码的转换过程,我们就不需要在每次获取参数时来进行字符编码转换了。









0 0


  • 上一篇Java调用浏览器打开网页


我的同类文章


java(8) spring(2)


  • •Java调用浏览器打开网页2016-04-27阅读7
  • •JAVA BigDecimal 小数处理2016-04-26阅读16
  • •命令行打war包,剔除java源文件2016-04-09阅读17
  • •正则表达式符号解释2016-04-01阅读34
  • •spring事务配置五种方式2016-04-27阅读274
  • •mybatis中$和#区别2016-04-26阅读5
  • •Tomcat配置参数详解2016-04-03阅读40
  • •配置Log4j2016-03-25阅读37


来自:http://www.javaeye.com/topic/483158

应用一:解决tomcat下中文乱码问题(先来个简单的) 

在tomcat下,我们通常这样来解决中文乱码问题:

过滤器代码:


[java] view plain copy

print      ?                
1. package
2.     
3. import
4. import
5. import
6. import
7.     
8. public class ContentTypeFilter implements
9.     
10. private String charset = "UTF-8";    
11. private
12.         
13. public void
14. "被销毁");    
15. null;    
16. null;    
17.     }    
18.     
19. public void
20. throws
21. //设置请求响应字符编码  
22.         request.setCharacterEncoding(charset);    
23.         response.setCharacterEncoding(charset);    
24.             
25.         HttpServletRequest req = (HttpServletRequest)request;    
26.             
27.             
28. "----请求被"+config.getFilterName()+"过滤");    
29. //执行下一个过滤器(如果有的话,否则执行目标servlet)  
30.         chain.doFilter(req, response);    
31.             
32. "----响应被"+config.getFilterName()+"过滤");    
33.     
34.     }    
35.     
36. public void init(FilterConfig config) throws
37. this.config = config;    
38. "charset");      
39. if( charset != null && charset.trim().length() != 0)    
40.             {    
41. this.charset = charset;    
42.             }    
43.     }    
44.     
45. }

package filter;  
  
import java.io.*;  
import javax.servlet.*;  
import javax.servlet.http.*;  
import wrapper.GetHttpServletRequestWrapper;  
  
public class ContentTypeFilter implements Filter {  
  
    private String charset = "UTF-8";  
    private FilterConfig config;  
      
    public void destroy() {  
        System.out.println(config.getFilterName()+"被销毁");  
        charset = null;  
        config = null;  
    }  
  
    public void doFilter(ServletRequest request, ServletResponse response,  
            FilterChain chain) throws IOException, ServletException {  
        //设置请求响应字符编码  
        request.setCharacterEncoding(charset);  
        response.setCharacterEncoding(charset);  
          
        HttpServletRequest req = (HttpServletRequest)request;  
          
          
        System.out.println("----请求被"+config.getFilterName()+"过滤");  
        //执行下一个过滤器(如果有的话,否则执行目标servlet)  
        chain.doFilter(req, response);  
          
        System.out.println("----响应被"+config.getFilterName()+"过滤");  
  
    }  
  
    public void init(FilterConfig config) throws ServletException {  
            this.config = config;  
            String charset = config.getServletContext().getInitParameter("charset");    
            if( charset != null && charset.trim().length() != 0)  
            {  
                this.charset = charset;  
            }  
    }  
  
}

web.xml中过滤器配置:


[html] view plain copy

print ?

    1. <!--将采用的字符编码配置成应用初始化参数而不是过滤器私有的初始化参数是因为在JSP和其他地方也可能需要使用-->
    2. <context-param>
    3. <param-name>charset</param-name>
    4. <param-value>UTF-8</param-value>
    5. </context-param>
    6.     
    7. <filter>
    8. <filter-name>ContentTypeFilter</filter-name>
    9. <filter-class>filter.ContentTypeFilter</filter-class>
    10. </filter>
    11.     
    12. <filter-mapping>
    13. <filter-name>ContentTypeFilter</filter-name>
    14. <url-pattern>/*</url-pattern>
    15. </filter-mapping>


    <!--将采用的字符编码配置成应用初始化参数而不是过滤器私有的初始化参数是因为在JSP和其他地方也可能需要使用-->  
        <context-param>  
                <param-name>charset</param-name>  
                <param-value>UTF-8</param-value>  
        </context-param>  
      
        <filter>  
            <filter-name>ContentTypeFilter</filter-name>  
            <filter-class>filter.ContentTypeFilter</filter-class>  
        </filter>  
      
        <filter-mapping>  
            <filter-name>ContentTypeFilter</filter-name>  
            <url-pattern>/*</url-pattern>  
        </filter-mapping>

    request.setCharacterEncoding(charset); 必须写在第一次使用request.getParameter()之前,这样才能保证参数是按照已经设置的字符编码来获取。
    response.setCharacterEncoding(charset);必须写在PrintWriter out = request.getWriter()之前,这样才能保证out按照已经设置的字符编码来进行字符输出。

    通过过滤器,我们可以保证在Servlet或JSP执行之前就设置好了请求和响应的字符编码。

    但是这样并不能完全解决中文乱码问题:

    对于post请求,无论是“获取参数环节”还是“输出环节"都是没问题的;

    对于get请求,"输出环节"没有问题,但是"获取参数环节"依然出现中文乱码,所以在输出时直接将乱码输出了。

    原因是post请求和get请求存放参数位置是不同的:

    post方式参数存放在请求数据包的消息体中。get方式参数存放在请求数据包的请求行的URI字段中,以?开始以param=value&parame2=value2的形式附加在URI字段之后。而request.setCharacterEncoding(charset); 只对消息体中的数据起作用,对于URI字段中的参数不起作用,我们通常通过下面的代码来完成编码转换:


    [java] view plain copy

    print      ?                
    1. String paramValue = request.getParameter("paramName");    
    2. paramValue = new String(paramValue.trim().getBytes("ISO-8859-1"), charset);

    String paramValue = request.getParameter("paramName");  
    paramValue = new String(paramValue.trim().getBytes("ISO-8859-1"), charset);

    但是每次进行这样的转换实在是很麻烦,有没有统一的解决方案呢?

    解决方案1: 在tomcat_home\conf\server.xml 中的Connector元素中设置URIEncoding属性为合适的字符编码


    [plain] view plain copy

    print      ?                
    1. <Connector port="8080" protocol="HTTP/1.1"     
    2.            connectionTimeout="20000"     
    3.            redirectPort="8443"     
    4.            URIEncoding="UTF-8"    
    5.  />


    <Connector port="8080" protocol="HTTP/1.1"   
               connectionTimeout="20000"   
               redirectPort="8443"   
               URIEncoding="UTF-8"  
     />

    这样做的缺点是,同一个tomcat下的其他应用也将受到影响。而其每次部署时都需要类修改配置也很麻烦。

    解决方案2:自定义请求包装器包装请求,将字符编码转换的工作添加到getParameter()方法中


    [java] view plain copy

    print      ?                
    1. package
    2.     
    3. import
    4. import
    5.     
    6. import
    7. import
    8.     
    9. public class GetHttpServletRequestWrapper extends
    10.     
    11. private String charset = "UTF-8";    
    12.     
    13. public
    14. super(request);    
    15.     }    
    16.     
    17. /** 
    18.      * 获得被装饰对象的引用和采用的字符编码 
    19.      * @param request 
    20.      * @param charset 
    21.      */
    22. public
    23.             String charset) {    
    24. super(request);    
    25. this.charset = charset;    
    26.     }    
    27.     
    28. /** 
    29.      * 实际上就是调用被包装的请求对象的getParameter方法获得参数,然后再进行编码转换 
    30.      */
    31. public
    32. super.getParameter(name);    
    33. null ? null
    34. return
    35.     }    
    36.     
    37. public
    38. "编码转换之前:"
    39. try
    40. return new String(target.trim().getBytes("ISO-8859-1"), charset);    
    41. catch
    42. return
    43.         }    
    44.     }    
    45.     
    46. }


    package wrapper;  
      
    import java.io.UnsupportedEncodingException;  
    import java.net.URLDecoder;  
      
    import javax.servlet.http.HttpServletRequest;  
    import javax.servlet.http.HttpServletRequestWrapper;  
      
    public class GetHttpServletRequestWrapper extends HttpServletRequestWrapper {  
      
        private String charset = "UTF-8";  
      
        public GetHttpServletRequestWrapper(HttpServletRequest request) {  
            super(request);  
        }  
      
        /** 
         * 获得被装饰对象的引用和采用的字符编码 
         * @param request 
         * @param charset 
         */  
        public GetHttpServletRequestWrapper(HttpServletRequest request,  
                String charset) {  
            super(request);  
            this.charset = charset;  
        }  
      
        /** 
         * 实际上就是调用被包装的请求对象的getParameter方法获得参数,然后再进行编码转换 
         */  
        public String getParameter(String name) {  
            String value = super.getParameter(name);  
            value = value == null ? null : convert(value);  
            return value;  
        }  
      
        public String convert(String target) {  
            System.out.println("编码转换之前:" + target);  
            try {  
                return new String(target.trim().getBytes("ISO-8859-1"), charset);  
            } catch (UnsupportedEncodingException e) {  
                return target;  
            }  
        }  
      
    }


    修改过滤器的doFilter方法 代码如下:


    [java] view plain copy

    print      ?                
    1. public void
    2. throws
    3. //设置请求响应字符编码  
    4.         request.setCharacterEncoding(charset);    
    5.         response.setCharacterEncoding(charset);    
    6. //新增加的代码          
    7.         HttpServletRequest req = (HttpServletRequest)request;    
    8.             
    9. if(req.getMethod().equalsIgnoreCase("get"))    
    10.         {    
    11. new
    12.         }    
    13.             
    14. "----请求被"+config.getFilterName()+"过滤");    
    15. //传递给目标servlet或jsp的实际上时包装器对象的引用,而不是原始的HttpServletRequest对象  
    16.         chain.doFilter(req, response);    
    17.             
    18. "----响应被"+config.getFilterName()+"过滤");    
    19.     
    20.     }


    public void doFilter(ServletRequest request, ServletResponse response,  
                FilterChain chain) throws IOException, ServletException {  
            //设置请求响应字符编码  
            request.setCharacterEncoding(charset);  
            response.setCharacterEncoding(charset);  
            //新增加的代码          
            HttpServletRequest req = (HttpServletRequest)request;  
              
            if(req.getMethod().equalsIgnoreCase("get"))  
            {  
                req = new GetHttpServletRequestWrapper(req,charset);  
            }  
              
            System.out.println("----请求被"+config.getFilterName()+"过滤");  
            //传递给目标servlet或jsp的实际上时包装器对象的引用,而不是原始的HttpServletRequest对象  
            chain.doFilter(req, response);  
              
            System.out.println("----响应被"+config.getFilterName()+"过滤");  
      
        }

    这样一来,在servlet中调用包装器的getParameters方法来获取参数,就已经完成了字符编码的转换过程,我们就不需要在每次获取参数时来进行字符编码转换了。