Java中拦截器和过滤器有什么区别?

拦截器(Interceptors)和过滤器(Filters)是两种用于处理求和响应的中间件组件

发布:2023-10-23     分类:闲者编程     标签:Java中间件
2023 - 10 - 22

在Java中,拦截器(Interceptors)和过滤器(Filters)是两种用于处理求和响应的中间件组件,它们在应用程序中起到类似的作用,但有一些关键区别。

总体来说,过滤器和拦截器在功能上有一些重叠,但它们的使用场景和执行时机略有不同。通常,如果你需要在求的原始数据上进行处理,如字符编码转换、求日志记录等,那么使用过滤器是更合适的选择。而如果你更关心对Controller方法的拦截和处理,例如权限检查、日志记录等,那么使用拦截器是更为合适的。

一. 过滤器(Filters)

过滤器是Servlet规范的一部分,它们工作在Servlet容器级别。 过滤器通常用于对求和响应进行预处理和后处理,例如修改求参数、编码解码、日志记录、安全检查等。 过滤器在web.xml文件中配置,并通过URL模式指定过滤器应用于哪些求。

1. SpringBoot中使用

创建一个过滤器类,与传统的Servlet过滤器类似:

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.IOException;

public class TimingFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // 初始化代码
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        long startTime = System.currentTimeMillis();

        // 继续求处理
        chain.doFilter(request, response);

        long endTime = System.currentTimeMillis();
        System.out.println("Request processed in " + (endTime - startTime) + " ms");
    }

    @Override
    public void destroy() {
        // 清理资源
    }
}

然后,在Spring Boot应用程序中,你可以直接将过滤器注册为FilterRegistrationBean:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
public class MyApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }

    @Bean
    public FilterRegistrationBean<TimingFilter> timingFilter() {
        FilterRegistrationBean<TimingFilter> registrationBean = new FilterRegistrationBean<>();
        registrationBean.setFilter(new TimingFilter());
        registrationBean.addUrlPatterns("/*"); // 设置过滤器的URL模式
        return registrationBean;
    }
}

2. Servlet中使用

创建一个简单的过滤器,用于记录求处理时间:

import javax.servlet.*;
import java.io.IOException;

public class TimingFilter implements Filter {
    public void init(FilterConfig filterConfig) throws ServletException {
        // 初始化代码
    }

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        long startTime = System.currentTimeMillis();

        // 继续求处理
        chain.doFilter(request, response);

        long endTime = System.currentTimeMillis();
        System.out.println("Request processed in " + (endTime - startTime) + " ms");
    }

    public void destroy() {
        // 清理资源
    }
}

在web.xml中配置过滤器:

<filter>
    <filter-name>TimingFilter</filter-name>
    <filter-class>com.example.TimingFilter</filter-class>
</filter>

<filter-mapping>
    <filter-name>TimingFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

二. 拦截器(Interceptors)

拦截器是Spring框架的一部分,它们工作在Spring MVC框架级别。 拦截器用于在求进入Controller之前和响应返回客户端之前执行一些操作,例如身份验证、日志记录、性能监控等。 拦截器通过实现Spring的HandlerInterceptor接口来创建,并在Spring配置文件中进行配置。

1. SpringBoot中使用

添加一个拦截器类:

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class TimingInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        long startTime = System.currentTimeMillis();
        request.setAttribute("startTime", startTime);
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        long endTime = System.currentTimeMillis();
        long startTime = (long) request.getAttribute("startTime");
        System.out.println("Request processed in " + (endTime - startTime) + " ms");
    }
}

在应用程序的主类上使用@SpringBootApplication注解,并注册拦截器:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@SpringBootApplication
public class MyApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }

    @Bean
    public TimingInterceptor timingInterceptor() {
        return new TimingInterceptor();
    }

    @Bean
    public WebMvcConfigurer webMvcConfigurer() {
        return new WebMvcConfigurer() {
            @Override
            public void addInterceptors(InterceptorRegistry registry) {
                registry.addInterceptor(timingInterceptor());
            }
        };
    }
}

2. Spring中使用

创建一个简单的拦截器,用于记录求处理时间:

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class TimingInterceptor implements HandlerInterceptor {
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        long startTime = System.currentTimeMillis();
        request.setAttribute("startTime", startTime);
        return true;
    }

    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                           ModelAndView modelAndView) throws Exception {
        long endTime = System.currentTimeMillis();
        long startTime = (long) request.getAttribute("startTime");
        System.out.println("Request processed in " + (endTime - startTime) + " ms");
    }

    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
                                Exception ex) throws Exception {
        // 在求完成后执行一些清理操作
    }
}

在Spring配置文件中配置拦截器:

<mvc:interceptors>
    <bean class="com.example.TimingInterceptor" />
</mvc:interceptors>

三. 拦截器和过滤器有什么区别

拦截器(Interceptor)和过滤器(Filter)都是在Java Web应用程序中用于对求进行预处理和后处理的组件,但它们之间有一些区别:

1. 触发时机

过滤器:在Servlet容器中,过滤器是最先执行的组件。当求进入Web应用程序时,过滤器会在Servlet之前拦截求,并在响应返回给客户端之后再进行处理。

拦截器:拦截器则是在Spring MVC框架中的一部分,它在求到达Spring的DispatcherServlet之后,但在具体的Controller方法执行之前进行拦截。

2. 使用场景:

过滤器:主要用于对求和响应的原始数据进行处理。例如,可以用过滤器来进行求日志记录、字符编码转换、权限验证、求防火墙等操作。

拦截器:拦截器更多地关注于对Controller方法的拦截和处理。它可以在执行Controller方法前后添加一些通用的处理逻辑,如权限检查、日志记录、性能监控等。

3. 执行顺序:

过滤器:可以配置多个过滤器,并且它们之间的执行顺序可以通过配置进行控制。过滤器是按照配置的顺序依次执行的。

拦截器:Spring MVC中的拦截器也可以配置多个,但它们的执行顺序是由拦截器本身决定的。你可以通过实现org.springframework.core.Ordered接口或使用@Order注解来控制拦截器的执行顺序。

4. 依赖框架:

过滤器:是Servlet规范中的一部分,独立于Spring框架。

拦截器:是Spring MVC框架提供的一部分,依赖于Spring框架。

5. 功能范围:

过滤器:可以拦截所有的求和响应,不仅限于Spring MVC求。

拦截器:主要用于拦截Spring MVC中的求。

总结:

过滤器和拦截器都可以用于求和响应的处理,但它们的用途和工作级别不同。 过滤器是Servlet容器级别的组件,而拦截器是Spring框架级别的组件。 过滤器通常用于低层次的任务,如求参数处理和字符编码,而拦截器通常用于高层次的任务,如权限检查和日志记录。

更新:2023-10-23
点击评论
评论区