过滤器Filter的案例3——解决全站的请求数据乱码问题

本文介绍了解决网站请求数据乱码问题的方法,包括GET和POST请求的不同处理方式,利用过滤器和装饰者模式对request对象进行增强,确保中文参数正确解析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

过滤器Filter的案例3——解决全站的请求数据乱码问题

5、Filter高级开发(request与response)说明

(1)request & response 与装饰者模式介绍

由于开发人员在filter中可以得到代表用户请求和响应的request、response对象,因此在编程中可以使用Decorator(装饰器)模式requestresponse对象进行包装,再把包装对象传给目标资源,从而实现一些特殊需求

Decorator设计模式的实现

1.首先看需要被增强对象继承了什么接口或父类,编写一个类也去继承这些接口或父类

2.在类中定义一个变量,变量类型即需增强对象的类型。

3.在类中定义一个构造函数,接收需增强的对象。

4.覆盖需增强的方法,编写增强的代码。

 

(2)request对象的增强

Servlet API 中提供了一个request对象的Decorator设计模式的默认实现HttpServletRequestWrapper ,(HttpServletRequestWrapper 类实现了request 接口中的所有方法,但这些方法的内部实现都是仅仅调用了一下所包装的的 request 对象的对应方法)以避免用户在对request对象进行增强时需要实现request接口中的所有方法。

说明:使用Decorator模式包装request对象,完全解决get、post请求方式下的乱码问题

实例: 案例五:解决全站的请求数据的乱码问题

 

(3)response对象的增强

Servlet  API 中提供了response对象的Decorator设计模式的默认实现HttpServletResponseWrapper ,(HttpServletResponseWrapper类实现了response接口中的所有方法,但这些方法的内部实现都是仅仅调用了一下所包装的的 response对象的对应方法)以避免用户在对response对象进行增强时需要实现response接口中的所有方法。

说明:使用Decorator模式包装response对象,解决数据压缩的问题

实例: 案例六:实现全站的数据的压缩

6、案例五: 解决全站的请求数据的乱码问题

(1)解决全站的请求数据的乱码:servlet实现

1.1 RequestServlet

package com.zhku.jsj144.zk.filter.requestFilter;
 
import java.io.IOException;
 
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//解决全站请求数据的乱码问题
 
/*
 * 失败原因:
 * 此时的server.xml配置是:
<Connector port="8080"protocol="HTTP/1.1"
          connectionTimeout="20000"
          redirectPort="8443"
                      URIEncoding="UTF-8"/>
*/
public class RequestServlet extends HttpServlet {
 
         //get请求
         public void doGet(HttpServletRequest request, HttpServletResponse response)
                            throws ServletException, IOException {
        
                   String  name=request.getParameter("name");//获取参数
                   System.out.println("解码前---name:"+name);
                   //通过使用指定的charset 解码指定的 byte 数组,构造一个新的 String
                  
                   //解码:字节-->字符  //编码:字符-->字节
                  
                   //失败1:tomcat的默认编码:由iso-8859-1该为了utf-8
                  
//               name是通过utf-8进行编码的,而此时通过ISO-8859-1去进行解码,就会出现解码错误的情况,
//               而解码出错的情况下,有通过utf-8去进行编码,来获得传递过来的中文参数:name,就会出现乱码情况。
                  
                   //name以iso8859-1的方式编码为字节数组【字符-->字节】, 然后以utf-8的方式解码为字符串【字节-->字符】
                   name= new String(name.getBytes("ISO-8859-1"),"UTF-8");
                  
                   //失败2:不同编码方式进行编码解码,可能会失败
                   //name以 utf-8 的方式编码为字节数组【字符-->字节】, 然后以gbk的方式解码为字符串【字节-->字符】
                   name= new String(name.getBytes("UTF-8"),"gbk");
                  
                   System.out.println("解码后---name:"+name);
                  
                  
         }
        
