Filter入门
什么是Filter
Filter被称作过滤器或者拦截器,其基本功能就是对Servlet容器调用Servlet的过程进行拦截,从而在Servlet进行响应处理前后实现一些特殊功能。
当浏览器访问服务器中的目标资源时,会被Filter拦截,在Filter中进行预处理操作,然后再将请求转发给目标资源。当服务器接收到这个请求后会对其进行响应,在服务器处理响应的过程中,也需要先将响应结果发送给拦截器,在拦截器中对响应结果进行处理后,才会发送给客户端。
常用实例:自动登录,解决全站乱码,屏蔽非法文字,进行响应数据压缩等等
Filter过滤器就是一个实现了javax.servlet.Filter接口的类,
在javax.servlet.Filter接口中定义了三个方法
init(FilterConfig filterConfig)
doFilter(ServletRequest request, ServletResponse response,FilterChain chain)
destroy()
Filter映射
Filter拦截的资源需要在web.xml文件中进行配置,即Filter映射。
Filter的映射方式可分为两种
使用通配符“*”来实现让过滤器拦截所有的请求访问
<filter-mapping>元素中有一个特殊的子元素<dispatcher>,该元素用于指定过滤器所拦截的资源被Servlet容器调用的方式
<dispatcher>元素的值共有四个:REQUEST、INCLUDE、FORWARD、ERROR。
Filter链
在一个Web应用程序中可以注册多个Filter程序,每个Filter程序都可以针对某一个URL进行拦截。如果多个Filter程序都对同一个URL进行拦截,那么这些Filter就会组成一个Filter链(也叫过滤器链)。
Filter链用FilterChain对象来表示,FilterChain对象中有一个doFilter()方法,该方法作用就是让Filter链上的当前过滤器放行,请求进入下一个Filter
FilterConfig接口
为了获取Filter程序在web.xml文件中的配置信息,Servlet API提供了一个FilterConfig接口,该接口封装了Filter程序在web.xml中的所有注册信息,并且提供了一系列获取这些配置信息的方法。
方法
String getFilterName ()getFilterName()方法用于返回在web.xml文件中为Filter所设置的名称,也就是返回<filter-name>元素的设置值。
ServletContext getServletContext()getServletContext()方法用于返回FilterConfig对象中所包装的ServletContext对象的引用。
String getInitParameter(String name)getInitParameter(String name)方法用于返回在web.xml文件中为Filter所设置的某个名称的初始化参数值,如果指定名称的初始化参数不存在,则返回null。
Enumeration getInitParameterNames()getInitParameterNames()方法用于返回一个Enumeration集合对象,该集合对象中包含在web.xml文件中为当前Filter设置的所有初始化参数的名称。
生命周期
1、实例化(new)
Web 容器启动时,即会根据 web.xml 中声明的 filter 顺序依次实例化这些 filter
2、初始化
1、实例化和初始化的操作只会在容器启动时执行,而且只会执行一次。
2、 Web 容器调用 init(FilterConfig) 来初始化过滤器。
3、容器在调用该方法时,向过滤器传递 FilterConfig 对象,
4、利用 FilterConfig 对象可以得到 ServletContext 对象,以及在 web.xml 中配置的过滤器的初始化参数
5、在这个init(FilterConfig)方法中,可以抛出 ServletException 异常,通知容器该过滤器不能正常工作。此时的 Web 容器启动失败,整个应用程序不能够被访问
3、过滤
每次访问被拦截目标资源,过滤器中的doFilter的方法就会执行
4、销毁
当服务器关闭(或应用卸载)的时候,服务器就会销毁Filter对象.
应用案例--Filter实现用户自动登录
案例分析
1、登录的功能的基础上实现的自动登录.
2、在登录的页面中勾选自动登录的复选框.点击提交.
3、在提交的Servlet中,在登录成功的地方记住用户名和密码.
4、在下次访问首页的时候带着Cookie过来.
5、编写一个过滤器:
1、判断用户是否已经登录了,如果已登陆执行第7步
2、如果未登录获得Cookies的信息
3、查找指定的名称的Cookie.
4、拿到Cookie以后获得用户名和密码
5、调用业务层,在去数据库进行查询
6、能查询到,将用户的信息存入到session,
7、放行
案例实现提要
1、创建项目,创建数据库、表
2、导入jar、页面资源、工具类
3、编写LoginServlet、service、dao、javaBean等完成登陆功能
4、编写过滤器
1、判断用户是否已经登陆如果已登陆执行第5步
2、如果没有登陆获得相应的cookie,从cookie中获得用户信息
3、调用service层的服务完成登陆
4、将用户信息保存到session作用域中
5、放行
Filter高级应用
什么是包装类
Filter过滤器可以获取到代表用户请求和响应的request、response对象。可是如果想对request和response对象中的任何信息进行修改,则需要通过包装类来实现。
在Servlet API中,提供了HttpServletRequestWrapper和HttpServletResponseWrapper两个类,它们分别是request和response对象的包装类。
装饰设计模式
HttpServletRequestWrapper和HttpServletResponseWrapper都采用了装饰设计模式。所谓装饰设计模式,指的是通过包装类的方式,动态增强某个类的功能。
特点
包装类要和被包装对象实现同样的接口
包装类持有一个被包装对象
包装类在实现接口的过程中,对于不需要包装的方法原封不动地调用被包装对象的方法来实现,对于需要包装的方法自己实现。
Filter实现统一全站编码
在Filter中对获取到的请求和响应消息进行编码,从而统一全站的编码方式。
Filter实现动态页面静态化
在实际开发中,有时为了提高程序性能、减轻数据库访问压力以及搜索引擎的优化,可以使用Filter实现动态页面静态化。
当客户端首次访问页面时,Filter会自定义response输出缓存HTML源码。当客户端第二次访问页面时,就会直接访问静态页面,这样避免访问数据库。
核心API
Filter
init(FilterConfig)
doFilter(ServletRequest, ServletResponse, FilterChain)
destroy()
FilterConfig
getServletContext()
getInitParameter(String)
getInitParameterNames()
FilterChain
doFilter(ServletRequest, ServletResponse, FilterChain)
配置
@WebFilter
urlPatterns
dispatcherTypes
REQUEST
FORWARD
INCLUDE
ASYNC
ERROR
asyncSupported
web.xml
<filter> -> <filter-name> / <filter-class>
<filter-mapping> -> <filter-name> / <url-pattern> / <servlet-name> / <dispatcher>
案例:全局解决中文乱码问题
1、案例介绍
1、在之前编写的servlet都出现了,那就是编码处理,且之前的程序GET请求需要单独处理
2、在实际开发中,需要统一处理编码
3、本案例将以上两个问题使用过滤器统一解决。也就是在servlet前后执行特定功能
案例使用到的相关技术
装饰者模式
1、作用
设计模式:专门为解决某一类问题,而编写的固定格式的代码。
2、结构
装饰者固定结构:接口A,已知实现类C,需要装饰者创建代理类B
1、创建类B,并实现接口A
2、提供类B的构造方法,参数类型为A,用于接收A接口的其他实现类(C)
3、给类B添加类型为A成员变量,用于存放A接口的其他实现类
4、增强需要的方法
5、实现不需要增强的方法,方法体重调用成员变量存放的其他实现类对应的方法
2、案例分析
1、post方式的乱码处理
1、在filter中设置一下request.setCharacterEncoding("UTF-8");
2、放行
2、get方式的乱码处理
1、在过滤器放行之前通装饰者设计模式方法对HttpServletRequest进行增强
2、放行:chain.dofilter(proxyrequest,response),参数中的请求对象为增强后的request对象。
3、案例实现
1、在原来项目完成的基础上,创建过滤器
2、设置服务解析post请求数据的编码集
request.setCharacterEncoding("UTF-8");
3、使用装饰者模式包装HttpServletRequest
1、在装饰类中判断请求方式是post还是get
2、如果是get提交,进行乱码处理
1、String arg=request.getParameter(参数名);
2、arg=new String(art.getBytes("ISO-8859-1"),"UTF-8")
3、如果是post无需处理
4、将乱码处理后的结果返回