Filter和Listener
1.过滤器Filter
客户端与服务器的请求与响应进行过滤,拦截或修改。
例如:实现权限访问控制,过滤敏感词汇,压缩响应信息功能。
Servlet API提供了Filter接口,实现该接口,称为过滤器。
步骤如下:
- 编写Java类实现Filter接口
- 在doFilter核心方法中编写拦截逻辑
- 设置拦截路径
手写过滤器
public class FirstFilter implements Filter {
//init :初始化方法
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("FirstFilter的init方法..." + this.hashCode());
}
//doFilter: 执行过滤,核心方法
// request:请求对象
// response:响应对象
// chain:过滤器链
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
System.out.println("FirstFilter的doFilter方法...放行之前" + this.hashCode());
//放行(如果有下一个过滤器,则执行下一个过滤器,没有则执行目标资源)
chain.doFilter(request, response);
System.out.println("FirstFilter的doFilter方法...放行之后" + this.hashCode());
}
//destroy: 销毁
@Override
public void destroy() {
System.out.println("FirstFilter的destroy方法..." + this.hashCode());
}
}
配置访问路径:
① 配置XML文件
<!--配置过滤器-->
<!--filter标签-->
<filter>
<filter-name>FirstFilter</filter-name>
<filter-class>com.qf.web.filter.FirstFilter</filter-class>
</filter>
<!--filterMapping-->
<filter-mapping>
<filter-name>FirstFilter</filter-name>
<!--拦截(过滤)路径-->
<!--精确拦截-->
<url-pattern>/welcome.jsp</url-pattern>
</filter-mapping>
拦截路径:
<!--filterMapping-->
<filter-mapping>
<filter-name>FirstFilter</filter-name>
<!--精确拦截-->
<url-pattern>/welcome.jsp</url-pattern>
<!--后缀拦截-->
<url-pattern>*.jsp</url-pattern>
<!--通配符拦截 /aaa/* , /*-->
<url-pattern>/images/*</url-pattern>
<!--filter 不能用 /-->
</filter-mapping>
配置参数:
<filter>
<init-param>
<param-name>username</param-name>
<param-value>张三</param-value>
</init-param>
</filter>
获取参数:
//init :初始化方法
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("FirstFilter的init方法..." + this.hashCode());
String username = filterConfig.getInitParameter("username");
System.out.println(username);
}
②注解配置
@WebFilter(filterName = "First",value = "/welcome.jsp",initParams = {@WebInitParam(name = "username",value = "李四")})
public class FirstFilter implements Filter {}
当XML与注解都配置,且是对同一个进行过滤时两个都会执行。执行顺序如下:
IDEA创建过滤器
若没有可以看看下面设置有没有点,打开的下面界面的快捷键Ctrl+Shift+S
@WebFilter(filterName = "SecondFilter",value = "/welcome.jsp")
public class SecondFilter implements Filter {
@Override
public void destroy() {
System.out.println("SecondFilter的destroy方法..."+this.hashCode());
}
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
System.out.println("SecondFilter的doFilter方法...放行之前"+this.hashCode());
chain.doFilter(req, resp);
System.out.println("SecondFilter的doFilter方法...放行之前"+this.hashCode());
}
@Override
public void init(FilterConfig config) throws ServletException {
System.out.println("SecondFilter的init方法..."+this.hashCode());
}
}
若用注解的方式创建的Filter,且对同一个进行过滤,执行的顺序按照过滤器名称字符串的顺序。
1.2.过滤器链
客户端对服务器发出请求,执行目标资源先执行多个过滤器,称之为过滤器链。
执行流程:
- 当第一个Filter的doFilter方法被调用时,服务器会创建一个代表Filter链的chain对象传递给该方法。在doFilter方法中,如果调用了chain对象的doFilter方法,则服务器会检查chain对象中是否还有filter,如果有,则调用第二个filter,如果没有,则调用目标资源。
1.3Filter优先级
- 若是XML配置的按由上到下的顺序。
- 若是注解配置的按类名称字符串顺序。
- XML配置高于注解的方式
- 同时创建会创建多个过滤器对象
1.4 过滤器经典应用
1.禁止浏览器缓存动态页面
以前浏览器会使用缓存,有刷新不更新的问题。
方式一:以下标签禁用缓存。
- <meta http-equiv="pragma" content="no-cache" /> //批注不缓存
- <meta http-equiv="cache-control" content="no-cache" /> //缓存控制不缓存
- <meta http-equiv="expires" content="0" /> //过期时间0
<%@ page contentType="text/html;charset=UTF-8" language="java"
%>
<html>
<head>
<title>Title</title>
<meta http-equiv="pragma" content="no-cache" />
<meta http-equiv="cache-control" content="no-cache" />
<meta http-equiv="expires" content="0" />
</head>
<body>
<h2>当前时间:<%=new Date().toString()%></h2>
</body>
</html>
方式二:添加过滤器
@WebFilter("*.jsp")
public class NoCacheFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
throws IOException, ServletException {
//放行
HttpServletResponse response = (HttpServletResponse) resp;
response.setHeader("pragma", "no-cache");
response.setHeader("cache-control", "no-cache");
response.setDateHeader("expires", 0);
chain.doFilter(req, resp);
}
@Override
public void destroy() {
}
}
设置缓存有效期:
@WebFilter(filterName = "CacheFilter", value = "*.jpg")
public class CacheFilter implements Filter {
@Override
public void destroy() {
}
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
throws ServletException, IOException {
HttpServletResponse response = (HttpServletResponse) resp;
response.setHeader("cache-control", "max-age=600");//10分钟
response.setDateHeader("expires", System.currentTimeMillis() + 600000);
chain.doFilter(req, resp);
}
@Override
public void init(FilterConfig config) throws ServletException {
}
}