JavaWeb--Filter(过滤器)学习(附加)

Posted jinner

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaWeb--Filter(过滤器)学习(附加)相关的知识,希望对你有一定的参考价值。

一、Filter运行原理解析多个Filter执行顺序

  1.一个数组:存放与请求相匹配的所有Filter

  2.一个Map:Map的key为<url-pattern>的值,value为Filter实例对象的引用

  3.执行原理:当请求到达Web服务器时,会先对该请求进行解析,使用解析出的URI作为比较对象,从Map中查找是否存在匹配的key。若存在匹配的key,那么读取其value,即Filter对象的引用,将该引用存入到数组中。然后继续向后查找(这里与servlet的运行原理不同,servlet查找到对应的key,则停止向后查找),直到将该Map查找完毕。这样在数组中就存在按照查找顺序排好序的Filter引用。最后数组初始化完毕,开始按照数组元素顺序进行执行。所有数组中的Filter全部执行完毕,再跳转到请求的目标资源。

(建议:1.查看源码  2.addFilter(ApplicationFilterConfig)--数组的扩容)

 

二、装饰者设计模式

    (1)装饰模式指的是在不必改变原类文件和使用继承的情况下,动态地加强一个对象的功能。

    (2)装饰者基类:1:装饰者基类要实现与目标类相同的接口     2:带参构造器(通过带参构造器传入目标对象)3    :重写不对其做任何性的增强(调用目标类的目标方法,但不对其做任何修改)

    继承装饰者基类    2:要有带参构造器    3:具体装饰者只对装饰者基类业务方法进行单一的增强(主要通过“装饰者链”不断加强)

技术分享图片
package com.jinner.service;
//业务逻辑接口
public interface SomeService {
    String doSome();
}
View Code
技术分享图片
package com.jinner.service;
//目标类
public class ServiceExc implements SomeService {
    @Override
    public String doSome() {
        return "      jinner";
    }

}
View Code
技术分享图片
package com.jinner.decorator;
import com.jinner.service.SomeService;
//装饰者基类
//要求1:装饰者要实现与目标类相同的接口
//要求2:无参构造器
//要求3:不对其做任何性的增强
public class SomeServiceDecorator implements SomeService {
    private SomeService target;  //目标对象
    public SomeServiceDecorator() {
        super();
        // TODO Auto-generated constructor stub
    }

    //通过带参构造器传入目标对象
    public SomeServiceDecorator(SomeService target) {
        super();
        this.target = target;
    }

    @Override
    public String doSome() {
        // 调用目标类的目标方法,但不对其做任何修改
        return target.doSome();
    }

}
View Code
技术分享图片
package com.jinner.decorator;

import com.jinner.service.SomeService;

public class ToupperCaseDecoration extends SomeServiceDecorator {
    
    public ToupperCaseDecoration() {
        super();
    }

    public ToupperCaseDecoration(SomeService target) {
        super(target);
    }

    @Override
    public String doSome() {
        // TODO Auto-generated method stub
        return super.doSome().toUpperCase();
    }
}
View Code
技术分享图片
package com.jinner.text;

import com.jinner.decorator.SomeServiceDecorator;
import com.jinner.service.ServiceExc;
import com.jinner.service.SomeService;

public class Mytext2 {

    public static void main(String[] args) {
        //创建目标对象
        SomeService target = new ServiceExc();
        //使用目标对象作为参数,创建装饰者
        SomeService service = new SomeServiceDecorator(target);
        String result = service.doSome();
        System.out.println("result = "+result);
    }

}
View Code

三、静态代理设计模式

(1)静态代理类与装饰者间的共同点:
   1.都要实现与目标类相同的接口
   2.这两个类中都要声明目标对象
   3.都可以在不修改目标类的前提下增加目标性能

(2)静态代理类与装饰者间的区别:
  1.使用目的不同:
   装饰者的使用目的:就是增强目标对象
   静态代理的使用目的是:为了保护和隐藏目标对象
   2.对于目标对象的获取方式不同:
   装饰者获取目标对象要通过带参构造器传进去
   静态代理中目标对象的获取:在无参构造器中直接获取

  

public class SomeServiceProxy implements SomeService {
    private SomeService target;
    
    //在无参构造器中创建目标对象
    public SomeServiceProxy() {
        target = new ServiceExc();
    }

