首页 > 其他 > 详细

Filter+Listener核心技术

时间:2021-02-10 12:56:03      阅读:39      评论:0      收藏:0      [点我收藏+]

一.filter过滤器

  • javaweb三大组件:filter、listener、servlet.
  • 过滤器是向web应用程序的请求和响应处理添加功能的web服务组件,可以在访问资源之前对请求和响应进行修改、判断、拦截  

技术分享图片

  • 实现方式
    • 实现filter(javax.servlet)接口并重写dofilter方法,一定要保留chain.doFilter(request,response);, 相当于放行功能
    • web.xml文件中配置过滤器

  

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

@WebFilter(filterName = "LoginFilter")
public class LoginFilter implements Filter {
    public void destroy() {
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        //1.ServletRequest是HttpServletRequest的父类,需要强转
        HttpServletRequest httpServletRequest=(HttpServletRequest)req;
        //2.获取session和路径
        var user = httpServletRequest.getSession().getAttribute("user");
        var servletPath = httpServletRequest.getServletPath();
        if(null==user && !servletPath.contains("login")){
            req.getRequestDispatcher("login.jsp").forward(req,resp);
        }else
        chain.doFilter(req, resp);
    }

    public void init(FilterConfig config) throws ServletException {

    }

}
   <filter>
        <filter-name>LoginFilter</filter-name>
        <filter-class>LoginFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>LoginFilter</filter-name>
        <url-pattern>/main.jsp</url-pattern>
    </filter-mapping>

1.filter接口

  • javax.servlet.Filter接口主要用于描述过滤器对象,可以对资源的请求和资源的响应操作进行筛选操作
  • 生命周期: 构造方法--初始化init--有阻拦调阻拦dofilter--结束就销毁
方法声明 功能介绍
void init(FilterConfig filterConfig) 实现过滤器的初始化操作
void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) 执行过滤操作的功能
void destroy() 实现过滤器的销毁操作

 

  • 执行结果:构造过滤器---过滤器正在初始化---阻拦一切html文件,不放行---过滤器销毁了
<filter>
        <filter-name>LifeFilter</filter-name>
        <filter-class>LifeFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>LifeFilter</filter-name>
        <url-pattern>*.html</url-pattern>
    </filter-mapping>
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

@WebFilter(filterName = "LifeFilter")
public class LifeFilter implements Filter {
    public LifeFilter() {
        System.out.println("构造过滤器");
    }

    public void destroy() {
        System.out.println("过滤器销毁了");
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        System.out.println("阻拦一切html文件,不放行");
    }

    public void init(FilterConfig config) throws ServletException {
        System.out.println("过滤器正在初始化");

    }

}

2.filterConfig接口

  • javax.servlet.FilterConfig接口主要用于描述过滤器的配置信息
  • 在配置文件中初始化过滤器配置信息init-param
方法声明 功能介绍
String getFilterName() 获取过滤器的名字
String getInitParameter(String name) 获取指定的初始化参数信息
Enumeration getInitParameterNames() 获取所有的初始化操作名称
ServletContext getServletContext() 获取ServletContext对象
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
import java.util.Enumeration;

@WebFilter(filterName = "FilterConfig")
public class FilterConfig implements Filter {
    public void destroy() {
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        chain.doFilter(req, resp);
    }

    public void init(javax.servlet.FilterConfig config) throws ServletException {
        System.out.println(config.getFilterName());//获取过滤器名字FilterConfig
        System.out.println(config.getInitParameter("name"));//获取参数值,指定的初始化参数信息admin
        var names = config.getInitParameterNames();//获取所有初始化的参数名
        while (names.hasMoreElements()){
            System.out.println(names.nextElement());//pass sex name age
        }
        System.out.println(config.getServletContext());//获取ServletContext对象信息 org.apache.catalina.core.ApplicationContextFacade@d5319d5

    }

}
  <filter>
        <filter-name>FilterConfig</filter-name>
        <filter-class>FilterConfig</filter-class>
        <init-param>
            <param-name>name</param-name>
            <param-value>admin</param-value>
        </init-param>
        <init-param>
            <param-name>pass</param-name>
            <param-value>123466</param-value>
        </init-param>
        <init-param>
            <param-name>sex</param-name>
            <param-value>female</param-value>
        </init-param>
        <init-param>
            <param-name>age</param-name>
            <param-value>16</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>FilterConfig</filter-name>
        <url-pattern>*.avi</url-pattern>
    </filter-mapping>

