一、监听器

  1. 使用场景:在一些业务场景中,当容器初始化完成之后,需要处理一些操作,比如一些数据的加载、初始化缓存、特定任务的注册、开启线程或程序来干某些事情等等。

  2. 使用步骤

    A. 监听类实现ApplicationListener接口 ;

    B. 将监听类添加到SpringApplication实例(两种方式:application.properties配置、java启动配置)。

  3. 事件类型

    A. ApplicationStartingEvent:SpringBoot启动开始时执行的事件;

    B. ApplicationEnvironmentPreparedEvent:SpringBoot对应Enviroment已经准备完毕,但此时上下文context还没有创建时触发的事件;

    C. ApplicationContextInitializedEvent:上下文初始化执行的事件;

    D. ApplicationPreparedEvent:SpringBoot上下文context创建完成,但此时spring中的bean是没有完全加载完成时触发的事件;

    E. ApplicationStartedEvent:bean实例化完成,但是未调用Runners接口时触发的事件;

    F. ApplicationReadyEvent:调用Runner 接口完毕时触发的事件;

    G. ApplicationFailedEvent:SpringBoot启动异常失败时执行的事件 。

  4. 举例

package com.ruhuanxingyun;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import com.nsac.business.listener.ApplicationStartup;

@SpringBootApplication
public class SpApp {
    public static void main(String[] args) {
        SpringApplication springApplication = new SpringApplication(SpApp.class);
        springApplication.addListeners(new ApplicationStartup());
        springApplication.run(args);
    }
}
package com.nsac.ruhuanxingyun;

import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;

public class ApplicationStartup implements ApplicationListener<ContextRefreshedEvent> {

    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        ApplicationContext ac = event.getApplicationContext();
        StepExecutor StepExecutor = new StepExecutor(ac.getEnvironment().getProperty("project-id"), ac.getBean("businessSingleJedisPool",redis.clients.jedis.JedisPool.class), 
                                ac.getBean("redisCluster", redis.clients.jedis.JedisCluster.class));
        Thread thread = new Thread(StepExecutor);
        thread.start();
    }

}

   5. 自定义监听器

 

二、过滤器(Filter)

  1. 使用场景:过滤器是处于客户端和服务器资源文件之间的一道过滤网,帮助我们过滤掉一些不符合要求的请求,通常用作Session校验和用户权限校验等;

  2. 自定义Filter实现步骤

    A. 实现javax.servlet.Filter类,重写三个方法;

    B. init方法:在容器中创建当前过滤器的时候自动调用;

    C. destory方法:在容器中销毁当前过滤器的时候自动调用;

    D. doFilter方法:过滤的具体操作。

  3. 组件扫描注册实现过滤器

    A. 采用@WebFilter + @ServletComponentScan注解实现;

    B. 代码

springboot 监听bean容器耗时 springboot使用监听器_spring

package com.ruhuanxingyun.web.manage.filter;

import cn.hutool.core.util.StrUtil;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;

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

/**
 * @description: 跨域 过滤器
 * @author: ruphie
 * @date: Create in 2020/12/26 14:14
 * @company: ruhuanxingyun
 */
@WebFilter(filterName = "corsFilter", urlPatterns = {"/api/*", "/gateway/*"})
public class CorsFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        // 跨域时会发送option请求
        if (!StrUtil.equals(HttpMethod.OPTIONS.name(), httpServletRequest.getMethod())) {
            chain.doFilter(request, response);
            return;
        }

        HttpServletResponse httpServletResponse = (HttpServletResponse) response;
        httpServletResponse.setHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, "*");
        httpServletResponse.setHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, "GET, POST, OPTIONS, PUT, DELETE");
        // 浏览器低版本不支持*
        httpServletResponse.setHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS, "Authorization, Content-Type");
        httpServletResponse.setStatus(HttpStatus.OK.value());
    }

}

注意使用@Order注解失效。


    A. 采用@Configuration + @Bean注解实现;

    B. 代码

  5. AntPathMatcher匹配规则

    A. ? 匹配一个字符,* 匹配0个或多个字符,** 匹配url中的0个或多个子目录;

 

三、拦截器(Interceptor)

  1. 使用场景:拦截器是动态拦截action调用的对象,然后提供在action执行前后增加一些操作,功能与过滤器类似,但是标准和实现方式不同,通常用在登录认证、记录系统日志和通用处理等;

  2. 自定义Interceptor实现步骤

    A. 实现HandlerInterceptor类,重写三个方法;

    B. preHandler方法:在Controller处理请求之前被调用,返回值是boolean类型,如果为true就继续下一步操作,若为false,则证明不符合拦截条件;

    C. postHandler方法:在Controller处理请求执行完毕后,生成视图前执行;

    D. afterCompletion方法:在DispatcherServlet完全处理请求后被调用,通常用于记录消耗时间,也可以对一些资源进行处理。

  3. Filter与Interceptor的区别

    A. Filter是JavaEE的标准,依赖于Servlet容器,生命周期也和容器一致,而Interceptor是SpringMVC中的内容,依赖于web框架;

    B. Filter是基于回调函数实现的,无法注入Ioc容器中的bean,而Interceptor是基于反射实现的,可以注入Ioc容器中的bean;

    C. Filter几乎可以对所有的请求起作用,而Interceptor只能对SpringMVC请求起作用;

    D. 触发时机不同,Filter是在请求进入容器后且在进入servlet之前进行预处理,请求结束是在servlet处理完之后,Interceptor是在请求进入servlet后且进入controller之前进行预处理的,controller中渲染了对应的视图之后请求结束;

  4. 拦截器实现

package com.ruhuanxingyun.web.config;

import com.ruhuanxingyun.web.interceptor.OperateLogInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * @description: 拦截器 配置
 * @author: ruphie
 * @date: Create in 2021/1/6 16:52
 * @company: ruhuanxingyun
 */
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    @Autowired
    private OperateLogInterceptor operateLogInterceptor;

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

}
package com.ruhuanxingyun.web.interceptor;

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;

/**
 * @description: 用户操作日志 拦截器
 * @author: ruphie
 * @date: Create in 2021/1/6 16:43
 * @company: ruhuanxingyun
 */
@Component
public class OperateLogInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("49250");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("1232");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        Map map = (Map) httpServletRequest.getAttribute("response");
        httpServletRequest.getRequestURI();
        HttpServletResponse httpServletResponse = (HttpServletResponse) response;
        httpServletResponse.getOutputStream();
    }

}