JavaWeb三大组件
- Servlet
- Listener
- Filter(过滤器)
过滤器作用
过滤器会在服务器启动时创建,在一组资源(jsp、servlet、css、html等等)之前执行。
拦截请求,判断决定是否让请求到达目标资源。
虽然在servlet中也可以判断是否接收请求,但是只能判断各自servlet的请求,而且需要在每个接收请求的servlet中重复写判断代码。而filter就可以统一拦截,统一判断。
过滤器的应用场景:
- 执行目标资源之前做预处理工作,例如设置编码,这种试通常都会放行,只是在目标资源执行之前做一些准备工作;
- 通过条件判断是否放行,例如校验当前用户是否已经登录,或者用户IP是否已经被禁用;
- 在目标资源执行后,做一些后续的特殊处理工作,例如把目标资源输出的数据进行处理(回程拦截)
编写Filter
写一个类实现Filter接口
void init(FilterConfig)
* 创建之后,马上执行;Filter会在服务器启动时就创建
FilterConfig-->与ServletConfig相似
* 获取初始化参数:getInitParameter()
* 获取过滤器名称:getFilterName()
* 获取appliction:getServletContext()
void destory()
* 销毁之前执行!在服务器关闭时销毁
void doFilter(ServletRequest,ServletResponse,FilterChain)
* 每次过滤时都会执行
FilterChain
* doFilter(ServletRequest, ServletResponse):放行(就相当于调用了目标Servlet的service()方法!)
在web.xml中配置(idea中可以直接在注解@WebFilter中配置)
web.xml
<!--filter中的filter-name与filter-mapping中的filter-name保持相同
filter-class:完整的类路径
url-pattern:拦截的文件 /* 全部文件,也可以指定文件-->
<filter>
<filter-name>AFilter</filter-name>
<filter-class>cn.edu.stu.AFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>AFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
注解中配置
@WebFilter(filterName = "BFilter",urlPatterns = "/*")
实例代码
AFilter.java
public class AFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
//启动服务器时执行一次
System.out.println("AFilter执行了");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//每次过滤都会执行
System.out.println("AFilter#start");
//放行
filterChain.doFilter(servletRequest,servletResponse);
System.out.println("AFilter#end");
}
@Override
public void destroy() {
//服务器关闭之前销毁
System.out.println("AFilter销毁了");
}
}
web.xml
<!--filter中的filter-name与filter-mapping中的filter-name保持相同
filter-class:完整的类路径
url-pattern:拦截的文件 /* 全部文件,也可以指定文件
也可以使用servlet-name 来指定访问的servlet名字(可以使用多个servlet-name)-->
<filter>
<filter-name>AFilter</filter-name>
<filter-class>cn.edu.stu.AFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>AFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
访问项目中的任何文件,都会调用AFilter的doFilter()方法
多过滤器
建立BFilter.java
//使用注解的方式注册
@WebFilter(filterName = "BFilter",urlPatterns = "/session/add.jsp")
public class BFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
//启动服务器时执行一次
System.out.println("BFilter执行了");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//每次过滤都会执行
System.out.println("BFilter#start");
filterChain.doFilter(servletRequest,servletResponse);
System.out.println("BFilter#end");
}
@Override
public void destroy() {
//服务器关闭之前销毁
System.out.println("BFilter销毁了");
}
}
这里可以看到对于BFilter中拦截的内容范围更小,这个时候启动项目,访问add.jsp文件。
BFilter#start
BFilter#start
BFilter#end"
BFilter#start
通过结果得到:执行目标资源,或是执行下一个过滤器,如果有下一个过滤器就行下一个过滤器,否则执行目标资源。
对于多个过滤器执行顺序
- 如果在web.xml中配置,根据<filter-mapping>的先后顺序执行。
- 如果在idea的webFilter的注解中注册,根据过滤器的名字的字母顺序来执行(例如AFilter>BFilter>CFilter),但是这种方式不一定每次都准确。如果有严格要求就是用在web.xml中配置
四种拦截方式
- 请求:REQUEST(默认)
- 转发:FORWARD
- 包含:INCLUDE
- 错误:REEOR
配置方式
(1)web.xml 在<filter-mapping>中进行配置!
<filter>
<filter-name>AFilter</filter-name>
<filter-class>cn.edu.stu.AFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>AFilter</filter-name>
<url-pattern>/BServlet</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
<dispatcher>INCLUDE</dispatcher>
<dispatcher>ERROR</dispatcher>
</filter-mapping>
(2)idea中注解中配置
@WebFilter(filterName = "BFilter",urlPatterns = "/BServlet",dispatcherTypes = DispatcherType.FORWARD)