         //post请求
         public void doPost(HttpServletRequest request, HttpServletResponse response)
                            throws ServletException, IOException {
                  
                   request.setCharacterEncoding("utf-8");
                   String  name=request.getParameter("name");//获取参数
                   System.out.println("name:"+name);
 
         }
}

1.2 RequestServlet2

package  com.zhku.jsj144.zk.filter.requestFilter;
 
import java.io.IOException;
 
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/*
 * 成功原因:
 * 此时的server.xml配置是:
<Connector port="8080"protocol="HTTP/1.1"
          connectionTimeout="20000"
          redirectPort="8443"
                      URIEncoding="UTF-8"/>
*/
public class RequestServlet2 extends HttpServlet {
 
         public void doGet(HttpServletRequest request, HttpServletResponse response)
                            throws ServletException, IOException {
                   String name = request.getParameter("name");// 获取参数
                  
                   //name 以iso8859-1的方式编码为字节数组【字符-->字节】, 然后以utf-8的方式解码为字符串【字节-->字符】
//               name= new String(name.getBytes("ISO-8859-1"), "UTF-8");
                   System.out.println("解码后---name:"+ name);
         }
 
         public void doPost(HttpServletRequest request, HttpServletResponse response)
                            throws ServletException, IOException {
 
                   doGet(request,response);
 
         }
 
}

1.3 RequestServlet3

package com.zhku.jsj144.zk.filter.requestFilter;
 
import java.io.IOException;
  
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//解决全站请求数据的乱码问题
 
/*
 * 成功:
 * 此时的server.xml配置是:
<Connectorport="8080" protocol="HTTP/1.1"
           connectionTimeout="20000"
           redirectPort="8443"/>
*/
public class RequestServlet3 extends HttpServlet {
   //get请求
   public void doGet(HttpServletRequest request, HttpServletResponse response)
         throws ServletException, IOException {
      String name=request.getParameter("name");//获取参数
      System.out.println("解码前---name:"+name);
     
      //解码:字节-->字符  //编码:字符-->字节
     
      //成功:因为tomcat的默认编码:由iso-8859-1
     
      //name 以iso8859-1的方式编码为字节数组【字符-->字节】,然后以utf-8的方式解码为字符串【字节-->字符】
      name = new String(name.getBytes("ISO-8859-1"),"UTF-8");
      System.out.println("解码后---name:"+name);
   }
  
   //post请求
   public void doPost(HttpServletRequest request, HttpServletResponse response)
         throws ServletException, IOException {
     
      request.setCharacterEncoding("utf-8");
      String name=request.getParameter("name");//获取参数
      System.out.println("name:"+name);
 
   }
}

1.4结论
1.4.1 get方式和post方式的编码设置方式不同

自从Tomcat5.x开始,GET和POST方法提交的信息,Tomcat采用了不同的方式来处理编码,

对于POST请求,Tomcat会仍然使用request.setCharacterEncoding方法所设置的编码来处理,如果未设置,则使用默认的iso-8859-1编码。

而GET请求,则不同,Tomcat对于GET请求并不会考虑使用request.setCharacterEncoding方法设置的编码,而会永远使用iso-8859-1编码。

1.4.2 get请求方式说明

因为post方式设置比较简单,所以这里就不再详细叙述;

而get方式设置方式稍微比较复杂点,所以在此详细叙述。

get请求方式:

当我们有去修改tomcat服务器的server.xml文件,并且设置设置参数:URIEncoding="UTF-8",此时,我们直接就可以获取到传递过来的中文参数,不会产生任何乱码问题,例子:RequestServlet2

反过来说,如果没有给tomcat服务器的server.xml文件进行任何设置,则像例子:RequestServlet3一样,进行一定编码的设置,才可以获得正确的中文参数。

特别说明,如果有修改过tomcat服务器server.xml文件,在使用时,又像RequestServlet3一样,给传递过来的中文参数,进行一定的编码设置,就会导致乱码,例子:RequestServlet则会导致乱码

