Filter过滤器
最近学习到了Servlet过滤器,记录一下
- 过滤器是一个驻留在服务器中的WEB组件(三大组件之一),他可以截取客户端和WEB资源(Servlet、JSP、HTML页面等)之间的请求和响应信息。
- 过滤器可以在WEB资源收到请求之前,浏览器收到响应之前,对请求和响应信息做一些相应的操作。
- 在一个WEB应用中可以部署多个过滤器,多个过滤器就组成了一个过滤器链,请求和响应必须在经过多个过滤器后才能到达目标。
- 通俗的说 实现了Filter接口的类都是过滤器。
- 对当前的请求进行过滤,判断是否符合规则,是否具备访问目标资源的条件。若符合,则放行;若不符合,则进行其他操作
过滤器不是必须将请求传送到下一个过滤器(或WEB资源),也可以自己来处理请求,发送响应
Filter的生命周期
由Tomcat管理其生命周期,且Filter比Servlet先加载
-
init()方法用于初始化Filter
-
doFilter()作用和service()方法类似,是过滤请求和响应的主要方法。
-
destroy()用于在Filter对象被销毁前做一些收尾工作。如:释放资源等。
即:
构造器(实例化):创建Filter实例是调用,Filter实例服务器一旦启动就会被创建
初始化:实例化之后紧接着初始化,服务器启动的过程中只执行一次
执行过滤:只要是需要进行过滤的请求,都会执行此方法
销毁:服务器关闭时销毁
Filter相关接口
一、Filter接口,实现Filter需要实现该接口
-
init()方法用于初始化Filter
-
doFilter()作用和service()方法类似,是过滤请求和响应的主要方法。
-
destroy()用于在Filter对象被销毁前做一些收尾工作。如:释放资源等。
二、FilterConfig对象在服务器调用init()方法时传递进来
-
getFilterName() 获取Filter的名字
-
getServletContext() 获取ServletContext对象(即application)
-
getInitParameter() 获取Filter的初始化参数
-
getInitParameterNames() 获取所有初始化参数的名字
三、FilterChain对象是在doFilter()方法被调用时作为参数传递进来的。
- doFilter()方法用于调用Filter链上的下一个过滤器,如果当前过滤器为最后一个过滤器则将请求发送到目标资源。
Filter的创建和使用
- 创建&使用
public class FirstFilter implements Filter {
//实现三个抽象方法...
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
// 放行操作,调用链上的下一个过滤器
filterChain.doFilter(servletRequest, servletResponse);
}
在过滤器中,执行过滤的方法doFilter(),其中就是对当前请求的过滤过程,因此一定要在需要放行时使用chain.doFilter()实现放行功能
- 注册(个人比较习惯使用xml注册的方式,也可以在创建filter时勾选注解的方式注册)
方式一:在web.xml中进行注册
<filter>
<filter-name>FirstFilter</filter-name>
<filter-class>com.atguigu.filter.FirstFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>FirstFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
filter-name 指定的是过滤器的名字
filter-class 指定的是过滤器的全类名
url-pattern 指定的是需要过滤器处理的请求地址,
/
为当前工程下,* 为所有资源
方式二:在IDEA创建时勾选注解
在IDEA中创建FIlter
Filter的过滤规则
- url-pattern设置filter的过滤规则
1、精确匹配:在url-pattern中设置某个资源的完整路径,此时过滤器就会对路径指定的资源进行过滤
<url-pattern>/test/test.jsp</url-pattern>
<url-pattern>/index.jsp</url-pattern>
2、路径匹配(通用匹配):在url-pattern中使用*表示所有资源
<url-pattern>/*</url-pattern>
<url-pattern>/test/*</url-pattern>
3、后缀匹配:在url-pattern中使用" *.后缀名 "表示只能对某种后缀的资源进行过滤
以上三种过滤规则不能混合使用,但是一个filter可以有多个url-pattern
4、servlet匹配:通过filter-mapping中的servlet-name,对servlet-name所对应的servlet进行过滤
<filter-mapping>
<filter-name>LoginFilter</filter-name>
<servlet-name>OrderClientServlet</servlet-name>
</filter-mapping>
多个Filter的执行顺序
执行顺序多用于springMVC
多个Filter的doFilter()执行顺序只跟在web.xml中的注册顺序有关,其实是按照filter-mapping的顺序执行,越靠前,越先执行
多个Filter的初始化和销毁的方法跟web.xml中注册的顺序没有关系,不需要考虑
多个Filter中执行过滤的方法doFIlter(),其中的内容,放行之前按顺序执行,放行之后的代码按照倒序执行【即栈状态】
FIlter使用实例
业务场景:用户需要登录才能对购物车中的商品进行结账,需要通过FIlter进行请求过滤,当session保存有用户信息,才会对该请求放行。
1、封装了原始的FIlter,因为只需要关注doFIlter()内的业务逻辑,不需要关注filter的初始化、销毁。同时转换ServletRequest、ServletResponse —>HttpServletRequest、HttpServletResponse
public abstract class HttpFilter implements Filter {
@Override
public void destroy() {
}
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
doFilter(request,response,chain);
}
public abstract void doFilter(HttpServletRequest request,HttpServletResponse response,FilterChain chain) throws ServletException, IOException;
@Override
public void init(FilterConfig config) throws ServletException {
}
}
2、继承HttpFilter ,只需要在doFIlter内写业务逻辑
public class LoginFilter extends HttpFilter {
@Override
public void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
HttpSession session = request.getSession();
Object user = session.getAttribute("user");
if (user == null){
// 未登录,使用请求域+转发跳转到login页面,并且在界面中提示用户需要登录
request.setAttribute("errorMsg","结账功能需要登录");
request.getRequestDispatcher("/pages/user/login.jsp").forward(request,response);
}else {
// 已登录
chain.doFilter(request,response);
}
}
}