SpringBoot 过滤器,Servlet,拦截器,监听器

本文详细介绍了web开发中的三大组件:Servlet(处理请求),Filter(预处理和后处理),以及Listener(监听器)的功能和应用场景。还对比了Interceptor和Filter的区别,以及在SpringBoot中如何通过各种注解和Bean方式注册这些组件。
摘要由CSDN通过智能技术生成

1.web中的三大组件

Servlet,Filter,Listener。

1.1 Servlet

        主要用来在业务处理之前进行控制,url传来之后,就对其进行处理,处理完成,返回或转向到某一自己指定的页面,可以向用户生成响应。

1.2 Filter

     过滤器(Filter),   可以理解一个一种特殊Servlet,主要用于对用户请求进行预处理,也可以对HttpServletResponse进行后处理,是一个典型的处理链,过滤请求,无法向用户生成响应。在 Servlet 前执行的。用于拦截和处理 HTTP 请求和响应,可用于身份认证、授权、日志记录和设置字符集(CharacterEncodingFilter)等场景。

1.3 Listener

       监听器用于监听web应用中某些对象、信息的创建、销毁、增加,修改,删除等动作的发生,然后作出相应的响应处理。

常用监听器

  •     监听session属性的增加、移除以及属性值改变的HttpSessionAttributeListener
  •     监听web上下文的初始化(服务器已准备好接收请求)与销毁的ServletContextListener
  •     监听web上下文属性的增加、删除、属性值变化的ServletContextAttributeListener
  •     监听request的创建与销毁的ServletRequestListener
  •     监听request的属性的增加、删除、属性值变化的ServletRequestAttributeListener
  •     在线用户数统计的监听器HttpSessionListener

1.4 Interceptor

        拦截器(Interceptor),和Servlet无关,由Spring框架实现。可用于身份认证、授权、日志记录、预先设置数据以及统计方法的执行效率等。

  • 拦截器是基于java的反射机制的,而过滤器是基于函数回调。
  • 拦截器不依赖与servlet容器,过滤器依赖与servlet容器。
  • 拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用。
  • 拦截器可以访问action上下文、值栈里的对象,而过滤器不能访问。
  • 在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次。
  • 拦截器可以获取IOC容器中的各个bean,而过滤器就不行,这点很重要,在拦截器里注入一个service,可以调用业务逻辑。
  • 拦截器(Interceptor):它依赖于web框架,在SpringMVC中就是依赖于SpringMVC框架。在实现上,基于Java的反射机制,属于面向切面编程(AOP)的一种运用,就是在service或者一个方法前,调用一个方法,或者在方法后,调用一个方法。

 Spring 中主要的拦截器有:

  • HandlerInterceptor
  • MethodInterceptor

HandlerInterceptor拦截器:

        HandlerInterceptor 类似 Filter,拦截的是请求地址 ,但提供更精细的的控制能力,必须过DispatcherServlet 的请求才会被拦截。

@Configuration
@Slf4j
public class MyHandlerInterceptorConfig implements WebMvcConfigurer {

    private static final Logger log = LoggerFactory.getLogger(MyHandlerInterceptorConfig.class);

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        List<String> patterns = new ArrayList<>();

        patterns.add("/**");

        registry.addInterceptor(new MyHandlerInterceptor())
                .addPathPatterns(patterns) // 需要拦截的请求
                .excludePathPatterns(); // 不需要拦截的请求
    }

    public class MyHandlerInterceptor implements HandlerInterceptor {
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            log.info("这是MyHandlerInterceptor.preHandle");
            return true;
        }

        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
            log.info("这是MyHandlerInterceptor.postHandle");
        }

        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
            log.info("这是MyHandlerInterceptor.afterCompletion");
        }
    }
}

 

MethodInterceptor拦截器: 

        MethodInterceptor 是 AOP 中的拦截器,它拦截的目标是方法,可以不是 Controller 中的方法。 

//第一步:新建一个Bean
@Service("aService")
public class AService {

    BService bService;

    public String aCallB() {
        String bResult = bService == null ? "bService is null" : bService.bCallBaidu();
        return "这是a;b返回:" + bResult;
    }
}


//第二步:新建代理类
@Configuration
public class MyMethodInterceptor implements MethodInterceptor {

    @Override
    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
        System.out.println("进入拦截,方法执行前,拦截方法是:" + methodInvocation.getMethod().getName());
        Object result = methodInvocation.proceed();
        System.out.println("方法执行后");
        return result;
    }
}

// 第三步:配置代理类和Bean
@Configuration
public class MyMethodInterceptorConfig {
    
    @Bean
    public BeanNameAutoProxyCreator beanNameAutoProxyCreator() {
        // 使用BeanNameAutoProxyCreator来创建代理
        BeanNameAutoProxyCreator beanNameAutoProxyCreator = new BeanNameAutoProxyCreator();

        // 指定一组需要自动代理的Bean名称
        beanNameAutoProxyCreator.setBeanNames("aService");

        //设置拦截器名称,这些拦截器是有先后顺序的
        beanNameAutoProxyCreator.setInterceptorNames("myMethodInterceptor");
        return beanNameAutoProxyCreator;
    }
} 

