监听器,过滤器,拦截器

2023-11-07

参考博文

作用

拦截器(interceptor):在一个请求进行中的时候,你想干预它的进展,甚至控制是否终止。这是拦截器做的事。
过滤器(Filter):当有一堆东西,只希望选择符合的东西。定义这些要求的工具,就是过滤器。
监听器(Listener):一个事件发生后,只希望获取这些事个事件发生的细节,而不去干预这个事件的执行过程,这就用到监听器

三者区别

拦截器(interceptor):依赖于web框架,基于Java的反射机制,属于AOP的一种应用。一个拦截器实例在一个controller生命周期内可以多次调用。只能拦截Controller的请求。

是在面向切面编程的就是在你的service或者一个方法前调用一个方法,或者在方法后调用一个方法比如动态代理就是拦截器的简单实现,在你调用方法前打印出字符串(或者做其它业务逻辑的操作),也可以在你调用方法后打印出字符串,甚至在你抛出异常的时候做业务逻辑的操作。

过滤器(Filter):依赖于Servlet容器,基于函数回掉,可以对几乎所有请求过滤,一个过滤器实例只能在容器初使化调用一次。

是在java web中,你传入的request,response提前过滤掉一些信息,或者提前设置一些参数,然后再传入servlet或者struts的 action进行业务逻辑,比如过滤掉非法url(不是login.do的地址请求,如果用户没有登陆都过滤掉),或者在传入servlet或者 struts的action前统一设置字符集,或者去除掉一些非法字符.

监听器(Listener):web监听器是Servlet中的特殊的类,用于监听web的特定事件,随web应用启动而启动,只初始化一次。

Java的监听器,也是系统级别的监听。监听器随web应用的启动而启动。Java的监听器在c/s模式里面经常用到,它
会对特定的事件产生产生一个处理。监听在很多模式下用到,比如说观察者模式,就是一个使用监听器来实现的,在比如统计网站的在线人数。

过滤器 监听器 拦截器
关注的点 web请求 系统级别参数、对象 部分web请求
如何实现 函数回调 事件 java反射机制
应用场景 设置字符编码,url级别权限访问,过滤敏感词汇,压缩响应信息 统计网站在线人数,清除过期的
是否依赖servlet容器 依赖 不依赖
servlet提供的支持 filter ServletContextListener,HttpSessionListener
spring提供支持 HandlerInterceptorAdapter,HandlerInterceptor
级别 系统 系统 非系统

启动顺序

监听器,过滤器,拦截器

拦截器

简要说明

SpringBoot通过实现HandlerInterceptor接口实现拦截器,通过实现WebMvcConfigurer接口实现一个配置类,在配置类中注入拦截器,最后再通过@Configuration注解注入配置。

实现接口HandlerInterceptor

重写三个方法
preHandle 在请求处理之前进行调用(Controller方法调用之前)
postHandle 请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后)
afterCompletion 整个请求结束之后被调用,也就是在DispatchServlet渲染了对应的视图之后执行(主要用于进行资源清理工作)

自定义拦截器

package com.geekmice.springbootselfexercise.interceptor;

import com.geekmice.springbootselfexercise.domain.UserDomain;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.Objects;

/**
 * @BelongsProject: spring-boot-self-exercise
 * @BelongsPackage: com.geekmice.springbootselfexercise.interceptor
 * @Author: pingmingbo
 * @CreateTime: 2023-09-12  13:35
 * @Description: 登录拦截器
 * @Version: 1.0
 */
@Slf4j
public class LoginInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        log.info("登录拦截器前置处理");
        HttpSession session = request.getSession();
        UserDomain user = (UserDomain) session.getAttribute("user");
        if (Objects.nonNull(user)) {
            log.info("当前用户已登录,继续后面流程");
            return true;
        }else{
            log.info("未登录,请登录");
            response.sendRedirect(request.getContextPath() + "/user/login");
            throw new IllegalArgumentException("未登录,请登录");
        }
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        log.info("request : [{}]", request);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        log.info("request : [{}]", request);
    }
}

配置拦截器

package com.geekmice.springbootselfexercise.config;

import com.geekmice.springbootselfexercise.interceptor.LoginInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * @BelongsProject: spring-boot-self-exercise
 * @BelongsPackage: com.geekmice.springbootselfexercise.config
 * @Author: pingmingbo
 * @CreateTime: 2023-09-12  13:47
 * @Description: 配置拦截器
 * @Version: 1.0
 */
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(getLoginInterceptor())
                .addPathPatterns("/**");
    }

    @Bean
    public LoginInterceptor getLoginInterceptor(){
        return new LoginInterceptor();
    }
}

在这里插入图片描述

过滤器

简要说明

使用过滤器很简单,只需要实现Filter类,然后重写它的3个方法即可。

