JavaWeb中的异卵双胞胎—监听器与过滤器

简介: 监听器与过滤器相关介绍以及代码实现流程(图文并茂)

@TOC

监听器

作用

监听request、session、application三个域对象的创建,销毁和数据的变更

使用

### 1、创建一个普通java类实现指定的接口

public class MyListener implements ServletRequestListener{
    //监听Request对象的创建和销毁
    @Override
    public void requestDestroyed(ServletRequestEvent arg0) {
        System.out.println("requset对象被销毁了");
        
    }
    @Override
    public void requestInitialized(ServletRequestEvent arg0) {
        System.out.println("request对象被创建了");
        
    }
    }

### 2、在web.xml进行配置,使其生效(放在dispalyname标签的上面)

 <!-- 监听器的配置 -->
  <listener>
      <listener-class>监听器所在java类的全限定类名(包名+类名)</listener-class>
  </listener>

示例:
在这里插入图片描述

监听器可以继承的的接口

1、ServletRequestListener

监听request的创建和销毁
 requestInitialized(ServletRequestEvent sre)
 requestDestroyed(ServletRequestEvent sre)

形参:

ServletRequestEvent可以获取当前监听到的request对象,对request对象的中的资源进行操作。

2、 ServletRequestAttributeListener

监听request作用域数据变更(添加移除替换)
attributeAdded(ServletRequestAttributeEvent srae)
attributeRemoved(ServletRequestAttributeEvent srae)
attributeReplaced(ServletRequestAttributeEvent srae)

形参:

ServletRequestAttributeEvent:可以获取当前被监听到的request中的数据。
getName(): 返回监听到的数据的键和getValue()返回监听的到的数据的值。

3、HttpSessionListener

监听session的创建和销毁
sessionCreated(HttpSessionEvent se)
sessionDestroyed(HttpSessionEvent se)

形参:

获取当前被监听到的session对象
### 4、HttpSessionAttributeListener
监听session的作用域数据变更
    attributeAdded(HttpSessionBindingEvent event)
    attributeRemoved(HttpSessionBindingEvent event)
    attributeReplaced(HttpSessionBindingEvent event)

形参:

获取当前监听到的session中的数据 getName()返回数据的键名
getValue()返回数据的值

5、ServletContextListener

监听application对象的创建和销毁
contextInitialized(ServletContextEvent sce)
contextDestroyed(ServletContextEvent sce)

形参:

获取application对象

6、ServletContextAttributeListener

监听application对象的数据变更
attributeAdded(ServletContextAttributeEvent event)
attributeRemoved(ServletContextAttributeEvent event)
attributeReplaced(ServletContextAttributeEvent event)

形参:

获取当前被监听的数据 getName()返回数据的键名,getValue()返回数据的值

案例:利用监听器实现在线用户的统计

1、后台代码的编写

package com.szxy.listener;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

public class MyListener implements ServletContextListener,HttpSessionListener{

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        // TODO Auto-generated method stub
        
    }
    
    //监听application对象初始化的方法
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        System.out.println("MyListener.contextInitialized()");
        //设置一个计数器
        int count=0;
        //获取application对象
        ServletContext sc = sce.getServletContext();
        //将计数器放入application对象中
        sc.setAttribute("count", count);
        
    }
    
    //监听session对象创建的方法
    @Override
    public void sessionCreated(HttpSessionEvent se) {
        System.out.println("MyListener.sessionCreated()");
        //获取application中的计数器
        ServletContext sc = se.getSession().getServletContext();
        int count = (int) sc.getAttribute("count");
        //计数器自增
        ++count;
        //将其放到application中去
        sc.setAttribute("count", count);
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
        System.out.println("MyListener.sessionDestroyed()");
        //获取application中的计数器
                ServletContext sc = se.getSession().getServletContext();
                int count = (int) sc.getAttribute("count");
                //计数器自减
                --count;
                //将其放到application中去
                sc.setAttribute("count", count);
    }
    
}

2、web.xml的配置

<!-- 配置监听器 -->
  <listener>
    <listener-class>com.szxy.listener.MyListener</listener-class>
  </listener>

过滤器

过滤器用于对用户请求进行拦截,对符合我们需求的资源进行放行处理

问题

目前我们访问Servlet,是可以直接进行访问的,没有进行任何防护。
可能会造成服务器资源的浪费,以及安全性不高。
我们希望真的在请求被Servlet处理之前,进行一次请求的校验,符合要求再调用对应Servlet进行请求处理

解决

使用过滤器

使用

1、创建一个普通java类并实现过滤器接口Filter

2、在web.xml中配置过滤器

<filter>
        <filter-name>配置的过滤器名称</filter-name>
        <filter-class>要配置的过滤器的全限定路径:包名.类名</filter-class>
</filter>
<filter-mapping>
        <filter-name>配置的过滤器名称</filter-name>
        <url-pattern>过滤器拦截请求地址的范围</url-pattern>
</filter-mapping>

示例

在这里插入图片描述

过滤器中的方法

doFilter方法

作用:
服务器在接收到浏览器发过来的请求后,先解析请求信息,创建对象request和response然后根据请求URL地址判断如果符合过滤器的过滤范围,则会调用过滤器中的doFilter来进行请求拦截,并将request和response对象作为实参传递给doFilter方法。我们可以在doFilter方法中声明过滤器拦截代码。
参数:
                ServletRequest:接收此次拦截的请求的request实参
                ServletResponse:接收此次拦截的请求的response实参
                FilterChain:可以进行请求放行
                        chain.doFilter(request, response);
    