(2)解决全站的请求数据的乱码:过滤器实现

这里只是实现的过滤器:当我们没有去修改tomcat服务器的server.xml文件

2.1思路分析

2.2代码实现:【RequestFilter + MyHttpServletRequestWrapper + web.xml文件配置】
2.2.1RequestFilter
package com.zhku.jsj144.zk.filter.requestFilter;

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;
//解决全站的请求数据的乱码问题的过滤器

//获取参数的三种方式
//request.getParameter("");
//request.getParameterNames();
//request.getParameterMap();

public class RequestFilter implements Filter {
	@Override
	public void init(FilterConfig filterConfig) throws ServletException {}
	@Override
	public void destroy() {}
	
	@Override
	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {

		HttpServletRequest req=(HttpServletRequest)request;
		HttpServletResponse resp=(HttpServletResponse)response;
		
		System.out.println("开始工作。。。。。。。。。。。。。。。。");
		
		
		//思路:获取参数有三种方式,我们的目的:就是对这三种方式进行改写:即增强它们的功能
		//装饰者模式,我们的思路时加强request,然后把加强后的request传递下去,这样,
		//在使用加强后的request的获得参数的三种方法,就可以获得设置编码后的,正确的中文参数了。
		
		//Servlet API 中提供了一个request对象的Decorator设计模式的默认实现类HttpServletRequestWrapper
		//注意:HttpServletRequestWrapper 类实现了request 接口中的所有方法,
		//但这些方法的内部实现都是仅仅调用了一下所包装的的 request 对象的对应方法
		
		//我们继承:HttpServletRequestWrapper,然后达到自己的目的
		MyHttpServletRequestWrapper myRequest =new MyHttpServletRequestWrapper(req);
		
		//增强后的request:myRequest--然后放行
		chain.doFilter(myRequest, resp);//放行
	}

	

}


2.2.2MyHttpServletRequestWrapper

package com.zhku.jsj144.zk.filter.requestFilter;
 
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
 
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
//获取参数的三种方式
//方法1:request.getParameter("");       返回类型:String
//方法2:request.getParameterNames();             返回类型:String【】
//方法3:request.getParameterMap();                 返回类型:Map<String,String[]>
 
//思路分析:重心放在方法3:request.getParameterMap();因为此方法,实际功能涵盖了方法1和方法2
//把方法3实现了,然后方法1和方法2调用方法3就可以了
 
//注意:通用方法getParameterMap是存在弊端的。
 
//因为当servlet种存在几行请求参数代码时:
//request.getParamger("aaa");request.getParamger("bbb");request.getParamger("ccc");
//每行代码都会:调用getParameterMap()方法,因此,每行代码执行时,都会获得三个参数:aaa,bbb,ccc的中文参数值,
//相当于:values[i]=new String(values[i].getBytes("iso-8859-1"),"utf-8");这行代码执行三次
//解释:代码执行第一次:中文参数,用iso-8859-1进行解码,然后用utf-8进行编码【因为一开始获得中文参数时是默认:iso-8859-1进行编码的】,所以
//此时是得到了正确的中文参数。       代码执行第二次:把正确的中文参数【utf-8编码过来的数值】,用iso-8859-1进行解码,然后用utf-8进行编码,此时
//获得了错误的中文参数,因为那个正确的中文参数,再次进行编码,解码用的是不同的码表,所以会出现乱码现象。   同理,代码执行第三次,也是跟代码执行第二次
//一样的结果,获得乱码。
 
//因此,我们要保证的是,对于获取过来的参数,我们只能获取一次,这样我们就可以获得正确的中文参数值了。
//解决思路:设置bool值,保证只进行一次获取,从而保证编码,解码的正确性。
//private boolean firstGet=false;//设置的bool数值
 