3. 多个过滤器的使用

  • 如果有多个过滤器都满足过滤的条件,则容器依据配置文件映射的先后顺序来调用各个过滤器
  • 执行顺序:浏览器访问资源先访问过滤器1,2,3; 资源返回时先返回过滤器3,2,1
  • 优点:
    • 实现代码的可插拔性,即增加或减少某个功能模块,不会影响程序的正常执行;
    • 可以将多个相同处理逻辑的模块集中写在过滤器里面,可实现重复利用、也方便代码的维护

    技术分享图片

  • 执行结果:第一个过滤器---第二个过滤器---第三个过滤器---返回第三个过滤器----返回第二个过滤器--返回第一个过滤器
  • 执行顺序跟配置文件映射的顺序相对应
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <filter>
    <filter-name>FilterA</filter-name>
    <filter-class>FilterA</filter-class>
</filter>
    <filter-mapping>
        <filter-name>FilterA</filter-name>
        <url-pattern>*.html</url-pattern>
    </filter-mapping>
    <filter>
        <filter-name>FilterB</filter-name>
        <filter-class>FilterB</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>FilterB</filter-name>
        <url-pattern>*.html</url-pattern>
    </filter-mapping>
    <filter>
        <filter-name>FilterC</filter-name>
        <filter-class>FilterC</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>FilterC</filter-name>
        <url-pattern>*.html</url-pattern>
    </filter-mapping>
</web-app>
import jdk.swing.interop.SwingInterOpUtils;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

@WebFilter(filterName = "FilterA")
public class FilterA implements Filter {
    public void destroy() {
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        System.out.println("第一个过滤器");
        chain.doFilter(req, resp);
        System.out.println("返回第一个过滤器");
    }

    public void init(FilterConfig config) throws ServletException {

    }

}

//---------------------------
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

@WebFilter(filterName = "FilterB")
public class FilterB implements Filter {
    public void destroy() {
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        System.out.println("第二个过滤器");
        chain.doFilter(req, resp);
        System.out.println("返回第二个过滤器");
    }

    public void init(FilterConfig config) throws ServletException {

    }

}
//--------------
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

@WebFilter(filterName = "FilterC")
public class FilterC implements Filter {
    public void destroy() {
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        System.out.println("第三个过滤器");
        chain.doFilter(req, resp);
        System.out.println("返回第三个过滤器");
    }

    public void init(FilterConfig config) throws ServletException {

    }

}

二、listener监听器

  • Servlet规范中定义的一种特殊的组件,用来监听Servlet容器产生的事件并进行相应的处理。
  • 容器产生的事件主要包括:与生命周期相关的事件、与属性状态相关的事件、与存值状态相关的事件
  • 实现方式:采用接口回调的方式,实现各监听器接口。
监听器类型 功能介绍
javax.servlet.ServletRequestListener 监听request作用域的创建和销毁
javax.servlet.ServletRequestAttributeListener 监听request作用域的属性状态变化
javax.servlet.http.HttpSessionListener 监听session作用域的创建和销毁
javax.servlet.http.HttpSessionAttributeListener 监听session作用域的属性状态变化
javax.servlet.ServletContextListener 监听application作用域的创建和销毁
javax.servlet.ServletContextAttributeListener 监听application作用域的属性状态变化
javax.servlet.http.HttpSessionBindingListener 监听对象与session的绑定和解除
javax.servlet.http.HttpSessionActivationListener 监听session数值的钝化和活化

1.ServletRequestListener监听器

  • ServletRequest创建和关闭时都会通知ServletRequestListener监听器。
  • 常用方法:
