一、监听器
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. 代码
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();
}
}