过滤器、监听器、拦截器

目录

一、 主要内容

二、 过滤器

2.1 介绍

2.2 实现

MyFilter01

MyFilter02

MyServlet01

MyServlet02

2.3 说明

2.4 执行顺序

1. 使用 web.xml

2. 使用注解和@Order

3. 使用FilterRegistrationBean

2.5字符乱码

三、监听器

3.1介绍

3.2实现

3.3在线人数统计

OnlineListener

OnlineServlet2

四、拦截器

4.1介绍

4.2实现方式

1.实现HandlerInterceptor接口

2.实现WebRequestInterceptor接口

3.继承HandlerInterceptorAdapter类

4.注册拦截器

4.3解决的问题

4.4与Spring Boot的集成

4.4执行顺序控制

4.5身份验证实例

步骤一:创建拦截器

步骤二:配置拦截器

步骤三:测试

注意事项

五、过滤器和拦截器区别 (面试常问)

六、如何理解"拦截器只能拦截部分web请求"

1.拦截器的作用范围

2.为什么拦截器不能拦截所有Web请求?

3.如何拦截所有Web请求?


一、 主要内容

过滤器(Filter)监听器(Listener)拦截器(Interceptor)
关注点web请求系统级别参数、对象Action(部分Web请求)
实现方式函数回调事件Java反射机制
应用场景设置字符编码统计网站在线人数拦截未登录用户
URL级别的权限访问控制清楚过期session审计日志
过滤敏感词汇
压缩响应信息
是否依赖Servlet容器
Servlet提供的支持Filter接口ServletRequestListener HttpSessionListener ServletContextListener
Spring提供的支持HandlerInterceptor WebRequestInterceptor HandlerInterceptorAdapter
级别系统级别系统级别非系统级别

二、 过滤器

2.1 介绍

  • Filter 即为过滤,用于在 Servlet 之外对 Request或者 Response 进行修改。

  • 它主要用于对用户请求进行预处 ,也可以对 HtpServletResponse 进行后处理

  • 使用 Filter 的完整流程: Filter 对用户请求进行预处理,接着将请求交给 Servlet 进行处理并生成响应,最后 Filter 再对服务器响应进行后处理。

  • 在一个 web 应用中,可以开发编写多个 Filter,这些 Filter 组合起来称之为一个 Filter 链

若是一个过滤器链:先配置先执行(请求时的执行顺序);响应时:以相反的顺序执行

在 HttpServletRequest 到达 Servlet 之前拦截客户的HttpServletRequest。根据需要检查 HttpServletRequest,也可修改 HttpServletRequest 头和数据。 在HttpServletResponse 到达客户端之前,拦截 HttpServletResponse。 根据需要检查HttpServletResponse,也可修改 HttpServletResponse头和数据

2.2 实现

  • 通过实现javax.servlet.Fileter的接口来实现一个过滤器。

  • 其中定义了 三个方法:init(),doFilter(),destroy(),分别在相应的时机执行。后期观察生命周期。

  • Filter 的实现只需要两步:

    • 1:编写 java 类实现 Filter接口,并实现其 doFilter 方法

    • 2:通过@WebFilter注解设置它所能拦截的资源。

    • filterChain.doFilter(servletRequest, servletResponse); 放行

/*/**

在Spring MVC框架中,配置拦截器(Interceptor)的路径模式时,/*/**这两个通配符有以下区别:

  • /*

    • 匹配一级目录下的所有请求路径。

    • 只匹配直接跟在指定路径后面的第一级子路径。

    例如,如果配置为 /user/*,那么它会匹配 /user/john 或 /user/admin,但不会匹配 /user/profile/edit。

  • /**

    • 匹配任意多级目录下的所有请求路径。

    • 它可以匹配任何深度的子路径。

    例如,如果配置为 /user/,那么它会匹配 /user/john、/user/admin、/user/profile/edit 等等。

    总结来说,/*只匹配直接下一层的路径,而/**可以匹配所有层级的路径,包括直接下一层和更深层次的路径

    在实际应用中,如果你想要对整个应用程序的所有请求进行拦截,通常会选择使用 /** ,因为它提供了更全面的覆盖。而 /* 更适合需要精细控制某些特定一级目录下的请求的情况。

MyFilter01
package com.dev.filter;
​
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
​
/**
 * 实现过滤器
 * 1. 实现javax.servlet.Filter接口
 * 2. 重写方法
 * 3. 在doFilter方法中编写过滤逻辑(控制资源访问)
 * 4,配置过滤器,设置拦截路径
 */
