1、javaweb中的过滤器day15过滤器(Filter)过滤器概述i什么是过滤器过滤器JavaWeb三大组件之一,它与 Servlet很相似!不它过滤器是用来拦截请求的,而不是处 理请求的。当用户请求某个 Servlet时,会先执行部署在这个请求上的 Filter,如果Filter “放行”,那么会继承执行用户请求的 Servlet;如果Filter不放行”,那么就不会执行用户请求的 Servlet。其实可以这样理解,当用户请求某个 Servlet时,Tomcat会去执行注册在这个请求上的 Filter,然后是否“放行”由 Filter来决定。可以理解为, Filter来决定是否调用 Serv
2、let!当执行完成 Servlet的代码后,还会执行 Filter后面的代码。过滤器 Servlet程序输出;start.*.servletend.2 过滤器之hello world其实过滤器与 Servlet很相似,我们回忆一下如果写的第一个 Servlet应用!写一个类,实现Servlet接口!没错,写过滤器就是写一个类,实现 Filter接口。public class HelloFilter impleme nts Filter public void ini t(FilterC onfig filterC on fig) throws ServletExcepti on public
3、void doFilter(ServletRequest request, ServletResp onse resp on se,FilterCha in cha in) throws lOExcepti on, ServletExcepti on System. out .println( Hello Filter );public void destroy。第二步也与 Servlet 一样,在web.xml文件中部署 Filter:vfilter vfilter- name helloFiltercn .itcast.filtvfilter-mappi nghelloFiltervurl
4、-patter n/i ndex.jsp应该没有问题吧,都可以看懂吧!OK了,现在可以尝试去访问 index.jsp页面了,看看是什么效果!当用户访问index.jsp页面时,会执行 HelloFilter的doFilter()方法!在我们的示例中,index.jsp页面是不会被执行的,如果想执行 index.jsp页面,那么我们需要放行!有很多同学总是错误的认为,一个请求在给客户端输出之后就算是结束了,这是不对的!其实 很多事情都需要在给客户端响应之后才能完成!过滤器详细1过滤器的生命周期我们已经学习过 Servlet的生命周期,那么 Filter的生命周期也就没有什么难度了!init(Fi
5、lterConfig):在服务器启动时会创建 Filter实例,并且每个类型的 Filter只创建一个实例,从此不再创建!在创建完 Filter实例后,会马上调用 init()方法完成初始化工作,这个方法只会被执行一次;doFilter(ServletRequest req,ServletResponse res,FilterChain chain):这个方法会在用户每次访 问“目标资源(patternindex.jsp )”时执行,如果需要放行”,那么需 要调用 FilterChain 的 doFilter(ServletRequest,ServletResponse)方法,如果不调用 Fi
6、lterChain的doFilter()方法,那么目标资源将无法执行;destroy():服务器会在创建 Filter对象之后,把 Filter放到缓存中一直使用,通常不会销毁它。一般会在服务器关闭时销毁 Filter对象,在销毁Filter对象之前,服务器会调用 Filter对象的destory()方法。2 FilterCo nfig你已经看到了吧, Filter接口中的init()方法的参数类型为 FilterConfig类型。它的功能与ServletConfig相似,与 web.xml文件中的配置信息对应。下面是 FilterConfig的功能介绍:ServletContext getS
7、ervletContext():获取 ServletContext 的方法;String getFilterName():获取 Filter 的配置名称;与 filter-name元素对应;Stri ng get In itParameter(Stri ng name):获取 Filter 的初始化配置,与 元素对应;Enumeration getlnitParameterNames():获取所有初始化参数的名称。puJilic class Hel丄oFil匕合応 戈mpltaii合ntw Filter puJtlic void inlt (FllterConf ig filter Confi
8、g) throws SeirvletEx cep Elon String f jlttzXcinw* = fllterConfig gut:FjLLti:IilSLmr(;Str j.11 1 = filter C onfg get In七cune ter ( pariuiiHam.c 1ff;口 nameiS s filterCo口丘ig 号暑七 InLtPar amsterNiuEs ();tx p r xn七丄i f ilt ExNameyiSys tem pu f p c xnt丄口v alj; while (names + hssNoreELements (I ) String 口削
9、熄 =(St ring) names nextE lenten t();Ftr.mg 卩目丄口启=flltgrConf ig Pgt InitPaiTRrnetei: (n&ni台); 守日七己尬 out Bprlntln (name + *= + value J;3 FilterChaindoFilter()方法 的参数中有一个类型为FilterCha in的参数,它只有一个方法: doFilter(ServletRequest,ServletResponse)。前面我们说doFilter()方法的放行,让请求流访问目标资源! 但这么说不严密,其实调用该方法的意思是,“我(当前Filter)
10、”放行了,但不代表其他人(其他过滤器)也放行。也就是说,一个目标资源上,可能部署了多个过滤器,就好比在你去北京的路上有多个打劫的 匪人(过滤器),而其中第一伙匪人放行了,但不代表第二伙匪人也放行了,所以调用 FilterChain类的doFilter()方法表示的是执行下一个过滤器的 doFilter()方法,或者是执行目标资源!如果当前过滤器是最后一个过滤器,那么调用 chain.doFilter()方法表示执行目标资源,而不是最后一个过滤器,那么 chain.doFilter()表示执行下一个过滤器的 doFilter()方法。4多个过滤器执行顺序一个目标资源可以指定多个过滤器,过滤器的执
11、行顺序是在 web.xml文件中的部署顺序:vfilter vfilter- name vfilter-classmyFilter1cn .itcast.fivfilter-mappi ngmyFilter1/i ndex.jsp/ filter-mappingvfilter- namevfilter-classmyFilter2 cn .itcast.filter.MyFilter2/ filter-classvfilter-mappi ngvfilter- nameurl-patter nmyFilter2/i ndex.jsp/ filter-name/ url-patternpubli
12、c class MyFilter1 exte nds HttpFilter public void doFilter(HttpServletRequest request, HttpServletResp onseresp onse.FilterChain chain)System. out .println(throws lOExcepti on, ServletExcepti on filterl start.cha in. doFilter(request, resp on se);System. out .println( filter1 end.);/ 放行,执行 MyFilter2
13、 的 doFilter();方法public class MyFilter2 exte nds HttpFilter public void doFilter(HttpServletRequest request, HttpServletResp onseresp onse,FilterChain chain)System. out .println(throws IOExcepti on, ServletExcepti on filter2 start.cha in. doFilter(request, resp on se);System. out .println( filter2 en
14、d.);/放行,执行目标资源);This is my JSP page.index.jsp %System.out.pri ntl n( in dex.jsp);%当有用户访问index.jsp页面时,输出结果如下:filter1 start.filter2 start.in dex.jsp filter2 en d.filter1 en d.5四种拦截方式我们来做个测试,写一个过滤器,指定过滤的资源为 b.jsp,然后我们在浏览器中直接访问 b.jsp,你会发现过滤器执行了!但是,当我们在 a.jsp 中 request.getRequestDispathcer( “/b.jsp ”).fo
15、rward(request,resp时se就不会再执行过滤器了!也就是说,默认情况下,只能直接访问目标资源才会执行过滤器,而 forward执行目标资源,不会执行过滤器!public class MyFilter exte nds HttpFilter public void doFilter(HttpServletRequest request,HttpServletResp onse resp on se, FilterChai n cha in) throws IOExcepti on, ServletExcepti on System. out .println( myfilter.
16、);cha in. doFilter(request, resp on se);filter -n amemyfiltercn .itcaist.filter.MyFilter/ filter-classmyfilter/b.jspb.jsp a.jsp http:/localhost:8080/filtertest/b.jsp - 直接访问 b.jsp 时,会执行过滤器内容;http:/localhost:8080/filtertest/a.jsp - 访问 a.jsp,但 a.jsp 会 forward 到 b.jsp,这时就不会执行 过滤器!其实过滤器有四种拦截方式!分别是: REQUE
17、ST FORWARD INCLUDE ERRORREQUEST直接访问目标资源时执行过滤器。包括:在地址栏中直接访问、表单提交、超链接、重定向,只要在地址栏中可以看到目标资源的路径,就是 REQUESTFORWARD 转发访问执行过滤器。包括 RequestDispatcher#forward()方法、jsp:forward 标签都是转发访问;INCLUDE 包含访问执行过滤器。包括 RequestDispatcher#include()方法、jsp:include 标签都是包含访问;ERROR当目标资源在 web.xml中配置为error-page中时,并且真的出现了异常,转发到 目标资源时
18、,会执行过滤器。可以在filter-mapping中添加0n个dispatcher子元素,来说明当前访问的拦截方式。 filter-mappi ngvfilter -n amemyfilter vurl-patter ndispatcherdispatcher/b.jsp REQUESTFORWARE/ dispatcherfilter-mappi ngmyfilter / filter-nameurl-patter n/b.jsp / url-patternvfilter-mappi ngfilter -n ameurl-patter ndispatchermyfilter/b.jsp FO
19、RWARDc/ filter-nameurl-patter ndispatcher其实最为常用的就是 REQUEST和FORWARD两种拦截方式,而 INCLUDE和ERROR都比较少用!其中INCLUDE比较好理解,我们这里不再给出代码,学员可以通过 FORWARD方式修改,来自己测试。而ERROR方式不易理解,下面给出 ERROR拦截方式的例子:filter-mappi ngfilter -n ameurl-patter n dispatcher/ filter-mapping myfilter /b.jsp ERROR500 /b.jsp a.jsp 6过滤器的应用场景过滤器的应用场景:
20、执行目标资源之前做预处理工作,例如设置编码,这种试通常都会放行,只是在目标资源执行之前做一些准备工作;通过条件判断是否放行,例如校验当前用户是否已经登录,或者用户 IP是否已经被禁用;在目标资源执行后,做一些后续的特殊处理工作,例如把目标资源输出的数据进行处理;7设置目标资源在web.xml文件中部署Filter时,可以通过* ”来执行目标资源:vfilter-mappi ng vfilter -n ame url-patter n myfilter /* 这一特性与Servlet完全相同!通过这一特性,我们可以在用户访问敏感资源时,执行过滤器, 例如:/admin/* ,可以把所有管理员才能
21、访问的资源放到 /admin路径下,这时可以通过过滤器来校验用户身份。还可以为vfilter-mapping指定目标资源为某个 Servlet,例如:vservlet vservlet- name myservlet v/ servlet-namevservlet-class cn .itcast.servlet.MyServletv/ servlet-classvservlet-mappi ngvservlet- name myservlet v/ servlet-namevurl-patter n/abc v/ url-pattern v/ servlet-mappingvfilter v
22、filter -n amemyfilter v/ filter-name vfilter-classcn .itcast.filter.MyFilterv/ filter-class v/ filter vfilter-mappi ngvfilter -n amemyfilter v/ filter-name vservlet- name myservlet v/ servlet-namev/ filter-mapping当用户访问 http:/localhost:8080/filtertest/abc 时,会执行名字为 myservlet 的 Servlet,这时会执行过滤器。8 Filte
23、r 小结Filter的三个方法:void init(FilterConfig):在 Tomcat 启动时被调用;void destroy():在Tomcat关闭时被调用;void doFilter(ServletRequest,ServletResponse,FilterChain):每次有请求时都调用该方法;FilterConfig类:与ServletConfig相似,用来获取 Filter的初始化参数ServletContext getServletContext():获取 ServletContext 的方法;String getFilterName():获取 Filter 的配置名称;
24、Stri ng get In itParameter(Stri ng name):获取 Filter 的初始化配置,与 元素对应; Enumeration getlnitParameterNames():获取所有初始化参数的名称。FilterChain 类:void doFilter(ServletRequest,ServletResponse):放行!表示执行下一个过滤器,或者执行目 标资源。可以在调用 FilterChain的doFilter()方法的前后添加语句, 在FilterChain的doFilter() 方法之前的语句会在目标资源执行之前执行,在 FilterChain的doFi
25、lter()方法之后的语句会在目标资源执行之后执行。四各拦截方式: REQUEST FORWARD INCLUDE ERROR 默认是 REQUES方式。REQUEST拦截直接请求方式;FORWARD拦截请求转发方式; INCLUDE拦截请求包含方式; ERROR拦截错误转发方式。过滤器应用案例分ip统计网站的访问次数1 说明网站统计每个ip地址访问本网站的次数。2分析因为一个网站可能有多个页面,无论哪个页面被访问,都要统计访问次数,所以使用过滤器最 为方便。因为需要分IP统计,所以可以在过滤器中创建一个 Map,使用IP为key,访问次数为value。当 有用户访问时,获取请求的 IP,如果IP在Map中存在,说明以前访问过,那么在访问次数上加 1,即可;IP在Map中不存在,那么设置次数为 1。把这个Map存放到ServletContext中!3 代码in dex.jsp分IP统计访问次数IP 地址 次数 $e ntry.keyt
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1