2.我们的网络应用程序经常接收汉字。由于可能会导致中文乱码,所以我们每次都需要在方法的开头使用request.setCharacterEncoding("utf-8");我们可以直接自己获取参数值吗?设置编码。有能力的!
我们已经想出了解决这个问题的方法。也就是说,我们在发出每个请求之前拦截每个请求,然后在设置完所有内容后释放该请求。类似于我们地铁站的检票系统。大家进站都要刷卡,扣钱后才能进站乘车。
Web中也有这种机制,我们称之为过滤器。这就是我们接下来要学习的过滤器
Filter简介
什么是filter1)Filter的基本功能是拦截Servlet容器调用Servlet(JSP)的过程,从而在Servlet处理请求之前和Servlet响应请求之后实现一些特殊功能。
2)ServletAPI中定义了三个接口类,供开发者编写Filter程序:Filter、FilterChain、FilterConfig
3)Filter程序是一个实现Filter接口的Java类。它类似于Servlet程序。它由Servlet容器调用并执行。
4)Filter程序需要在web.xml文件中注册并设置其可以拦截的资源:Filter程序可以拦截Jsp、Servlet、静态图像文件和静态html文件
filter的运行原理是什么这个Servlet过滤器就是我们的过滤器
1)当web.xml中注册了一个Filter来拦截某个Servlet程序时,这个Filter就成为了Tomcat与Servlet程序之间通信线路上的一道屏障。Filter可以通过Servlet容器对Servlet程序的请求进行拦截,并根据Servlet程序发回Servlet容器的响应来决定是否继续将请求传递给Servlet程序以及是否修改请求及相应的信息。
2)一个Web应用程序中可以注册多个Filter程序,每个Filter程序可以拦截一个或一组Servlet程序。
3)如果有多个Filter程序拦截某个Servlet程序的访问过程,当该Servlet的访问请求到来时,Web容器会将这多个Filter程序组合成一条Filter链(过滤器链)。Filter链中各个Filter的拦截顺序与应用程序的web.xml中映射的顺序一致
Filter-helloword
你好世界
编写过滤器的三个步骤:
1.创建过滤器实现类并实现过滤器接口
2、编写web.xml配置文件,配置过滤器信息。
3.运行项目,可以看到filter起作用了。
代码:
//1.Filter实现类publicclassMyFirstFilterImplementsFilter{@Overridepublicvoidinit(FilterConfigfilterConfig)throwsServletException{System.out.println('初始化方法');}@OverridepublicvoiddoFilter(ServletRequestrequest,ServletResponseresponse,FilterChainchain)throwsIOException,ServletException{System.out.println('dofiltermethod');}}@Overridepublicvoiddestroy(){System.out.println('销毁方法.');}}//2。web.xml配置过滤器filter-nameMyFirstFilter/filter-namefilter-classcom.atguigu.filter.MyFirstFilter/filter-class/filterfilter-mappingfilter-nameMyFirstFilter/filter-nameurl-pattern/index.jsp/url-pattern/filter-映射//3。运行程序,发现不再显示index.jsp页面,并且后台输出了“dofilter方法”,说明我们编写的过滤器已经被执行了。filter的生命周期1)当服务器启动时,过滤器被创建并初始化,并执行init()方法。
2)当请求通过过滤器时执行doFilter方法。
3)当服务器停止时,调用destroy方法。
filter放行请求我们发现刚才配置过滤器后,无法访问index.jsp页面。访问该页面时,会调用过滤器的dofilter方法。说明dofilter这个方法拦截我们的请求。
我们如何显示页面。也就是如何释放请求。我们观察到一个filterChain被传递到这个方法中。filterChain中有一个doFilter()方法。释放请求只需要调用filterChain的dofilter方法即可。
publicvoiddoFilter(ServletRequestrequest,ServletResponseresponse,FilterChainchain)throwsIOException,ServletException{System.out.println('dofilter方法');chain.doFilter(request,response);//释放请求}filter拦截原理我们在chain.doFilter(request,response);方法后面也写一句,System.out.println
(“执行完doFilter方法后.”),同样在index.jsp页面上编写一个jsp脚本片段,输出的是一个jsp页面。运行程序后,发现控制台输出了这样几句话:
dofilter方法.我按照jsp页面的dofilter方法.我们不难发现filter的运行过程
FilterChain
doFilter(ServletRequestrequest,ServletResponseresponse,FilterChainchain)
在执行doFilter之前,filterChain对象被容器传递到方法中。调用该对象的.doFilter()方法会释放请求,实际上是执行过滤器链中的下一个doFilter方法,但如果只有一个过滤器,则会被释放。
FilterConfig
FilterConfig与ServletConfig类似,是filter的配置信息对象。FilterConfig对象具有以下方法。
getFilterName():获取当前过滤器的名称。获取到的是web.xml中配置的filter-name的值
getInitParameter(Stringname):获取过滤器的初始化参数。在web.xml中配置
getInitParameterNames():获取过滤器初始化参数名称的集合。
getServletContext():获取当前Web项目的ServletContext对象。
Filter的url-pattern
url-pattern配置哪些请求被过滤器过滤。主要有以下几种配置:
web.xml中配置的/是以当前项目路径为根路径。
1)精确匹配:
/index.jsp/user/login请求/index.jsp、/user/login时会执行过滤方法
2)路径匹配:
/user/*/*/user/路径下的所有请求都会被拦截。/*表示拦截系统的所有请求,包括静态资源文件。
3)扩展匹配:
*.jsp*.action所有后缀名为.jsp.action的请求都会被拦截。
注意:/login/*.jsp的写法是错误的,只能是以上三种形式中的任意一种。新形式无法组合。
*jsp也是错误的,扩展名匹配必须是后缀名
4)多种url-pattern配置
以上三种形式相对有限,但是可以配置多种url-pattern,所以这三种组合基本上可以解决所有问题。
多Filter执行顺序
如果同一个资源有多个过滤器对其进行拦截,则拦截顺序以web.xml中配置的顺序为准
执行流程图如下
请求处理完之后总会回来执行doFilter之后的方法。
HttpServletWrapper和HttpServletResponseWrapper
定义ServletAPI提供了一个HttpServletRequestWrapper类来包装原始请求对象。HttpServletRequestWrapper类实现HttpServletRequest接口中的所有方法。这些方法的内部实现仅调用包装的请求对象。对应方法
//包装类实现ServletRequest接口。publicclassServletRequestWrapperImplementsServletRequest{//包装的ServletRequest对象privateServletRequestrequest;//构造函数传入ServletRequest实现类对象publicServletRequestWrapper(ServletRequestrequest){if(request==null){thrownewIllegalArgumentException('Requestcanbenull');}}this.request=请求;}//通过调用被包装的成员变量的方法来具体实现ServletRequest的方法:公共对象getAttribute(Stringname){returnthis.request.getAttribute(name);}publicEnumerationgetAttributeNames(){returnthis.request.getAttributeNames();}//.}类似的ServletAPI也提供了一个HttpServletResponseWrapper类来包装原始的响应对象
作用用于修改或增强HttpServletRequest或HttpServletResponse的方法。
公共类MyHttpServletRequest扩展了HttpServletRequestWrapper{公共MyHttpServletRequest(HttpServletRequest请求){超级(请求);}@OverridepublicStringgetParameter(Stringname){Stringval=super.getParameter(name);if(val!=nullval.contains('操')){val=val.replace('操','****');返回值;}}推荐博客
程序员除了写代码之外还能如何赚取另一份薪水?
使用Filter中,使用MyHttpServletRequest替换传入的HttpServletRequest
HttpServletRequestreq=newMyHttpServletRequest(request);filterChain.doFilter(req,response);此时到达目标Servlet或JSP的HttpServletRequest实际上是MyHttpServletRequest