在一个项目中,每一个Servlet都是处理自己相关的业务。在这些Servlet执行之前都是需要判断用户是否登录了。如果用户登录了,可以继续操作,如果没有登录,需要用户登录。判断用户是否登录的代码是固定的,并且在每一个Servlet类当中都需要编写,如果这样显然代码没有得到重复利用。包括每一个Servlet都要解决中文乱码问题,也有公共的代码。这些代码目前都是重复编写,都没有达到复用。这些代码的复用问题的解决就需要使用Filter(过滤器)来实现。
Filter(过滤器)是Servlet规范中一个,我们通过该技术来实现每个Servlet中代码复用的问题。
Filter(过滤器)可以在Servlet这个目标程序执行之前添加代码。也可以在目标Servlet执行之后添加代码。前后都可以添加过滤规则。像前面说的,在每个Servlet中执行具体业务之前都需要判断的用户是否登录的代码就可以写在Filter(过滤器)中,并且让它在Servlet目标程序之前执行,而解决响应时中文乱码的代码也可以放到Filter(过滤器)中,并且让其在Servlet目标程序之后去执行。
Filter(过滤器)的编写步骤:
1.编写一个Java类实现一个接口:jarkata.servlet.Filter。并且实现这个接口当中所有的方法。
init方法:在Filter对象第一次被创建之后调用,并且只调用一次。
doFilter方法:只要用户发送一次请求,则执行一次。发送N次请求,则执行N次。在这个方法中编写过滤规则。
destroy方法:在Filter对象被释放/销毁之前调用,并且只调用一次。
2.在web.xml文件中对Filter进行配置。这个配置和对Servlet的配置很像。
<filter>
<filter-name>filter2</filter-name>
<filter-class>com.bjpowernode.javaweb.servlet.Filter2</filter-class>
</filter>
<filter-mapping>
<filter-name>filter2</filter-name>
<url-pattern>*.do</url-pattern>
</filter-mapping>
或者在类上使用注解进行配置:@WebFilter({"*.do"})
注意:
Servlet对象默认情况下,在服务器启动的时候是不会新建对象的。
Filter对象默认情况下,在服务器启动的时候就会新建对象。
Servlet是单例的。Filter也是单例的。(单实例。)
目标Servlet是否执行,取决于两个条件:
第一:在过滤器当中是否编写了:filterChain.doFilter(request,response);代码。
chain.doFilter(request, response); 这行代码的作用:
执行下一个过滤器,如果下面没有过滤器了,执行(与请求路径对应的)Servlet。
注意:Filter的优先级,天生的就比Servlet优先级高。
/a.do 对应一个Filter,也对应一个Servlet。那么一定是先执行Filter,然后再执行Servlet。
第二:用户发送的请求路径是否和Servlet的请求路径一致。(不一致是不会执行的)
关于Filter的配置路径:
/a.do、/b.do、/dept/save 这些配置方式都是精确匹配。
/* 匹配所有路径。
*.do 后缀匹配。不要以 / 开始
/dept/* 前缀匹配。
Filter的执行顺序:
1.在web.xml文件中进行配置的时候:
依靠filter-mapping标签的配置位置,越靠上优先级越高。过滤器的调用顺序,遵循栈数据结构。
2.使用@WebFilter进行配置的时候:
比较Filter这个类名
比如:FilterA和FilterB,会先执行FilterA,再执行FilterB
比如:Filter1和Filter2,会先执行Filter1,再执行Filter2
为此:对于过滤器的配置我们通常使用web.xml的方式进行,而不是采用@WebFilter的方式。
Filter的生命周期:
和Servlet对象生命周期一致。唯一的区别:Filter默认情况下,在服务器启动阶段就实例化。Servlet不会。
Filter过滤器这里有一个设计模式(责任链设计模式):
过滤器最大的优点:
在程序编译阶段不会确定调用顺序。因为Filter的调用顺序是配置到web.xml文件中的,只要修改web.xml配置文件中filter-mapping的顺序就可以调整Filter的执行顺序。显然Filter的执行顺序是在程序运行阶段动态组合的。那么这种设计模式被称为责任链设计模式。
责任链设计模式最大的核心思想:
在程序运行阶段,动态的组合程序的调用顺序。