// 拦截所有资源
@WebFilter("/myServlet01")
public class MyFilter01 implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
​
        // 处理请求数据
        System.out.println("filter01start ");
​
        filterChain.doFilter(servletRequest, servletResponse);
​
        // 处理响应数据
        System.out.println("filter01end");
    }
​
    @Override
    public void destroy() {
​
    }
}
MyFilter02
package com.dev.filter;
​
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
​
/**
 * 实现过滤器
 * 1. 实现javax.servlet.Filter接口
 * 2. 重写方法
 * 3. 在doFilter方法中编写过滤逻辑(控制资源访问)
 * 4,配置过滤器,设置拦截路径
 */
// 拦截所有资源
@WebFilter("/myServlet02")
public class MyFilter01 implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
​
        // 处理请求数据
        System.out.println("filter02start ");
​
        filterChain.doFilter(servletRequest, servletResponse);
​
        // 处理响应数据
        System.out.println("filter02end");
    }
​
    @Override
    public void destroy() {
​
    }
}
​
MyServlet01
package com.dev.filter;
​
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import java.io.IOException;
​
@WebServlet("/myServlet01")
public class MyServlet01 extends HttpServlet {
    @Override
    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
        System.out.println("servlet01......");
    }
}
​
MyServlet02
package com.dev.filter;
​
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import java.io.IOException;
​
@WebServlet("/myServlet02")
public class MyServlet02 extends HttpServlet {
    @Override
    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
        System.out.println("servlet02......");
    }
}

