过滤器和监听器
Servlet过滤器和监听器
Filter过滤器概述
当客户端访问服务器的资源时,过滤器可以将请求拦截下来,完成一些特殊的功能。举个例子帮助大家理解:比如2020年初在爆发了新冠病毒疫情,为了防止病毒扩算到全国,武汉市宣布封城,所有交通渠道限制通行,在各个出入口设卡拦截,只有体温正常的医务人员和急救物资才能进入城区。这里武汉市各个出入口的关卡,起到的就是过滤器的作用。
在程序中是同样的道理,比如用户在访问服务器资源时只允许登录过的用户才能正常访问。这里登录校验起到的就是过滤器的作用。除了登录校验,在程序中过滤器的用处还有统一编码处理,铭感词汇过来
过滤器快速入门
过滤器步骤
1. 定义一个类,实现接口Filter
2. 复写方法
3. 配置拦截路径
web.xml配置
注解配置
代码实现
// /*: 访问所有资源之前,都会执行该过滤器
@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 {
System.out.println("filterDemo1被执行了....");
//放行
filterChain.doFilter(servletRequest,servletResponse);
}
@Override
public void destroy() {
}
}
浏览器访问 http://localhost:8080/FilterListener/index.jsp 查看控制台输出结果,会发现在过滤器执行了两次。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nUEd2lBx-1684336061687)(/Volumes/T7 Shield/assets/8、Filter和Listener/20211210153143.png)]
过滤器web配置
上面的案例采用web.xml方式进行配置效果是一样的
<filter>
<filter-name>FilterDemo1</filter-name>
<filter-class>com.itheima.FilterDemo1</filter-class>
</filter>
<filter-mapping>
<filter-name>FilterDemo1</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
浏览器访问 http://localhost:8080/FilterListener/index.jsp 查看控制台输出结果,会发现在过滤器执行了两次。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9ObiION5-1684336061687)(/Volumes/T7 Shield/assets/8、Filter和Listener/20211210153152.png)]
过滤器执行流程
1. 执行过滤器
2. 执行放行后的资源
3. 回来执行过滤器放行代码下边的代码
过滤器生命周期
1. init:在服务器启动后,会创建Filter对象,然后调用init方法。只执行一次。用于加载资源
2. doFilter:每一次请求被拦截资源时,会执行。执行多次
3. destroy:在服务器关闭后,Filter对象被销毁。如果服务器是正常关闭,则会执行destroy方法。只执行一次。用于释放资源
过滤器配置详解
拦截路径配置
1. 具体资源路径: /index.jsp
只有访问index.jsp资源时,过滤器才会被执行
2. 拦截目录: /user/*
访问/user下的所有资源时,过滤器都会被执行
3. 后缀名拦截: *.jsp
访问所有后缀名为jsp资源时,过滤器都会被执行
4. 拦截所有资源:/*
访问所有资源时,过滤器都会被执行
拦截方式配置
【注解配置】:设置dispatcherTypes属性
1. REQUEST:默认值。浏览器直接请求资源
2. FORWARD:转发访问资源
3. INCLUDE:包含访问资源
4. ERROR:错误跳转资源
5. ASYNC:异步访问资源
【web.xml配置】
设置<dispatcher></dispatcher>标签即可
看下面的注解配置的举例
//直接请求http://localhost:8080/FilterListener/index.jsp时,被过滤器拦截
@WebFilter(value = "/index.jsp",dispatcherTypes = DispatcherType.REQUEST)
//请求转发到http://localhost:8080/FilterListener/index.jsp,被过滤器拦截
@WebFilter(value = "/index.jsp",dispatcherTypes = DispatcherType.FORWARD)
过滤器链(配置多个过滤器)
执行顺序:如果有两个过滤器:过滤器1和过滤器2
1. 过滤器1
2. 过滤器2
3. 资源执行
4. 过滤器2
5. 过滤器1
过滤器先后顺序问题:
1. 注解配置:按照类名的字符串比较规则比较,值小的先执行
* 如: AFilter 和 BFilter,AFilter就先执行了。
2. web.xml配置: <filter-mapping>谁定义在上边,谁先执行
案例1:登录验证
需求:
1. 访问UserManager案例的资源。验证其是否登录
2. 如果登录了,则直接放行。
3. 如果没有登录,则跳转到登录页面,提示"您尚未登录,请先登录"
//设置拦截路径为所有路径
@WebFilter("/*")
public class LoginFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//获取请求的uri
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
String uri = request.getRequestURI();
//当uri是请求登录、js、css、font、验证码资源时放行
if(uri.contains("/login.jsp")||uri.contains("/LoginServlet")||uri.contains("/js")||uri.contains("css")||uri.contains("fonts")||uri.contains("/VerificationCodeServlet")){
filterChain.doFilter(request,servletResponse);
}else{
//否则,判断是否登录
Object loginUser = request.getSession().getAttribute("loginUser");
if(loginUser==null){
//如果没有登录,跳转到登录页面
response.sendRedirect(request.getContextPath()+"/login.jsp");
}else {
//如果有登录,直接放行
filterChain.doFilter(request,servletResponse);
}
}
}
@Override
public void destroy() {
}
}
案例2:敏感词汇过滤
* 需求:
1. 对users案例录入的数据进行敏感词汇过滤
2. 敏感词汇参考《敏感词汇.txt》
3. 如果是敏感词汇,替换为 ***
* 分析:
1. 对request对象进行增强。增强获取参数相关方法
2. 放行。传递代理对象
Servlet监听器
Listener监听器是web的三大组件之一。
* 事件监听机制
* 事件 :一件事情
* 事件源 :事件发生的地方
* 监听器 :一个对象
* 注册监听:将事件、事件源、监听器绑定在一起。 当事件源上发生某个事件后,执行监听器代码
ServletContextListener接口
ServletContextListener用来监听ServletContext对象的在创建和销毁时所做的事情。
public void contextDestroyed(ServletContextEvent sce)
ServletContext对象被销毁之前会调用该方法
public void contextInitialized(ServletContextEvent sce)
ServletContext对象创建后会调用该方法
步骤
1. 定义一个类,实现ServletContextListener接口
2. 复写方法
3. 配置方式
1. web.xml
<listener>
<listener-class>cn.itcast.web.listener.ContextLoaderListener</listener-class>
</listener>
* 指定初始化参数<context-param>
2. 注解:
* @WebListener