//第四步: 测试调用Bean
{
    @Autowired
    AService aService;

    @PostConstruct
    public void init(){
        aService.aCallB();
    }
}

只有调用了bean才能触发拦截器: 

2.过滤器和拦截器区别:

Filter

Interceptor

Summary

Filter 接口定义在 javax.servlet 包中

接口 HandlerInterceptor 定义在org.springframework.web.servlet 包中

Filter 定义在 web.xml 中

Filter在只在 Servlet 前后起作用。Filters 通常将 请求和响应(request/response) 当做黑盒子,Filter 通常不考虑servlet 的实现。

拦截器能够深入到方法前后、异常抛出前后等,因此拦截器的使用具有更大的弹性。允许用户介入(hook into)请求的生命周期,在请求过程中获取信息,Interceptor 通常和请求更加耦合。

在Spring构架的程序中,要优先使用拦截器。几乎所有 Filter 能够做的事情, interceptor 都能够轻松的实现

Filter 是 Servlet 规范规定的。

而拦截器既可以用于Web程序,也可以用于Application、Swing程序中。

使用范围不同

Filter 是在 Servlet 规范中定义的,是 Servlet 容器支持的。

而拦截器是在 Spring容器内的,是Spring框架支持的。

规范不同

Filter 不能够使用 Spring 容器资源

拦截器是一个Spring的组件,归Spring管理,配置在Spring文件中,因此能使用Spring里的任何资源、对象,例如 Service对象、数据源、事务管理等,通过IoC注入到拦截器即可

Spring 中使用 interceptor 更容易

Filter 是被 Server(like Tomcat) 调用

Interceptor 是被 Spring 调用

因此 Filter总是优先于interceptor执行

3.Spring Boot下Servlet、Filter等注册方法:

  1. 使用@WebFilter、@WebServlet、@WebListener注解来标识类
  2. 使用FilterRegistrationBean、ServletRegistrationBean来对Filter、Servlet进行自定义注册
  3. 使用@Bean来自动添加,添加后默认的过滤路径为 /*

2.1 @WebFilter或@WebServlet方式

  • 可以指定拦截规则比如: /*,但无法指定过滤器的顺序
  • @WebFilter注解要想生效必须在启动类上加上@ServletComponentScan注解
  • Servlet3.0中,监听器的配置可以直接在代码中通过@WebListener
    注解来完成

@WebFilter:

/**
 * @description @WebFilter 注解要想生效必须在启动类上加上@ServletComponentScan注解
 * 拦截规则是 /*,但无法制定过滤器的顺序
 **/
@WebFilter(urlPatterns = "/*")
public class MyFilter implements Filter {
	@Override
	public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
		filterChain.doFilter(servletRequest,servletResponse);
	}
}

 @WebServlet:

    @WebServlet
    public class MyServlet implements Servlet {

        @Override
        public void init(ServletConfig servletConfig) throws ServletException {

        }

        @Override
        public ServletConfig getServletConfig() {
            return null;
        }

        @Override
        public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {

        }

        @Override
        public String getServletInfo() {
            return null;
        }

        @Override
        public void destroy() {

        }
    }






    @WebServlet
    public class MyHttpServlet extends HttpServlet {

        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            super.doGet(req, resp);
        }

        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            super.doPost(req, resp);
        }
    }

2.2  @Bean方式

  • 可以指定优先级顺序,但拦截规则只能是 /*
@Configuration
@Order(-1)
public class BeanFilter implements Filter {
	@Override
	public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

		filterChain.doFilter(servletRequest,servletResponse);
	}
}

2.3 FilterRegistrationBean方式(推荐)

    public FilterRegistrationBean<MyFilter> filterRegistrationBean() {
        FilterRegistrationBean<MyFilter> registrationBean = new FilterRegistrationBean<>();
        // 设置自己的过滤器
        registrationBean.setFilter(new MyFilter());
        // 设置自定义的拦截规则
        registrationBean.addUrlPatterns("/*");
        // 设置拦截器的顺序
        registrationBean.setOrder(1);
        // 是否启用
        registrationBean.setEnabled(true);
        return registrationBean;
    }
    @Bean
    public ServletRegistrationBean<MyHttpServlet> servletRegistrationBean() {
        ServletRegistrationBean<MyHttpServlet> registrationBean = new FilterRegistrationBean<>();
        registrationBean.setServlet(new MyHttpServlet());
        // 设置自定义的拦截规则
        registrationBean.addUrlMappings("/**");
        // 设置拦截器的顺序
        registrationBean.setOrder(1);
        // 是否启用
        registrationBean.setEnabled(true);
        return registrationBean;
    }

参考:

Springboot过滤器注册的三种方式_springboot 注册过滤器-CSDN博客

SpringBoot配置Servlet的两种方式_springbootjspviewservletconfig-CSDN博客

谈谈 Spring 的过滤器和拦截器 - fuxing. - 博客园

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值