方法声明 功能介绍
void requestInitialized(ServletRequestEvent sre) 实现ServletRequest对象的初始化
void requestDestroyed(ServletRequestEvent sre) 实现ServletRequest对象的销毁
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;

public class MyServletRequestListener implements ServletRequestListener {
    //ServletRequest创建和关闭时
    //利用idea时会自动打开浏览器,就会创建两次
        //ServletRequest创建了
        //ServletRequest关闭了
        //ServletRequest创建了
        //ServletRequest关闭了
    
    @Override
    public void requestDestroyed(ServletRequestEvent servletRequestEvent) {
        System.out.println("ServletRequest关闭了");
    }
    //改为手动打开浏览器访问时,访问时创建,关闭时关闭
    //ServletRequest创建了
    //ServletRequest关闭了
    @Override
    public void requestInitialized(ServletRequestEvent servletRequestEvent) {
        System.out.println("ServletRequest创建了");

    }
}
  <listener>
        <listener-class>MyServletRequestListener</listener-class>
    </listener>

2. ServletRequestAttributeListener监听器

  • ServletRequest添加、删除或者替换一个属性的时候,将会通知ServletRequestAttributeListener监听器。
  • 常用方法:
方法声明 功能介绍
void attributeAdded(ServletRequestAttributeEvent srae) 增加属性时触发
void attributeReplaced(ServletRequestAttributeEvent srae) 修改属性时触发
void attributeRemoved(ServletRequestAttributeEvent srae) 删除属性时触发
  • 执行结果:修改属性org.apache.catalina.ASYNC_SUPPORTED:true---增加属性name:zhangfei---修改属性name:zhangfei---删除属性name

  • 注意:这里修改属性并没有把修改后的属性值打印输出
import javax.servlet.ServletRequestAttributeEvent;
import javax.servlet.ServletRequestAttributeListener;

public class MyServletRequestAttributeListener implements ServletRequestAttributeListener {
    //当请求附带属性时监听
    @Override
    public void attributeAdded(ServletRequestAttributeEvent servletRequestAttributeEvent) {
        System.out.println("增加属性"+servletRequestAttributeEvent.getName()+":"+servletRequestAttributeEvent.getValue());//增加属性
    }

    @Override
    public void attributeRemoved(ServletRequestAttributeEvent servletRequestAttributeEvent) {
        System.out.println("删除属性"+servletRequestAttributeEvent.getName());//删除属性

    }

    @Override
    public void attributeReplaced(ServletRequestAttributeEvent servletRequestAttributeEvent) {
        System.out.println("修改属性"+servletRequestAttributeEvent.getName()+":"+servletRequestAttributeEvent.getValue());//修改属性
    }
}
<%--
  Created by IntelliJ IDEA.
  User: Administrator
  Date: 2021/2/9
  Time: 12:11
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>MyServletRequestAttributeListener监听request属性</title>
</head>
<body>
<%
    request.setAttribute("name","zhangfei"); //增加属性
    request.setAttribute("name","guanyu"); //修改属性
    request.removeAttribute("name");//删除属性
%>
</body>
</html>
  <listener>
        <listener-class>MyServletRequestAttributeListener</listener-class>
    </listener>

3. HttpSessionListener监听器

  • 当一个HttpSession刚被创建或者失效(invalidate)的时候,将会通知HttpSessionListener监听器。
  • 常用方法如下:
方法声明 功能介绍
void sessionCreated(HttpSessionEvent
se)
当一个HttpSession对象被创建时会调用这个方法
void sessionDestroyed(HttpSessionEvent
se)
当一个HttpSession超时或者调用HttpSession invalidate()方法让它销毁时,将会调用这个方法
  <listener>
        <listener-class>MyHttpSessionListener</listener-class>
    </listener>
    <!--观察不到会话销毁的原因是因为会话的生命周期默认为30分钟,自定义会话存活时间为3s,就会自动销毁会话-->
    <session-config>
        <session-timeout>1</session-timeout>
    </session-config>
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

public class MyHttpSessionListener implements HttpSessionListener{
    @Override
    public void sessionCreated(HttpSessionEvent httpSessionEvent) {
        System.out.println("会话创建");
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
        System.out.println("会话销毁");
    }
}

4. HttpSessionAttributeListener监听器

  • HttpSession中添加、删除或者替换一个属性的时候,将会通知HttpSessionAttributeListener监听器。
  • 常用方法如下
方法声明 功能介绍
void attributeAdded(HttpSessionBindingEvent
se)
当往会话中加入一个属性的时候会调用这个
方法
void
attributeRemoved(HttpSessionBindingEvent
se)
当从会话中删除一个属性的时候会调用这个
方法
void
attributeReplaced(HttpSessionBindingEvent se)
当改变会话中的属性的时候会调用这个方法

 

  • 执行结果:增加属性name:zhangfei---修改属性name:zhangfei---删除属性name

 

import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;

public class MyHttpSessionAttributeListener implements HttpSessionAttributeListener {
    @Override
    public void attributeAdded(HttpSessionBindingEvent httpSessionBindingEvent) {
        System.out.println("增加属性"+httpSessionBindingEvent.getName()+":"+httpSessionBindingEvent.getValue());//增加属性

    }

    @Override
    public void attributeRemoved(HttpSessionBindingEvent httpSessionBindingEvent) {
        System.out.println("删除属性"+httpSessionBindingEvent.getName());//删除属性

    }

    @Override
    public void attributeReplaced(HttpSessionBindingEvent httpSessionBindingEvent) {
        System.out.println("修改属性"+httpSessionBindingEvent.getName()+":"+httpSessionBindingEvent.getValue());//修改属性

    }
}
   <listener>
        <listener-class>MyHttpSessionAttributeListener</listener-class>
    </listener> 
<%--
  Created by IntelliJ IDEA.
  User: Administrator
  Date: 2021/2/9
  Time: 12:11
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>MyServletRequestAttributeListener监听request属性</title>
</head>
<body>
<%
    session.setAttribute("name","zhangfei"); //增加属性
    session.setAttribute("name","guanyu"); //修改属性
    session.removeAttribute("name");//删除属性
%>
</body>
</html>

5. ServletContextListener监听器

  • ServletContext创建和关闭时都会通知ServletContextListener监听器。
  • 常用方法如下
方法声明 功能介绍
void
contextInitialized(ServletContextEvent
sce)
ServletContext创建的时候,将会调用这个方法
void
contextDestroyed(ServletContextEvent
sce)
ServletContext销毁的时候(例如关闭应用服务器
或者重新加载应用),将会调用这个方法

 

  • 启动servlet就会创建servlet并监听,终止会销毁
 <listener>
        <listener-class>MyServletContextListener</listener-class>
    </listener>
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

public class MyServletContextListener implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        System.out.println("ServletContext创建");
    }

    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
        System.out.println("ServletContext销毁");

    }
}

6.ServletContextAttributeListener监听器

  • ServletContext添加、删除或者替换一个属性的时候,将会通知ServletContextAttributesListener监听器
  • 常用方法如下
方法声明 功能介绍
void attributeAdded(ServletContextAttributeEvent
scae)
ServletContext中加入一个属性的时
候触发
void
attributeRemoved(ServletContextAttributeEvent
scae)
ServletContext中删除一个属性的时
候触发
void
attributeReplaced(ServletContextAttributeEvent
scae)
改变ServletContext中属性的时候触发

 

  • 执行结果:增加属性name:zhangfei---修改属性name:zhangfei---删除属性name 

<listener>
        <listener-class>MyServletContextAttributeListener</listener-class>
    </listener>
import javax.servlet.ServletContextAttributeEvent;
import javax.servlet.ServletContextAttributeListener;

public class MyServletContextAttributeListener implements ServletContextAttributeListener {
    @Override
    public void attributeAdded(ServletContextAttributeEvent servletContextAttributeEvent) {
        System.out.println("增加属性"+servletContextAttributeEvent.getName()+":"+servletContextAttributeEvent.getValue());//增加属性

    }

    @Override
    public void attributeRemoved(ServletContextAttributeEvent servletContextAttributeEvent) {
        System.out.println("删除属性"+servletContextAttributeEvent.getName());//删除属性

    }