init方法和destory方法

init方法:服务器启动时调用
destory方法:服务器关闭时调用
证明:过滤器的生命周期为从服务器开启到服务器关闭

过滤器之拦截范围配置

(见上图实例)
拦截所有: /*
        拦截部分Servlet的请求: *.do
        拦截指定Servlet的请求:和要拦截的指定的Servlet的url-pattern配置完全一致即可,例如:/my.do
        
注意:
多个过滤器拦截顺序
       过滤器之间会出现多重拦截,web服务器根据Filter在web.xml中的注册顺序,决定先调用哪个Filter.
      当第一个Filter的doFilter方法被调用时,web服务器会创建一个代表Filter链的FilterChain对象传递给该方法,在doFilter方法中,开发人员如果调用了FilterChain对象的doFilter方法,则web服务器会检查FilterChain对象中是否还有filter,如果有,则调用第二个filter,如果没有,则调用目标资源。

三种过滤器综合使用小案例

1)MyServlet(访问别名my .do)
在这里插入图片描述
2) 三个过滤器(MyFilter/MyFilter2/MyFilter3)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
3) 运行结果
在这里插入图片描述

项目案例——判断用户是否登录

通过过滤器实现判断用户是否登录:如登录则进行登录资源放行,否则则会返回登录界面,防止用户通过url直接访问其他资源

1、新建一个UserLoginFilter类实现Filter接口(import javax.servlet.Filter;)

2、类的具体内容

package com.szxl.web.Filter.UserLoginFilter
import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import com.bjsxt.pojo.Users;
/**
 * 用于判断用户是否登录
 * @author chy
 *
 */
public class UserLoginFilter implements Filter{

    @Override
    public void destroy() {
        // TODO Auto-generated method stub
        
    }

    @Override
    public void doFilter(ServletRequest arg0, ServletResponse arg1,
            FilterChain chain) throws IOException, ServletException {
        
        //获取用户访问的uri(统一资源标识符)
        HttpServletRequest req=(HttpServletRequest) arg0;
        String uri = req.getRequestURI();
        //判断当前访问的uri是否是用户登陆资源,如果是则放行
        //indexOf:比较uri这个字符串中是否存在login字符串。-1为indexOf的返回值,返回不到返回-1
        if (uri.indexOf("login")!=-1 || uri.indexOf("userlogin")!= -1) {
            chain.doFilter(arg0, arg1);
        }else {
            //用户是否登录的判断
            HttpSession session = req.getSession();
            Users user = (Users) session.getAttribute("user");
            if (user!=null && user.getUsername().length()>0) {
                chain.doFilter(arg0, arg1);//放行
            }else {
                req.setAttribute("msg", "请登录");
                req.getRequestDispatcher("/login").forward(arg0, arg1);
            }
        }
    }

    @Override
    public void init(FilterConfig arg0) throws ServletException {
        // TODO Auto-generated method stub
        
    }

}
注:session中必须要有名为user的对象,必须要有login.jsp页面(登录)以及userlogin(用户登陆的servlet的访问别名@RequestMapping("/userlogin"))

3、在web.xml中添加该过滤器

<!-- 定义判断用户是否登录的过滤器 -->
      <filter>
            <filter-name>UserLoginFilter</filter-name>
            <filter-class>com.szxl.web.Filter.UserLoginFilter</filter-class>
    </filter>
    <filter-mapping>
            <filter-name>UserLoginFilter</filter-name>
            <url-pattern>/*</url-pattern>
    </filter-mapping>

4、测试该过滤器

不登录,直接访问index中相关资源

没有配置过滤器之前
在这里插入图片描述
配置过滤器之后
在这里插入图片描述

相关文章
|
2月前
|
Web App开发 SQL Java
javaweb实现分页(二)
javaweb实现分页(二)
19 1
|
2月前
|
SQL 关系型数据库 MySQL
javaweb实现分页查询(一)
javaweb实现分页查询(一)
20 0
|
2月前
|
SQL 关系型数据库 MySQL
javaweb中实现分页,持续更新……
javaweb中实现分页,持续更新……
19 1
|
28天前
|
JSON Java 应用服务中间件
JavaWeb项目之乱码问题及如何解决
JavaWeb项目之乱码问题及如何解决
|
2月前
|
Java Spring 容器
[JavaWeb]——过滤器filter与拦截器Interceptor的使用、执行过程、区别
[JavaWeb]——过滤器filter与拦截器Interceptor的使用、执行过程、区别
|
23天前
|
JavaScript 前端开发
javaweb文件上传和下载
javaweb文件上传和下载
|
2月前
|
前端开发 NoSQL 应用服务中间件
javaweb单点登录的三种实现方式
javaweb单点登录的三种实现方式
35 0
|
2月前
|
SQL 前端开发 Java
Java后端进阶之路: JavaWeb(四)
Java后端进阶之路: JavaWeb
35 1
|
XML SQL Java
Java后端进阶之路: JavaWeb(三)
Java后端进阶之路: JavaWeb
34 1
|
20小时前
|
缓存 Java 调度
Java并发编程:深入理解线程池
【4月更文挑战第30天】 在Java并发编程中,线程池是一种重要的工具,它可以帮助我们有效地管理线程,提高系统性能。本文将深入探讨Java线程池的工作原理,如何使用它,以及如何根据实际需求选择合适的线程池策略。