过滤器&拦截器

80 阅读5分钟

过滤器(Filter)和拦截器(Interceptor)是在Java Web开发中用于处理HTTP请求和响应的两个重要的组件。它们的作用相似,都可以用于在请求到达目标资源之前或响应返回到客户端之前进行一些处理

过滤器

  1. 工作位置: 过滤器是Servlet规范中的一部分,它在Servlet容器内部工作。过滤器可以拦截所有的请求和响应,包括Servlet、JSP和静态资源等。
  2. 依赖于Servlet API: 过滤器依赖于Servlet API,通常通过javax.servlet.Filter接口实现。过滤器的配置在web.xml中完成。
  3. 生命周期: 过滤器的生命周期由Servlet容器管理,包括初始化、执行过滤操作和销毁。
  4. FilterChain: 过滤器链(FilterChain)用于按照顺序执行一组过滤器。在过滤器链中,每个过滤器都可以对请求和响应进行处理,并决定是否将请求继续传递给下一个过滤器或目标资源。

拦截器

  1. 工作位置: 拦截器是Spring框架的一部分,它在Spring的上下文中工作。拦截器只能拦截Spring MVC的请求。
  2. 依赖于Spring框架: 拦截器是Spring框架的一部分,通常通过实现org.springframework.web.servlet.HandlerInterceptor接口实现。拦截器的配置在Spring的配置文件或通过注解完成。
  3. 生命周期: 拦截器的生命周期由Spring容器管理,它被实例化并注入到Spring容器中。
  4. HandlerInterceptor: 拦截器通过HandlerInterceptor接口提供了在处理请求之前、处理请求时和处理请求之后的钩子方法,让开发者能够执行一些自定义的逻辑。

总结比较

  • 过滤器是Servlet规范的一部分,而拦截器是Spring框架的一部分。
  • 过滤器可以拦截所有的请求和响应,包括Servlet、JSP和静态资源;拦截器只能拦截Spring MVC的请求。
  • 过滤器依赖于Servlet API,而拦截器依赖于Spring框架。
  • 过滤器的配置通常在web.xml中完成,而拦截器的配置通常在Spring的配置文件或通过注解完成。
  • 过滤器的生命周期由Servlet容器管理,而拦截器的生命周期由Spring容器管理。

过滤器例子

一个常见的过滤器使用例子是实现字符编码的过滤器,用于确保在整个应用程序中的请求和响应都使用相同的字符编码,以防止乱码问题。

`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 CharacterEncodingFilter implements Filter {

private String encoding;

@Override
public void init(FilterConfig filterConfig) throws ServletException {
        // 从web.xml中获取配置的字符编码
        encoding = filterConfig.getInitParameter("encoding");
        if (encoding == null) {
            encoding = "UTF-8"; // 默认使用UTF-8
        }
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        // 设置请求和响应的字符编码
        request.setCharacterEncoding(encoding);
        response.setCharacterEncoding(encoding);

        // 继续执行过滤器链
        chain.doFilter(request, response);
    }

    @Override
    public void destroy() {
        // 在销毁过滤器时执行一些清理操作
    }
}

一个常见的过滤器使用例子是实现字符编码的过滤器,用于确保在整个应用程序中的请求和响应都使用相同的字符编码,以防止乱码问题。

以下是一个简单的字符编码过滤器的例子:

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 CharacterEncodingFilter implements Filter {

    private String encoding;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // 从web.xml中获取配置的字符编码
        encoding = filterConfig.getInitParameter("encoding");
        if (encoding == null) {
            encoding = "UTF-8"; // 默认使用UTF-8
        }
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        // 设置请求和响应的字符编码
        request.setCharacterEncoding(encoding);
        response.setCharacterEncoding(encoding);

        // 继续执行过滤器链
        chain.doFilter(request, response);
    }

    @Override
    public void destroy() {
        // 在销毁过滤器时执行一些清理操作
    }
}

在上述例子中,CharacterEncodingFilter是一个实现了javax.servlet.Filter接口的过滤器。该过滤器的作用是在处理请求时设置请求和响应的字符编码,以确保它们都使用相同的编码。

配置这个过滤器需要在web.xml文件中添加如下的配置:

`
<filter>
    <filter-name>CharacterEncodingFilter</filter-name>
    <filter-class>com.example.CharacterEncodingFilter</filter-class>
    <init-param>
        <param-name>encoding</param-name>
        <param-value>UTF-8</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>CharacterEncodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>
`

这个配置告诉Servlet容器,将CharacterEncodingFilter应用于所有的请求 (<url-pattern>/*</url-pattern>),并使用UTF-8作为字符编码。

拦截器例子

一个常见的拦截器使用例子是日志记录。你可以创建一个拦截器,用于记录每个请求的详细信息,例如请求的URL、请求参数、处理时间等。以下是一个简单的日志记录拦截器的例子:

首先,创建一个实现HandlerInterceptor接口的拦截器类:

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

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

public class LoggingInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 在处理请求之前执行,可以进行一些预处理操作
        System.out.println("Request URL: " + request.getRequestURL());
        System.out.println("Request Parameters: " + request.getParameterMap());
        System.out.println("Handling Time: " + System.currentTimeMillis());
        return true; // 返回true表示继续执行后续的拦截器和处理器
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        // 在处理请求后执行,但在视图渲染之前(Controller方法调用之后)
        System.out.println("Handling Time: " + System.currentTimeMillis());
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // 在整个请求完成之后执行,包括视图渲染完成后
        System.out.println("Handling Time: " + System.currentTimeMillis());
    }
}

然后,在Spring配置文件中配置拦截器:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Bean
    public LoggingInterceptor loggingInterceptor() {
        return new LoggingInterceptor();
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 注册拦截器,并指定拦截的路径
        registry.addInterceptor(loggingInterceptor()).addPathPatterns("/**");
    }
}

在上述例子中,LoggingInterceptor实现了HandlerInterceptor接口,通过覆写preHandlepostHandleafterCompletion方法,可以在请求的不同生命周期阶段执行相应的操作。在WebConfig类中,通过addInterceptors方法注册拦截器,并指定了拦截的路径为"/**",表示拦截所有的请求。