public class MyHttpServletRequestWrapper extends HttpServletRequestWrapper{
 
         //目的:获得原有的requset
         private HttpServletRequest request;
        
         //有参构造函数,将原来的request获取,然后进行相关的加强后返回
         public MyHttpServletRequestWrapper(HttpServletRequest request) {
                   super(request);
                   this.request=request;
         }
 
         @Override
         public String getParameter(String name) {
                   Map<String,String[]> map = getParameterMap();//调用 getParameterMap()方法
                   String[] values = map.get(name);
                   //要进一步判断是否为空
                   if(values!=null){
                            String value=values[0];//返回数组的第一个元素         
                            return value;
                   }
                   return null;
//               return super.getParameter(name);
         }
        
         @Override
         public String[] getParameterValues(String name) {
                   Map<String,String[]> map = getParameterMap();//调用 getParameterMap()方法
                  
                   String[]  values = map.get(name);
                   return values;
//               return super.getParameterValues(name);
         }
        
         //成员变量的bool数值,相当于一个全局变量
         private boolean firstGet=false;//设置的bool数值
         //默认是false,再调用一次后,即甚至为true。即不会第二次调用该方法
        
         @Override
         publicMap<String, String[]> getParameterMap() {
                  
                   if(firstGet==false){//只有在第一次时,才会进行调用的操作
                            //对于get和post的请求方式做不同的处理
                            String  method = request.getMethod();
                           
                            //post的请求方式
                            if("post".equalsIgnoreCase(method)){
                                     try{
                                               request.setCharacterEncoding("utf-8");
                                     }catch (UnsupportedEncodingException e) {
                                               e.printStackTrace();
                                     }
                                     return super.getParameterMap();
                            }
                           
                            //get的请求方式
                            else{
                                    
                                     Map<String,String[]> maps = request.getParameterMap();//所有参数
                                    
                                     Map<String,String[]> newMaps=new HashMap<String,String[]>();//保存修改后的数据
                                     //遍历获取到的所有参数
                                     for(int i = 0; i < maps.size(); i++)
                                     {
                  
                                               Set<String> keySet = maps.keySet();
                                              
                                               for(String key : keySet)
                                               {
                                                        String[] values = maps.get(key);//得到数值
                                                        //对数值进行重新编码,解码
                                                        for(int j=0;j<values.length;j++)
                                                        {
                                                                 try{
                                                                           values[i]=newString(values[i].getBytes("iso-8859-1"),"utf-8");
                                                                 }catch (UnsupportedEncodingException e) {
                                                                           e.printStackTrace();
                                                                 }
                                                                
                                                        }
                                                       
                                                        //因为java.util.Map所包装的HttpServletRequest对象的参数是不可改变的,
                                                        //强行更改就会报java.lang.IllegalStateException:
                                                        //Nomodifications are allowed to a locked ParameterMap异常,
                                                        //这个时候就会通过间接更改值的方式解决这个问题
 
                                                        //所以 此段代码作废:    maps.put(key, values);//maps对于原来的可以进行覆盖
                                                        //正确思路:是重新new一个新的map,然后进行赋值,最后进行返回,即可达到要求
                                                       
                                                        newMaps.put(key,values);//用新的map进行保存
                                               }
                                     }
                                     firstGet=true;//设置为true后,是为了避免二次使用
//                                  return maps;
                                     return newMaps;//修改后的maps
                            }
                   }
                  
                   //由于已经调用过了,所以直接返回上一次的数值即可,无须做任何处理
                   return super.getParameterMap();
         }
}

2.2.3 web.xml文件配置

 <!--  解决全站的请求数据的乱码问题 -->
 
   <filter>
  <filter-name>RequestFilter</filter-name>
  <filter-class>com.zhku.jsj144.zk.filter.requestFilter.RequestFilter</filter-class>
  </filter>
  <filter-mapping>
  <filter-name>RequestFilter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值