一、概念
Filter
是Java Web
的三大组件之一。Java Web
三大组件分别是Servlet
、Filter
、Listener
。
Filter
的作用一般用于完成通用的操作。例如:登录验证、统一编码处理、敏感字符过滤…在实际开发中,过滤器就是对Web资源进行拦截,做一些处理后再交给下一个过滤器或servlet处理,通常都是用来拦截request
进行处理,或者对返回的response
进行拦截处理。其处理流程见下图:
拦截request
可以简单理解为,在客户端向后端发送请求时,我们需要对其请求加一些"修饰",将"修饰"后的请求带到后端。其中这个"修饰"是需要在这个请求的过程中完成的,这里因为是通用操作,可能是对所有的request
进行"修饰",所以并没有在客户端进行编写,否则当再加入一个request
请求时,我们又要编写对应的规则,因此我们借用过滤器在请求过程中,对我们需要改写的request
进行"修饰"。
其中,这里的"修饰"就可以理解为在原有的request
请求中,再加入一些"修改"。例如:在Servlet中过多字符集编码发生变化需要修改时,你是选择对每个Servlet
都进行修改,还是会选择一个通用的"规则",来自动判断帮我们进行修改呢?而这里通用的"规则"就是Filter
,我们可以把这些通用的字符集编码配置等工作放在Filter
中,由Filter
在请求过程中或返回过程中帮我们来实现。
二、过滤器的快速使用
其中过滤增强的方法写在doFilter
中。
@WebFilter("/*") //访问所有资源之前,都会执行该过滤器
public class FilterDemo1 implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
'''对request请求消息进行增强'''
filterChain.doFilter(servletRequest,servletResponse); // 修饰完以后进行放行
'''放行回来后,对response响应消息的增强'''
}
@Override
public void destroy() {
}
}
filterChain.doFilter(servletRequest,servletResponse)
用于对我们的请求进行放行。doFilter
中的参数就是request
,response
;带着请求消息和响应消息。
2.1 执行流程
在doFilter
放行前,对request
请求进行增强,然后带着增强后的requeset
进入到doFilter
;从doFilter
方法出来后,将后台返回的response
进行增强,返回给前端。
2.2 过滤器生命周期方法
init
:在服务器启动后,会创建Filter
对象,然后调用init
方法。只执行一次。用于加载资源。doFilter
:每一次请求被拦截资源时,会执行。执行多次。destroy
:在服务器关闭后,Filter
对象被销毁。如果服务器是正常关闭,则会执行destroy
方法。只执行一次。用于释放资源。
三、过滤器配置
3.1 web.xml配置
<filter>
<filter-name>demo1</filter-name>
<filter-class>cn.itcast.web.filter.FilterDemo1</filter-class>
</filter>
<filter-mapping>
<filter-name>demo1</filter-name>
<!-- 拦截路径 -->
<url-pattern>/*</url-pattern>
</filter-mapping>
3.2 拦截路径设置
- 具体资源路径: /index.jsp 只有访问index.jsp资源时,过滤器才会被执行
- 拦截目录: /user/* 访问/user下的所有资源时,过滤器都会被执行
- 后缀名拦截: *.jsp 访问所有后缀名为jsp资源时,过滤器都会被执行
- 拦截所有资源:/* 访问所有资源时,过滤器都会被执行
3.3 注解配置
通过设置dispatcherTypes属性,设置拦截方式,即资源被访问的方式。
REQUEST
:默认值。浏览器直接请求资源FORWARD
:转发访问资源(只有在转发访问资源时,才会被拦截器所拦截,直接访问反而不会了)INCLUDE
:包含访问资源ERROR
:错误跳转资源ASYNC
:异步访问资源
以上是数组的形式,可以同时同时填写多个条件。
在web.xml
中的配置在:
设置<dispatcher></dispatcher>
标签即可
3.4 过滤器链
即同时配置多个过滤器,多个过滤器对同一路径进行拦截时。
类似于栈的形式先进后出,例如有两个过滤器 A和B。
执行顺序即为:过滤器A --> 过滤器B --> 执行资源 --> 过滤器B --> 过滤器A
执行资源前的是对request
的增强,执行资源后的是对response
的增强
过滤器执行的先后顺序:
- 注解配置:按照类名的字符串比较规则比较,值小的先执行.
- 如: AFilter 和 BFilter,AFilter就先执行了。
- web.xml配置: <filter-mapping>谁定义在上边,谁先执行.
四、过滤器基本案例实战
4.1 登录验证(权限控制)
对这一讲中–Java初试MVC及三层架构的登录进行验证。
要求:
- 如果已经登录,则直接放行。
- 如果没有登录,则跳转到登录页面,并提示信息。
思路:
设置LoginFilter
。判断当前用户是否登录(判断Session
中是否有User
)。
- 如果用户已经登录,则对其进行放行
- 如果没有登录,提示用户进行先进行登录。
**注意:**先排除是否是登录相关的资源。
- 如果是,直接放行;
- 不是,判断是否登录。
代码实现:
登录权限的案例代码实现@WebFilter("/*")
public class LoginFilter implements Filter {
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
// 强转 -- 转换成子接口HttpServletRequest;也可以将ServletResponse转换成子接口HttpServletResponse
HttpServletRequest request = (HttpServletRequest) req;
String uri = request.getRequestURI(); // 获取请求路径
// 排除不需要过滤的资源路径
if (uri.contains("/login.jsp")