注意

  • 定义两个拦截器

    • MyFilter01 @WebFilter("/myServlet")

    • MyFilter02 @WebFilter("/*)

  • 定义两个Servlet:

    • MyServlet01 @WebServlet("/myServlet")

    • MyServlet02 @WebServlet("/myServlet02")

访问

  • /myServlet02 ------ filter02start ==>servlet02==>filter02end

  • /myServlet ------ filter01start ==>filter02start ==>servlet01==>filter02end==>filter01end

2.3 说明

  • 过滤器

    • 在请求到达资源之前,过滤器会进行预处理(处理request);在响应到达客户端之前,过滤器会进行后处理(处理response)

  • 过滤器链

    • 当存在多个过滤器时,先配置的先执行(如果没有配置文件,则按照字母排序)

      • 过滤器1、过滤器2、过滤器3

        • 当请求访问资源时,过滤器执行的顺序是1->2->3;

        • 到达资源后,响应的顺序为 3->2->1;

2.4 执行顺序

1. 使用 web.xml

过滤器的执行顺序就是它们在web.xml中声明的顺序。最先声明的过滤器将最先执行,而最后声明的过滤器将在响应阶段最后执行

<!-- web.xml -->
<filter>
    <filter-name>AuthFilter</filter-name>
    <filter-class>com.example.AuthFilter</filter-class>
</filter>
​
<filter-mapping>
    <filter-name>AuthFilter</filter-name>
    <url-pattern>/secure/*</url-pattern>
</filter-mapping>
​
<filter>
    <filter-name>LoggingFilter</filter-name>
    <filter-class>com.example.LoggingFilter</filter-class>
</filter>
​
<filter-mapping>
    <filter-name>LoggingFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>
​

执行顺序说明

  • 对于所有请求,LoggingFilter都会被触发,因为它匹配所有URL模式。

  • 对于以/secure/开头的请求,除了LoggingFilter之外,AuthFilter也会被触发。

  • 因为AuthFilter在web.xml中先于LoggingFilter声明,所以对于匹配/secure/的请求,AuthFilter会先于LoggingFilter执行。

  • 对于非/secure/的请求,仅LoggingFilter会被执行。

因此,即使过滤器处理不同的URL模式,它们的执行顺序仍然基于配置文件中的声明顺序。

2. 使用注解和@Order

在Spring框架中,可以使用@WebFilter注解结合@Order注解来指定过滤器的执行顺序。@Order注解需要一个整数参数,数值越小的过滤器将越早执行

@Order(1)
@WebFilter(urlPatterns = "/*")
public class FirstFilter implements Filter {
    // ...
}
​
@Order(2)
@WebFilter(urlPatterns = "/*")
public class SecondFilter implements Filter {
    // ...
}

3. 使用FilterRegistrationBean

在Spring Boot或Spring MVC中,你也可以通过FilterRegistrationBean在配置类中注册过滤器

@Configuration
public class FilterConfig {
​
    @Bean
    public FilterRegistrationBean<FirstFilter> firstFilterRegistration() {
        FilterRegistrationBean<FirstFilter> registration = new FilterRegistrationBean<>();
        registration.setFilter(new FirstFilter());
        registration.addUrlPatterns("/*");
        registration.setOrder(1);
        return registration;
    }
​
    @Bean
    public FilterRegistrationBean<SecondFilter> secondFilterRegistration() {
        FilterRegistrationBean<SecondFilter> registration = new FilterRegistrationBean<>();
        registration.setFilter(new SecondFilter());
        registration.addUrlPatterns("/*");
        registration.setOrder(2);
        return registration;
    }
}

2.5字符乱码

请求Tomcat7及以下版本Tomcat8及以上版本
POST乱码,需要处理乱码,需要处理
GET乱码,需要处理不会乱码,无需处理

处理

  • POST

    • request.setCharacterEncoding("UTF-8");

  • GET (服务器版本在 Tomcat7及以下版本)

    • 得到请求类习惯

    • 得到服务器版本信息

    • 判断请求为GET且版本小于8

    • 处理乱码

package com.dev.filter;
​
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
​
/**
 * 请求乱码统一处理
 *  tomcat8及以上版本 POST请求乱码问题
 *  tomecat7以下版本 POST/GET请求乱码问题
 */
@WebFilter("/**")
public class AEncodingFilter implements Filter {
    
    public AEncodingFilter(){
    
    }
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    
    }
    
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        // 基于HTTP
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        
        // 处理请求乱码问题
        request.setCharacterEncoding("UTF-8");
        
        // 放行
        filterChain.doFilter(request, response);
        
    }
    
    @Override
    public void destroy() {
    
    }
}

三、监听器

3.1介绍

web 监听器是Servlet 中一种的特殊的类,能帮助开发者监听 web 中的特定事件,比如 ServletcontextHttpSession,ServletRequest 的创建和销毁;变量的创建、销毁和修改等。 可以在某些动作前后增加处理,实现监控。例如可以用来统计在线人数等。

3.2实现

监听器有三类8种:

  • 监听生命周期

    • ServletRequestListener

    • HttpSessionListener

    • ServletContextListener

  • 监听值的变化

    • ServletRequestAttributeListener

    • HttpSessionAttributeListener

    • ServletContextAttributeListener

  • 针对 session 中的对象

    • 监听 session 中的 java 对象(javaBean),是javaBean 直接实现监听器 的接口

3.3在线人数统计

OnlineListener
package com.dev.listener;
​
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
​
/**
 * 在线人数统计
 */
@WebListener
public class OnlineListener implements HttpSessionListener {
    
    // 得到在线人数
    public static int onlineCount = 0;
    
    /**
     * 当有新的session创建时,在线人数加一
     * @param httpSessionEvent
     */
    @Override
    public void sessionCreated(HttpSessionEvent httpSessionEvent) {
        onlineCount++;
        
        // 将在线人数放入session作用域中
        // httpSessionEvent.getSession().setAttribute("onlineCount", onlineCount);
        // 将在线任务放入application作用域中
        httpSessionEvent.getSession().getServletContext().setAttribute("onlineCount", onlineCount);
    }
    
