65

SpringBoot | 第七章:过滤器、监听器、拦截器

 6 years ago
source link: http://www.importnew.com/29401.html?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

前言

在实际开发过程中,经常会碰见一些比如系统启动初始化信息、统计在线人数、在线用户数、过滤敏高词汇、访问权限控制(URL级别)等业务需求。这些对于业务来说一般上是无关的,业务方是无需关系的,业务只需要关系自己内部业务的事情。所以一般上实现以上的功能,都会或多或少的用到今天准备讲解的 过滤器监听器拦截器 来实现以上功能。

过滤器

过滤器 Filter ,是 Servlet 的的一个实用技术了。可通过过滤器,对请求进行拦截,比如读取 session 判断用户是否登录 、判断访问的 请求URL是否有访问权限(黑白名单) 等。主要还是可对请求进行预处理。接下来介绍下,在 springboot 如何实现过滤器功能。

利用WebFilter注解配置

@WebFilterServlet3.0 新增的注解,原先实现过滤器,需要在 web.xml 中进行配置,而现在通过此注解,启动启动时会自动扫描自动注册。

编写Filter类:

//注册器名称为customFilter,拦截的url为所有
@WebFilter(filterName="customFilter",urlPatterns={"/*"})
@Slf4j
public class CustomFilter implements Filter{

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        log.info("filter 初始化");
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        // TODO Auto-generated method stub
        log.info("doFilter 请求处理");
        //对request、response进行一些预处理
        // 比如设置请求编码
        // request.setCharacterEncoding("UTF-8");
        // response.setCharacterEncoding("UTF-8");
        //TODO 进行业务逻辑
        
        //链路 直接传给下一个过滤器
        chain.doFilter(request, response);
    }

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

然后在启动类加入 @ServletComponentScan 注解即可。

@SpringBootApplication
@ServletComponentScan
@Slf4j
public class Chapter7Application {
    
    public static void main(String[] args) {
        SpringApplication.run(Chapter7Application.class, args);
        log.info("chapter7 服务启动");
    }
}

启动后,控制台输出:

3Q7ZbaA.png!web

过滤器已经生效了。但当注册多个过滤器时,无法指定执行顺序的,原本使用 web。xml 配置过滤器时,是可指定执行顺序的,但使用 @WebFilter 时,没有这个配置属性的(需要配合 @Order 进行),所以接下来介绍下通过 FilterRegistrationBean 进行过滤器的注册。

–小技巧–

  1. 通过 过滤器的名字 ,进行顺序的约定,比如 LogFilterAuthFilter ,此时 AuthFilter 就会比 LogFilter 先执行,因为首字母 AL 前面。
  2. 通过 @Order 指定执行顺序,值越小,越先执行

FilterRegistrationBean方式

FilterRegistrationBeanspringboot 提供的,此类提供setOrder方法,可以为filter设置排序值,让spring在注册web filter之前排序后再依次注册。

改写filter

其实就输出了@webFilter注解即可。其他的都没有变化。

启动类中利用 @bean 注册FilterRegistrationBean

@Bean
    public FilterRegistrationBean  filterRegistrationBean() {
        FilterRegistrationBean registration = new FilterRegistrationBean();
        //当过滤器有注入其他bean类时,可直接通过@bean的方式进行实体类过滤器,这样不可自动注入过滤器使用的其他bean类。
        //当然,若无其他bean需要获取时,可直接new CustomFilter(),也可使用getBean的方式。
        registration.setFilter(customFilter());
        //过滤器名称
        registration.setName("customFilter");
        //拦截路径
        registration.addUrlPatterns("/*");
        //设置顺序
        registration.setOrder(10);
        return registration;
    }

    @Bean
    public Filter customFilter() {
        return new CustomFilter();
    }

注册多个时,就注册多个FilterRegistrationBean即可

启动后,效果和第一种是一样的。

buiqIrr.png!web

监听器

Listeeshi是servlet规范中定义的一种特殊类。用于监听servletContext、HttpSession和servletRequest等域对象的创建和销毁事件。监听域对象的属性发生修改的事件。用于在事件发生前、发生后做一些必要的处理。一般是获取在线人数等业务需求。

创建一个ServletRequest监听器(其他监听器类似创建)

@WebListener
@Slf4j
public class Customlister implements ServletRequestListener{

    @Override
    public void requestDestroyed(ServletRequestEvent sre) {
        log.info("监听器:销毁");
    }

    @Override
    public void requestInitialized(ServletRequestEvent sre) {
        log.info("监听器:初始化");
    }

}

和创建过滤器一样,在启动类中加入 @ServletComponentScan 进行自动注册即可。

MRbEJve.png!web

拦截器

以上的过滤器、监听器都属于 Servlet 的api,我们在开发中处理利用以上的进行过滤web请求时,还可以使用 Spring 提供的拦截器( HandlerInterceptor )进行更加精细的控制。

编写自定义拦截器类

@Slf4j
public class CustomHandlerInterceptor implements HandlerInterceptor{

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		log.info("preHandle:请求前调用");
		//返回 false 则请求中断
		return true;
	}

	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		log.info("postHandle:请求后调用");

	}

	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		log.info("afterCompletion:请求调用完成后回调方法,即在视图渲染完成后回调");

	}

}

通过继承 WebMvcConfigurerAdapter 注册拦截器

@Configuration
public class WebMvcConfigurer extends WebMvcConfigurerAdapter{
	
	@Override
	 public void addInterceptors(InterceptorRegistry registry) {
		 //注册拦截器 拦截规则
		//多个拦截器时 以此添加 执行顺序按添加顺序
		registry.addInterceptor(getHandlerInterceptor()).addPathPatterns("/*");
	 }
	
	@Bean
	public static HandlerInterceptor getHandlerInterceptor() {
		return new CustomHandlerInterceptor();
	}
}

启动后,访问某个url,控制台输出

ZF77FfZ.png!web

请求链路说明

UBJJVzI.png!web

在整个请求的过程,此一图胜千言,希望对此有个深刻的了解,通过不同组合实现不同的业务功能。

总结

本章节主要介绍了常用web开发时,会用到的一些常用类,本章节对 servlet 未进行介绍,平时用的比较少,用法和配置其实和拦截器、监听器是类似的,再次就不阐述了。

最后

目前互联网上很多大佬都有 SpringBoot 系列教程,如有雷同,请多多包涵了。本文是作者在电脑前一字一句敲的,每一步都是实践的。若文中有所错误之处,还望提出,谢谢。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK