~~本文已参与「新人创作礼」活动,一起开启掘金创作之路。~~
一、定义:
- 过滤器(Filter):对于满足条件的流程进行过滤,如对所有的web操作设置utf-8编码
- 拦截器(Interceptor):对所有操作流程进行拦截,进行干预,甚至终止操作
二、异同点
相同点:
都是aop编程思想的体现,可以在程序执行前后做一些操作
不同点:
- Filter是Servlet组件,Interceptor是Spring组件
- 触发时机不一样,过滤器是在进入容器后,进入Servlet前进行预处理;拦截器是在进入Servlet之后,Controller之前进行处理
- 由于拦截器是Spring组件,故可以获取IOC容器中的各个Bean
三、过滤器简单实现
Filter接口由J2EE定义,在Servlet执行之前由容器进行调用。
实现方式:
- 新建一个类实现Filter接口
- 重写Filter接口里的doFilter接口,里面实现过滤逻辑
1、自定义过滤器
/**
*
* 多过滤器过滤优先级与名称有关
* 当本类名称为JavaWebFilter时, 本类先于JavaWebFilterB启动
* 当本类名称改为JavaWebFilterC时, 本类将晚于JavaWebFilterB启动
*
* 下面通过 @Order() 设置的优先级并不生效
*
*/
//@Order(2)
@WebFilter("/*")
public class JavaWebFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
BasicLogUtil.info("进入过滤器");
chain.doFilter(request, response);
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
BasicLogUtil.info("过滤器启动");
}
@Override
public void destroy() {
BasicLogUtil.info("过滤器被摧毁");
}
}
2、配置过滤器
1)自动配置
springboot启动类通过@ServletComponentScan注解配置自动扫描Servlet组件
该配置方式通过@Order注解设置的优先级不生效,优先级只能通过其默认的方式:按名称来决定
@SpringBootApplication
//@ServletComponentScan // 自动扫描Servlet组件,此处是Filter
public class Springboot04Application {
public static void main(String[] args) {
SpringApplication.run(Springboot04Application.class, args);
}
}
2)手动配置(可以通过order设置优先级)
@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean<CustomFilter> filterRegistrationBean(){
FilterRegistrationBean<CustomFilter> filterFilterRegistrationBean=
new FilterRegistrationBean<>();
filterFilterRegistrationBean.setFilter(new JavaWebFilter());
filterFilterRegistrationBean.addUrlPatterns("/*");
// filterFilterRegistrationBean.setOrder(0); //决定注册的优先级
return filterFilterRegistrationBean;
}
}
四、拦截器简单实现
HandlerInterceptor用于拦截Controller方法的执行,其声明了如下三个方法:
- preHandle:在Controller方法执行前进行过滤处理
- postHandle:在Controller方法执行后、视图渲染前进行过滤处理
- afterCompletion:在整个方法执行后(包括异常处理)进行过滤处理
perHandle()方法的返回值为boolean,返回为true,继续往下执行,否则请求结束
1、自定义拦截器
public class SelfIntercetor implements HandlerInterceptor {
/**
* 请求处理前调用(controller方法之前)
* @param request
* @param response
* @param handler
* @return true: 请求继续往下执行,否则该请求在此处终止
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
BasicLogUtil.info("preHandle: 进入拦截器");
return true;
}
/**
* 请求处理之后,渲染视图之前调用(执行完controller方法后立即调用)
* @param request
* @param response
* @param handler
* @param modelAndView
* @throws Exception
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
BasicLogUtil.info("postHandle: 执行完controller,但未渲染视图");
}
/**
* 请求执行完后调用(DispatcherServlet渲染视图后执行)
* @param request
* @param response
* @param handler
* @param ex
* @throws Exception
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
BasicLogUtil.info("afterCompletion: 渲染视图完成");
}
}
2、配置拦截器
- Spring Boot 1.5,都是靠重写 WebMvcConfigurerAdapter 的方法来添加自定义拦截器
- SpringBoot 2.0 后,推荐实现 WebMvcConfigurer 或者继承 WebMvcConfigurationSupport 实现
@Configuration
public class SelfWebConfig implements WebMvcConfigurer {
/**
* 配置项目中的静态资源不会被拦截,如resources下static文件里的html、js、css等
* @param registry
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
WebMvcConfigurer.super.addResourceHandlers(registry);
}
/**
* 注册自定义拦截器,使其生效
* @param registry
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 拦截所有路径请求,但忽略/login、/register、/static/**
registry.addInterceptor(new SelfIntercetor())
.addPathPatterns("/**")
.excludePathPatterns("/login", "/register", "/static/**");
WebMvcConfigurer.super.addInterceptors(registry);
}
/**
* 设置请求的默认页面
* @param registry
*/
@Override
public void addViewControllers(ViewControllerRegistry registry) {
// 重定向到登录页面
// registry.addViewController("/").setViewName("forward:/login.html");
// 默认访问index.html页面
registry.addViewController("").setViewName("index");
// 设置优先级,当地址重复时,执行优先级最高的
registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
WebMvcConfigurer.super.addViewControllers(registry);
}
}