大家好,又见面了,我是你们的朋友全栈君。
Spring MVC的拦截器(Interceptor)和Filter不同,但是也可以实现对请求进行预处理,后处理。先介绍它的使用,只需要两步: 1.1 实现拦截器 实现拦截器可以通过继承HandlerInterceptorAdapter类。如果preHandle方法return true,则继续后续处理。
public class InterceptorDemo extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
StringBuffer requestURL = httpServletRequest.getRequestURL();
System.out.println("前置拦截器1 preHandle: 请求的uri为:"+requestURL.toString());
return true;
}
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
System.out.println("拦截器1 postHandle: ");
}
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
System.out.println("拦截器1 afterCompletion: ");
}
}
1.2 注册拦截器 实现拦截器后还需要将拦截器注册到spring容器中,可以通过implements WebMvcConfigurer,覆盖其addInterceptors(InterceptorRegistry registry)方法。记得把Bean注册到Spring容器中,可以选择@Component 或者 @Configuration。
@Configuration
public class InterceptorConfig implements WebMvcConfigurer{
/** * 注册自定义拦截器 */
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new InterceptorDemo2()).addPathPatterns("/**");
registry.addInterceptor(new InterceptorDemo()).addPathPatterns("/**");
}
}
注意这里注册了两个拦截器。这两个拦截器的执行顺序和配置顺序有关系,即先配置顺序就在前(感觉这样不太方便,但没有找到设置类似order的API)。
发起一个请求,在控制台可以看到拦截器生效:
前置拦截器2 preHandle: 用户名:null
前置拦截器1 preHandle: 请求的uri为:http://localhost:8010/user/353434
拦截器1 postHandle:
拦截器2 postHandle:
拦截器1 afterCompletion:
拦截器2 afterCompletion:
1.3 拦截器的总结 1.3.1 工作原理 一个拦截器,只有preHandle方法返回true,postHandle、afterCompletion才有可能被执行;如果preHandle方法返回false,则该拦截器的postHandle、afterCompletion必然不会被执行。拦截器不是Filter,却实现了Filter的功能,其原理在于:
1.3.2 拦截器工作流程
1.3.3 和Filter共存时的执行顺序 拦截器是在DispatcherServlet这个servlet中执行的,因此所有的请求最先进入Filter,最后离开Filter。其顺序如下。
Filter->Interceptor.preHandle->Handler->Interceptor.postHandle->Interceptor.afterCompletion->Filter
1.3.4 应用场景 拦截器本质上是面向切面编程(AOP),符合横切关注点的功能都可以放在拦截器中来实现,主要的应用场景包括:
springboot下过滤器的使用有两种形式: 2.1 注解形式 创建一个Filter,并使用WebFilter注解进行修饰,表示该类是一个Filter,以便于启动类进行扫描的时候确认
@WebFilter(urlPatterns = "/*",filterName = "filter2")
public class FilterAnnotationTest implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("过滤器2开始初始化");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("过滤器2开始工作");
filterChain.doFilter(servletRequest,servletResponse);
}
@Override
public void destroy() {
System.out.println("过滤器2销毁");
}
}
然后在启动类上添加注解@ServletComponentScan,该注解用于自动扫描指定包下(默认是与启动类同包下)的WebFilter/WebServlet/WebListener等特殊类。 2.2 代码注册方式 同样编写Filter,但是不添加WebFilter注解,通过@Bean注入spring
public class FilterDemo implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
System.out.println("过滤器开始工作。。"+httpServletRequest.getRequestURL());
filterChain.doFilter(servletRequest,servletResponse);
}
@Override
public void destroy() {
System.out.println("过滤器开始销毁");
}
}
然后利用filterRegistrationBean来进行注册。也可以在代码里设置Order
@Configuration
public class FilterDemo {
@Bean
@Order(2)
//spring boot会按照order值的大小,从小到大的顺序来依次过滤
public FilterRegistrationBean configFilter(){
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
filterRegistrationBean.setFilter(new FilterDemo());
filterRegistrationBean.addUrlPatterns("/*");
filterRegistrationBean.setName("sessionFilter");
//filterRegistrationBean.setOrder(2);
return filterRegistrationBean;
}
}
2.3 过滤器filter和拦截器Interceptor的区别 spring的拦截器和servlet的过滤器有相似之处,都是AOP思想的体现,都可以实现权限检查,日志记录,不同的是
过滤器开始工作。。http://localhost:8010/user/353434
前置拦截器2 preHandle: 用户名:null
前置拦截器1 preHandle: 请求的uri为:http://localhost:8010/user/353434
拦截器1 postHandle:
拦截器2 postHandle:
拦截器1 afterCompletion:
拦截器2 afterCompletion:
过滤器开始工作。。http://localhost:8010/favicon.ico
可以通过这个博客里的一张图来说明:
监听器的简单使用如下:先编写监听器的实现:
@WebListener
public class WebListenerDemo implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("监听器初始化。。。。。。。。。。。。");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("监听器销毁。。。。。。。。。。。");
}
}
监听session创建的监听器(可以用来统计在线人数)
@WebListener
public class SessionListener implements HttpSessionListener {
@Override
public void sessionCreated(HttpSessionEvent se) {
System.out.println("。。。创建session成功");
}
@Override
public void sessionDestroyed(HttpSessionEvent se) {
System.out.println("。。。销毁session");
}
}
然后在启动类上添加注解@ServletComponentScan即可,当然也可以注册到spring容器中省却@ServletComponentScan注解。
@Configuration
public class ListenerConfig {
@Bean
public ServletListenerRegistrationBean servletListenerRegistrationBean() {
ServletListenerRegistrationBean slrBean = new ServletListenerRegistrationBean();
slrBean.setListener(new WebListenerDemo());
return slrBean;
}
@Bean
public ServletListenerRegistrationBean sessionListenerRegistrationBean() {
ServletListenerRegistrationBean slrBean = new ServletListenerRegistrationBean();
slrBean.setListener(new SessionListener());
return slrBean;
}
}
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/160977.html原文链接:https://javaforall.cn