init方法:程序启动调用Filter的init()方法(永远只调用一次);在容器中创建当前过滤器的时候自动调用这个方法。
destory方法:程序停止调用Filter的destroy()方法(永远只调用一次);在容器中销毁当前过滤器的时候自动调用这个方法。
doFilter方法:doFilter()方法每次的访问请求如果符合拦截条件都会调用(程序第一次运行,会在servlet调用init()方法以后调用;不管第几次,都在调用doGet(),doPost()方法之前)。这个方法有3个参数,分别是ServletRequest、ServletResponse和FilterChain可以从参数中获取HttpServletReguest和HttpServletResponse对象进行相应的处理操作。

在springboot 启动类添加该注解@ServletComponentScan

package com.geekmice.springbootselfexercise;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;

@SpringBootApplication
@ServletComponentScan
@MapperScan("com.geekmice.springbootselfexercise.dao")
public class SpringBootSelfExerciseApplication {

    public static void main(String[] args) {
        SpringApplication springApplication = new SpringApplication(SpringBootSelfExerciseApplication.class);
        springApplication.run(args);
    }

}

写个过滤器类,实现Filter接口

package com.geekmice.springbootselfexercise.filter;

import com.geekmice.springbootselfexercise.param.MyRequestWrapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.Configuration;

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

/**
 * @BelongsProject: spring-boot-self-exercise
 * @BelongsPackage: com.geekmice.springbootselfexercise.filter
 * @Author: pingmingbo
 * @CreateTime: 2023-09-05  09:27
 * @Description: 修改分页参数默认值
 * @Version: 1.0
 */
@Configuration
@Slf4j
@WebFilter(filterName = "authFilter", urlPatterns = {"/tzArea"})
public class InitValueFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        log.info("过滤器开始初始化 : [{}]" , filterConfig);
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        String pageSize = httpServletRequest.getParameter("pageSize");
        String pageNum = httpServletRequest.getParameter("pageNum");
        if(StringUtils.isAnyBlank(pageSize,pageNum)){
            pageSize="11";
            pageNum="1";
            Map<String,Object> map = new HashMap(16);
            map.put("pageSize", pageSize);
            map.put("pageNum", pageNum);
            MyRequestWrapper myRequestWrapper = new MyRequestWrapper(httpServletRequest, map);
            chain.doFilter(myRequestWrapper, response);
        }


    }

    @Override
    public void destroy() {
        log.info("过滤器销毁");
    }
}

监听器

简要说明

web监听器是一种 Servlet 中特殊的类,它们能帮助开发者监听 web 中特定的事件,比如 ServletContext, HttpSession, ServletRequest的创建和销毁;变量的创建、销毁和修改等。可以在某些动作前后增加处理,实现监控。

如何使用

自定义事件
package com.geekmice.springbootselfexercise.event;

import com.geekmice.springbootselfexercise.domain.UserDomain;
import org.springframework.context.ApplicationEvent;

/**
 * @BelongsProject: spring-boot-self-exercise
 * @BelongsPackage: com.geekmice.springbootselfexercise.event
 * @Author: pingmingbo
 * @CreateTime: 2023-09-12  15:17
 * @Description: 自定义事件
 * @Version: 1.0
 */
public class MyEvent extends ApplicationEvent {

    private UserDomain userDomain;

    public MyEvent(Object source, UserDomain userDomain) {
        super(source);
        this.userDomain = userDomain;
    }

    public UserDomain getUserDomain() {
        return userDomain;
    }

    public void setUserDomain(UserDomain userDomain) {
        this.userDomain = userDomain;
    }
}
自定义过滤器
package com.geekmice.springbootselfexercise.listener;

import com.geekmice.springbootselfexercise.domain.UserDomain;
import com.geekmice.springbootselfexercise.event.MyEvent;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

/**
 * @BelongsProject: spring-boot-self-exercise
 * @BelongsPackage: com.geekmice.springbootselfexercise.listener
 * @Author: pingmingbo
 * @CreateTime: 2023-09-12  15:20
 * @Description: 自定义监听器,监听事件
 * @Version: 1.0
 */
@Slf4j
@Component
public class MyListener implements ApplicationListener<MyEvent> {
    @Override
    public void onApplicationEvent(MyEvent event) {
        // 获取事件中信息
        UserDomain userDomain = event.getUserDomain();
        // 用于逻辑处理
        log.info("userDomain : [{}]", userDomain);
    }
}
接口调用
package com.geekmice.springbootselfexercise.service.impl;

import com.geekmice.springbootselfexercise.domain.UserDomain;
import com.geekmice.springbootselfexercise.event.MyEvent;
import com.geekmice.springbootselfexercise.service.EventService;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

/**
 * @BelongsProject: spring-boot-self-exercise
 * @BelongsPackage: com.geekmice.springbootselfexercise.service.impl
 * @Author: pingmingbo
 * @CreateTime: 2023-09-12  15:25
 * @Description: 测试发布事件
 * @Version: 1.0
 */
@Service
public class EventServiceImpl implements EventService {
    @Resource
    private ApplicationContext applicationContext;

    @Override
    public void publishEvent() {
        UserDomain user = UserDomain.builder().userName("pmb").build();
        // 发布事件
        MyEvent myEvent = new MyEvent(this, user);
        applicationContext.publishEvent(myEvent);
        return;
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

监听器,过滤器,拦截器 的相关文章

随机推荐