    /**
     * 当session销毁时,在线人数减一
     * @param httpSessionEvent
     */
    @Override
    public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
        onlineCount--;
        // 将在线人数放入session作用域中
        // httpSessionEvent.getSession().setAttribute("onlineCount", onlineCount);
        // 将在线任务放入application作用域中
        httpSessionEvent.getSession().getServletContext().setAttribute("onlineCount", onlineCount);
    }
}
​
OnlineServlet2
package com.dev.listener;
​
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
​
/**
 * 在线任务统计
 */
@WebServlet("/online")
public class OnlineServlet2 extends HttpServlet {
    
    @Override
    public void service(HttpServletRequest req, HttpServletResponse res) throws IOException {
        
        //得到动作
        String action = req.getParameter("action");
        if ("logout".equals(action)) {
            // 退出
            req.getSession().invalidate();
            return;
        }
        
        // 得到当前访问的ip
        String ip = req.getRemoteAddr();
        System.out.println("当前访问的ip为:" + ip );
        
        
        // 获取session作用域中的在线人数
        // Integer onlineCount =(Integer) req.getSession().getAttribute("onlineCount");
        // 获取application作用域中的在线人数
        Integer onlineCount =(Integer) req.getSession().getServletContext().getAttribute("onlineCount");
        
        // 响应数据 在页面中显示人数
        res.setContentType("text/html;charset=utf-8");
        res.getWriter().write("当前在线人数为:" + onlineCount+"<a href='myServlet03?action=logout'>退出</a>");
        res.getWriter().flush();
        res.getWriter().close();
    }
}

四、拦截器

4.1介绍

拦截器(Interceptor)是Java Web应用中的一种设计模式,主要用于在请求到达目标组件(如控制器)之前或响应离开目标组件之后执行一些特定的逻辑。在Spring框架中,拦截器是AOP(面向切面编程)的一个应用,可以用来实现诸如权限验证、日志记录、事务管理、性能监控等功能。

4.2实现方式

1.实现HandlerInterceptor接口

在Spring MVC中,拦截器可以通过实现HandlerInterceptor接口来创建

该接口包含三个方法:

  • preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception: 在请求处理之前调用,可以用于权限验证、数据校验等。如果返回false,则请求处理停止,不会继续执行后续的拦截器或控制器方法。

  • postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception: 在请求处理之后,但在视图渲染之前调用,可以用于日志记录、缓存处理等。

  • afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception: 在视图渲染之后调用,可以用于资源清理等操作。

   
import org.springframework.web.servlet.HandlerInterceptor;
   import org.springframework.web.servlet.ModelAndView;
​
   import javax.servlet.http.HttpServletRequest;
   import javax.servlet.http.HttpServletResponse;
​
   public class CustomInterceptor implements HandlerInterceptor {
​
       @Override
       public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
           // 在这里实现你的逻辑
           return true;
       }
​
       @Override
       public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
           // 在这里实现你的逻辑
       }
​
       @Override
       public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
           // 在这里实现你的逻辑
       }
   }
   
2.实现WebRequestInterceptor接口

这个接口与HandlerInterceptor类似,但是它在更早的阶段被调用,甚至在请求映射之前。这使得它适合做一些全局的初始化工作。实现WebRequestInterceptor接口需要重写以下方法:

  • preHandle(WebRequest request):在请求处理之前调用。

  • postHandle(WebRequest request, ModelMap model):在请求处理之后调用。

  • afterCompletion(WebRequest request, Exception ex):在请求处理完成之后调用。

3.继承HandlerInterceptorAdapter类

如果你不想实现HandlerInterceptor接口中的所有方法,可以继承HandlerInterceptorAdapter类,这是一个适配器类,它为HandlerInterceptor接口提供了默认实现,你只需要重写你感兴趣的方法即可。

  
 import org.springframework.web.servlet.HandlerInterceptorAdapter;
​
   public class CustomInterceptor extends HandlerInterceptorAdapter {
​
       @Override
       public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
           // 在这里实现你的逻辑
           return true;
       }
   }
   
4.注册拦截器

