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

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

监听器

作用

监听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中相关资源

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

相关文章
|
5月前
|
存储 前端开发 JavaScript
基于JavaWeb实现停车场管理系统
基于JavaWeb实现停车场管理系统
|
5月前
|
前端开发 JavaScript Java
图书借阅管理平台|基于JavaWeb实现图书借阅系统
图书借阅管理平台|基于JavaWeb实现图书借阅系统
109 1
|
2月前
|
设计模式 Java 关系型数据库
【Java笔记+踩坑汇总】Java基础+JavaWeb+SSM+SpringBoot+SpringCloud+瑞吉外卖/谷粒商城/学成在线+设计模式+面试题汇总+性能调优/架构设计+源码解析
本文是“Java学习路线”专栏的导航文章,目标是为Java初学者和初中高级工程师提供一套完整的Java学习路线。
366 37
|
27天前
|
前端开发 Java 应用服务中间件
Javaweb学习
【10月更文挑战第1天】Javaweb学习
29 2
|
1月前
|
安全 Java Android开发
JavaWeb解压缩漏洞之ZipSlip与Zip炸弹
JavaWeb解压缩漏洞之ZipSlip与Zip炸弹
41 5
|
2月前
|
缓存 前端开发 Java
【Java面试题汇总】Spring,SpringBoot,SpringMVC,Mybatis,JavaWeb篇(2023版)
Soring Boot的起步依赖、启动流程、自动装配、常用的注解、Spring MVC的执行流程、对MVC的理解、RestFull风格、为什么service层要写接口、MyBatis的缓存机制、$和#有什么区别、resultType和resultMap区别、cookie和session的区别是什么?session的工作原理
【Java面试题汇总】Spring,SpringBoot,SpringMVC,Mybatis,JavaWeb篇(2023版)
|
5月前
|
前端开发 Java 关系型数据库
JavaWeb开发简介
JavaWeb开发简介
53 0
|
2月前
|
安全 Java Android开发
JavaWeb解压缩漏洞之ZipSlip与Zip炸弹
JavaWeb解压缩漏洞之ZipSlip与Zip炸弹
92 2
|
2月前
|
SQL JSON JavaScript
JavaWeb基础9——VUE,Element&整合Javaweb的商品管理系统
Vue 指令、生命周期、this和$、vue脚手架进行模块化开发/ElementUI框架、综合案例,element商品列表展示增删改查
JavaWeb基础9——VUE,Element&整合Javaweb的商品管理系统
|
5月前
|
SQL Java 数据库连接
JavaWeb Mapper代理开发
JavaWeb Mapper代理开发