    @Override
    public String doSome() {
        // TODO Auto-generated method stub
        return target.doSome().toUpperCase();
    }

}

 

   3.功能增强的实现者不同:
   装饰者设计模式中存在装饰者基类,其并不真正实现增强,所以存在“装饰者链”的概念
   静态代理设计模式中一般不存在父子类的关系,具体增强,就是由代理类完成,无需子类完成,所以不存在“链”的概念


四、post与get方法提交的中文乱码问题(这里指低版本的Tomcat)
(1)tomcat7:
1.没有自动解决中文乱码问题
2.Filter的init和destory要手动实现
(2)tomcat9:
1.解决了中文乱码问题
2.Filter的init和destory要自动实现

(3)post方式提交中文乱码问题:
1.使用过滤器实现,filter的chain.doFilter(arg0, arg1)前加上arg0.setCharacterEncoding("utf-8")  优点:1.避免每个servlet重复代码量    2.修改容易
(4)GET方式提交中文乱码问题:
分析:当用户提交了一个包含中文参数的请求时,浏览器首先将这些中文转化为一个字节序列,发送到服务器,服务器接收这个字节序列后,会按照其默认的字符编码ISO8859-1对其进行解码,此时就产生乱码。但接着,服务器会把将解码过的参数存放到parameterMap(关键)中,那么这个Map中的参数已经是乱码了。
2.因parameterMap中存放的参数已经是乱码,故request.parameter()不能使用。那么重新定义HttpServletRequest,但其不能修改,用装饰者设计模式进行增强。

技术分享图片
package com.jinner.text;

import java.io.UnsupportedEncodingException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.Vector;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
//定义具体的请求的装饰者类
public class CustomRequest extends HttpServletRequestWrapper {

    public CustomRequest(HttpServletRequest request) {
        super(request);
        // TODO Auto-generated constructor stub
    }
    /**
     *  要将原始的Map替换为自定义的Map
     *  原始的map中的数据是乱码
     *  自定义的Map中的数据来自于原始的Map,但是由原始Map中的数据解决乱码问题后再放入
     */
    @Override
    public Map<String, String[]> getParameterMap() {
        //新建一个map,将来其中的数据是解决过乱码的。将来用户获取到的Map也是这个Map
        Map<String,String[]> newMap = new HashMap<>();
        //获取原始的Map,其中的数据是包含乱码的
        Map<String,String[]> originalMap = super.getParameterMap(); 
        
        /**
         * 将原始Map中的数据解决乱码问题后,写进新的的Map
         * 遍历原始Map
         */
        try {
            for(String key : originalMap.keySet()) {
                //获取当前遍历key的所有值
                String[] values = originalMap.get(key);
                //遍历values数组,对第一个值进行中文乱码问题解决
                for(int i=0;i<values.length;i++) {
                    //按照字符当前的编码进行打散,即进行编码
                    
                    byte[] bytes = values[i].getBytes("ISO8859-1");
                    
                    //按照目标编码进行组装,即进行解码
                    values[i] = new String(bytes,"UTF-8"); 
                    
                    //将解决了乱码问题的数据放入到新的Map中
                    newMap.put(key, values);
                }
            }
        } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        //返回新创建的Map
        return newMap;
    }
    
    @Override
    public Enumeration<String> getParameterNames() {
        Map<String, String[]> parameterMap = this.getParameterMap();
        //keySet转为Vector
        Set<String> keySet = parameterMap.keySet();
        Vector keyVector = (Vector) keySet;
        //将Vector转换为Enumeration
        return keyVector.elements();
    }
    
    @Override
    public String[] getParameterValues(String name) {
        //获取自定义的parameterMap
        Map<String, String[]> parameterMap = this.getParameterMap();
        
        return parameterMap.get(name);
    } 
    
    @Override
    public String getParameter(String name) {
        // TODO Auto-generated method stub
        return this.getParameterValues(name)[0];
    }
    
    
}
View Code

 

(5)访问权限过滤器

关键:String servletPath = request.getServletPath();

      servletPath.startWith("/****")



























以上是关于JavaWeb--Filter(过滤器)学习(附加)的主要内容,如果未能解决你的问题,请参考以下文章

学习日记:关于javaweb filter中过滤了css文件的解决方法

JavaWeb Filter

javaweb----Filter

JavaWeb:Filter

如何将过滤器附加到 QuickBlox 的 videoTrack?

附加 QueryDSL 谓词或基于过滤器值构建谓词