一旦你创建了拦截器,就需要在Spring配置中注册它。这可以通过实现WebMvcConfigurer接口的addInterceptors方法来完成。

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 {
​
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new CustomInterceptor())
                .addPathPatterns("/**"); // 指定拦截器应用的所有请求
    }
}
​

4.3解决的问题

拦截器可以解决多种问题:

  • 权限控制:在请求到达控制器之前验证用户权限。

  • 日志记录:记录请求和响应的详细信息,有助于调试和审计。

  • 性能监控:计算请求处理时间,监控应用性能。

  • 数据校验:检查请求参数的有效性,防止非法请求。

  • 资源清理:确保在请求处理完毕后释放资源。

4.4与Spring Boot的集成

在Spring Boot中使用拦截器,可以通过以下步骤:

  • 创建拦截器类并实现HandlerInterceptor接口。

  • 在Spring配置类中注册拦截器,通常通过实现WebMvcConfigurer接口的addInterceptors方法。

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
​
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
​
public class MyInterceptor implements HandlerInterceptor {
​
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("Pre-handle logic...");
        return true; // 返回true表示继续处理请求
    }
​
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("Post-handle logic...");
    }
​
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {java
        System.out.println("After completion logic...");
    }
}
​

接下来,在Spring配置类中注册这个拦截器

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 {
​
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new MyInterceptor())
                .addPathPatterns("/**"); // 指定拦截器应用的所有请求
    }
}
​

4.4执行顺序控制

拦截器的执行顺序可以通过以下方式控制:

  • 配置顺序:在addInterceptors方法中,拦截器的添加顺序决定了它们的执行顺序

  • 实现Ordered接口:让拦截器实现Ordered接口并重写getOrder()方法,返回一个整数,数值越小,优先级越高

import org.springframework.core.Ordered;
import org.springframework.web.servlet.HandlerInterceptor;
​
public class MyInterceptor implements HandlerInterceptor, Ordered {
​
    @Override
    public int getOrder() {
        return 1; // 优先级高于其他返回值大于1的拦截器
    }
​
    // 其他方法...
}

4.5身份验证实例

假设我们有一个Spring Boot应用,其中某些资源是受保护的,只有经过身份验证的用户才能访问。我们可以使用拦截器来检查用户的会话状态,确保只有已登录的用户才能访问这些资源。

步骤一:创建拦截器

首先,我们需要创建一个拦截器类,实现HandlerInterceptor接口,并覆盖preHandle方法来执行身份验证逻辑。


import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
​
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
​
@Component
public class AuthenticationInterceptor implements HandlerInterceptor {
​
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 从session中获取用户信息
        HttpSession session = request.getSession(false);
        if (session != null) {
            Object user = session.getAttribute("user");
            if (user != null) {
                // 用户已登录,允许请求继续
                return true;
            }
        }
        
        // 用户未登录,重定向到登录页面
        response.sendRedirect(request.getContextPath() + "/login");
        return false;
    }
​
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        // 这里可以处理请求后的逻辑,例如日志记录
    }
​
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // 这里可以处理请求完成后的清理工作
    }
}

步骤二:配置拦截器

接下来,我们需要在Spring配置类中注册这个拦截器,并指定它应该应用于哪些URL。

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 {
​
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new AuthenticationInterceptor())
                .addPathPatterns("/protected/*") // 指定拦截器应用于/protected下的所有请求
                .excludePathPatterns("/protected/login", "/protected/logout"); // 排除登录和登出路经
    }
}
​
步骤三:测试