    @Override
    public void attributeReplaced(ServletContextAttributeEvent servletContextAttributeEvent) {
        System.out.println("修改属性"+servletContextAttributeEvent.getName()+":"+servletContextAttributeEvent.getValue());//修改属性

    }
}
<%--
  Created by IntelliJ IDEA.
  User: Administrator
  Date: 2021/2/9
  Time: 12:11
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>MyServletRequestAttributeListener监听request属性</title>
</head>
<body>
<%
    application.setAttribute("name","zhangfei"); //增加属性
    application.setAttribute("name","guanyu"); //修改属性
    application.removeAttribute("name");//删除属性
%>
</body>
</html>

7. HttpSessionBindingListener监听器

  • HttpSession中绑定和解除绑定时,将会通知HttpSessionListener监听器。
  • 常用方法如下
方法声明 功能介绍
void valueBound(HttpSessionBindingEvent event) 有对象绑定时调用该方法
void valueUnbound(HttpSessionBindingEvent event) 有对象解除绑定时调用该方法
<%--
  Created by IntelliJ IDEA.
  User: Administrator
  Date: 2021/2/9
  Time: 12:02
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="com.Person" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>
<%
  Person person = new Person();
  person.setName("zhangfei");
  session.setAttribute("person",person);
  session.removeAttribute("person");

%>
  </body>
</html>
package com;

import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;

public class Person implements HttpSessionBindingListener {
    private String name;

    @Override
    public String toString() {
        return "Person{" +
                "name=‘" + name + ‘\‘‘ +
                ‘}‘;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Person() {
    }

    public Person(String name) {
        this.name = name;
    }

    @Override
    public void valueBound(HttpSessionBindingEvent httpSessionBindingEvent) {
        System.out.println("开始绑定");
    }

    @Override
    public void valueUnbound(HttpSessionBindingEvent httpSessionBindingEvent) {
        System.out.println("解除绑定");
    }
}

8. HttpSessionActivationListener监听器

  • 当有session数值的钝化和活化操作时,将会通知HttpSessionActivationListener监听器。
  • 常用方法如下:
方法声明 功能介绍
void sessionWillPassivate(HttpSessionEvent se) 有钝化操作时调用该方法
void sessionDidActivate(HttpSessionEvent se) 有活化操作时调用该方法

 

  • 配置context.xml文件的方式如下  
<Manager className="org.apache.catalina.session.PersistentManager"
saveOnRestart="true">
<!-- 配置文件存放的路径信息,可以自由指定 -->
<Store className="org.apache.catalina.session.FileStore"
directory="C:\session"/>
</Manager>

三、案例应用

  • 实现功能: 在线人数统计监听
  • 监听器 
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

public class MyListener implements HttpSessionListener, ServletContextListener {
    ServletContext servletContext=null;
    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
       servletContext = servletContextEvent.getServletContext();
    }

    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
        servletContext=null;
    }

    @Override
    public void sessionCreated(HttpSessionEvent httpSessionEvent) {
//将当前的在线人数加上1,并且保存到ServletContext(application)中        
System.out.println("有新用户上线");
        Object count = servletContext.getAttribute("count");
        if (null==count){
            servletContext.setAttribute("count",1);
        }else
        {   Integer num=(Integer) count;
        num++;
        servletContext.setAttribute("count",num);
        }
        System.out.println("当前在线用户人数为"+servletContext.getAttribute("count"));

    }

    @Override
    public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
        System.out.println("用户下线");
        
    }
}
  • 配置文件
  <listener>
        <listener-class>MyListener</listener-class>
    </listener>
  • jsp文件 
<%--
  Created by IntelliJ IDEA.
  User: Administrator
  Date: 2021/2/10
  Time: 11:05
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>监听在线用户人数</title>
</head>
<body>
<h1>
     当前在线用户人数:${applicationScope.count}
</h1>
</body>
</html>

Filter+Listener核心技术

原文:https://www.cnblogs.com/forever-fate/p/14395253.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!