现在,每当有请求尝试访问/protected/*下的资源时,AuthenticationInterceptor都会被调用。如果用户没有登录,他们将被重定向到登录页面。如果已经登录,则请求将继续正常处理。

注意事项
  • 确保登录和登出路由被排除在拦截器之外,否则用户将无法访问这些页面。

  • 考虑到安全性,可能还需要在拦截器中加入更复杂的认证逻辑,例如检查JWT令牌等。

  • 如果应用中有多个拦截器,它们的执行顺序可以通过实现Ordered接口并重写getOrder()方法来控制。

通过这种方式,拦截器可以帮助我们在Spring Boot应用中实现细粒度的访问控制,提高应用的安全性和健壮性。

五、过滤器和拦截器区别 (面试常问)

过滤器(Filter)和拦截器(Interceptor)在Java Web应用程序中扮演着重要的角色,它们用于在请求到达目标组件(如Servlet或JSP)之前或之后执行特定的逻辑。两者都可以在请求过程中介入并可能阻止请求。

尽管它们有相似的功能,但它们在实现机制、作用范围、依赖环境等方面存在显著差异。

  • 实现机制:

    • 过滤器是基于函数回调的,通常通过实现javax.servlet.Filter接口来创建。过滤器会拦截所有进入Servlet容器的请求和响应,并且可以访问HttpServletRequest和HttpServletResponse对象。

    • 拦截器是基于Java的反射机制(动态代理)实现的,通常与框架如Spring MVC一起使用。拦截器可以访问更广泛的上下文信息,比如Spring MVC的ModelAndView对象,以及控制器方法的参数和返回值。

  • 依赖环境:

    • 过滤器依赖于Servlet容器,如Tomcat、Jetty等,因此只能在Web环境中使用。

    • 拦截器不依赖于Servlet容器,可以在任何使用Spring MVC框架的应用中使用,即使是在非Web环境中也可以实现类似的功能。

  • 作用范围:

    • 过滤器可以拦截几乎所有的HTTP请求,包括对静态资源的请求。

    • 拦截器通常只拦截那些由控制器处理的请求,即所谓的“action”请求,不会拦截静态资源请求。

  • 生命周期:

    • 过滤器在Servlet容器启动时初始化,在容器关闭时销毁,每个请求只调用一次doFilter()方法。

    • 拦截器可以多次调用,取决于请求的路径和配置,每次请求可以调用多次拦截器的preHandle()、postHandle()和afterCompletion()方法。

  • 配置方式:

    • 过滤器通过web.xml文件或注解(如@WebFilter)配置。

    • 拦截器通常通过Spring的配置类或XML文件配置。

六、如何理解"拦截器只能拦截部分web请求"

截器主要用于拦截和处理由控制器(Controller)处理的请求,而不是所有的Web请求。

这是因为拦截器的设计初衷是为了处理业务逻辑层面的请求,如权限检查、日志记录、数据预处理等,这些通常与具体的业务操作相关联。

1.拦截器的作用范围

  • 控制器请求:拦截器主要针对由控制器处理的请求,即通过HTTP方法(GET、POST等)调用控制器方法的请求。拦截器可以访问控制器方法的参数、返回值、以及模型和视图对象。

  • 静态资源请求:拦截器通常不会拦截静态资源(如CSS、JavaScript、图片等)的请求,因为这些请求不涉及业务逻辑,而是直接由Web服务器或Servlet容器处理。

  • 非控制器路径:对于不通过控制器处理的请求,如直接指向特定资源或Servlet的请求,拦截器也不会进行拦截。

2.为什么拦截器不能拦截所有Web请求?

  • 设计目的:拦截器的设计目的是为了在业务逻辑层面上进行干预,而并非处理底层的网络通信或静态资源的分发。

  • 性能考虑:如果拦截器拦截所有请求,包括静态资源请求,可能会引入不必要的性能开销,因为静态资源的处理通常非常快速,而拦截器的介入可能会增加延迟。

  • 框架限制:Spring MVC的拦截器机制是基于控制器的,因此它天然不适合处理那些不由控制器处理的请求。

3.如何拦截所有Web请求?

  • 如果需要对所有Web请求进行处理,包括静态资源请求,那么应该使用过滤器(Filter)过滤器是Servlet容器级别的,它可以拦截所有进入容器的请求,无论这些请求是针对控制器还是静态资源。

  • 过滤器的实现和配置与拦截器不同,它通过实现javax.servlet.Filter接口来创建,并在web.xml文件或使用@WebFilter注解来配置。

总结来说,拦截器在Spring MVC中主要用于处理与业务逻辑相关的请求,而过滤器则可以用于处理所有类型的Web请求,包括静态资源请求。

  • 7
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

伏颜.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值