Try using it in your preferred language.

English

  • English
  • 汉语
  • Español
  • Bahasa Indonesia
  • Português
  • Русский
  • 日本語
  • 한국어
  • Deutsch
  • Français
  • Italiano
  • Türkçe
  • Tiếng Việt
  • ไทย
  • Polski
  • Nederlands
  • हिन्दी
  • Magyar
translation

这是AI翻译的帖子。

제이온

[Spring] Filter、Interceptor、Argument Resolver 是什麼?

  • 写作语言: 韓国語
  • 基准国家: 所有国家 country-flag

选择语言

  • 汉语
  • English
  • Español
  • Bahasa Indonesia
  • Português
  • Русский
  • 日本語
  • 한국어
  • Deutsch
  • Français
  • Italiano
  • Türkçe
  • Tiếng Việt
  • ไทย
  • Polski
  • Nederlands
  • हिन्दी
  • Magyar

durumis AI 总结的文章

  • Filter 是一種 J2EE 標準規格功能,它可以在請求傳遞給 DispatcherServlet 前後,針對所有符合 URL 模式 的請求處理額外任務。Filter 執行於 Web 容器中。Interceptor 是 Spring 提供的技術,它可以在 DispatcherServlet 呼叫控制器前後參照或處理請求和回應。Interceptor 執行於 Spring 上下文 中。
  • Argument Resolver 可以間接地將請求傳入的參數值轉換為所需的物件。
  • Filter 和 Interceptor 在執行位置上有所差異,Filter 執行於 Web 容器中,Interceptor 執行於 Spring 容器中。Filter 以 DispatcherServlet 為基準處理請求,Interceptor 以控制器為基準 處理請求。Argument Resolver 執行於 Interceptor 之後,並返回特定物件。

什麼是过滤器 (Filter)?

过滤器是 J2EE 标准规范功能,它允许在将请求传递到调度程序 Servlet (Dispatcher Servlet) 之前或之后处理与 URL 模式匹配的所有请求的附加操作。也就是说,过滤器由 Tomcat 等 Web 容器而不是 Spring 容器管理,因此它是在请求到达调度程序 Servlet 之前处理请求的。



过滤器 (Filter) 实现

为了添加过滤器,您需要实现 javax.servlet 的 Filter 接口,该接口包含以下三个方法。


  • init 方法
    • 这是一个初始化过滤器对象并将其添加到服务的方法。 Web 容器调用 init 方法一次以初始化过滤器对象,之后所有请求都将通过 doFilter() 方法处理。
  • doFilter 方法
    • 当所有与 URL 模式匹配的 HTTP 请求在传递到调度程序 Servlet 之前由 Web 容器执行,并且在调度程序 Servlet 从客户端返回 HTTP 响应之前由 Web 容器执行。
      doFilter() 的参数是 FilterChain,它允许通过 FilterChain 的 doFilter() 将请求传递给下一个目标。通过在 chain.doFilter() 之前和之后添加我们需要的处理过程,我们可以执行我们想要的处理。
  • destory 方法
    • 这是一个从服务中删除过滤器对象并返回所用资源的方法。它由 Web 容器调用一次,此后不再由 doFilter() 处理。


示例代码 - Servlet 规范

@WebFilter("/*")
public class dolphagoFilter implements Filter {

    @Override
      public void init(FilterConfig filterConfig) throws ServletException {}

    @Override
      public void doFilter(ServletRequest request, ServletResponse response, 
FilterChain filterChain) throws IOException, ServletException {
        // 在这里进行预处理
        request.setCharacterEncoding("UTF-8");
        System.out.println("doFilter() 前....");

        filterChain.doFilter(request, response);

        // 在这里进行后处理
        System.out.println("doFilter() 后....");
      }

    @Override
      public void destroy() {    }


示例代码 - @Component

@Order(1)
@Component
public class CustomFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException { }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
        throws IOException, ServletException {
        chain.doFilter(request, response);
    }

    @Override
    public void destroy() { }


  • @Component:可以将过滤器注册为 Spring Bean。
  • @Order:如果有多个过滤器,则可以定义它们的顺序。
  • 将与 Servlet 规范匹配的过滤器注册为 Spring Bean 后,就可以使用与 Spring 规范匹配的其他 Bean。


示例代码 - @Configuration

@Configuration
public class CustomRegistrationBean {

    @Bean
    public FilterRegistrationBean customFilterBean() {
        FilterRegistrationBean registration = new FilterRegistrationBean<>();
        registration.setFilter(new CustomFilter());
        registration.setOrder(1);
        registration.addUrlPatterns("/api/*");
        return registration;
    }

如果要使过滤器仅在特定 URI 上运行,可以使用 FilterRegistrationBean 将过滤器注册为 Spring Bean。


过滤器 (Filter) 用途

主要负责验证和处理请求参数本身。


  • 与安全相关的通用操作
    • 由于过滤器在 Web 容器中运行,因此可以进行安全检查(XSS、CSRF 防御等),并阻止任何不正确的请求。阻止请求到达 Spring 容器可以提高安全性。
  • 所有请求的日志记录
  • 图像/数据压缩和字符串编码
    • 过滤器实现了在 Web 应用程序中普遍使用功能,例如图像或数据的压缩或字符串编码。
  • ServletRequest 自定义
    • HttpServletRequest 只能读取一次 Body 中的内容。因此,Filter 或 Interceptor 无法读取 Body。要记录 Body,您可以创建一个自定义的 ServletRequest。


拦截器 (Interceptor)

拦截器 (Interceptor) 含义

拦截器 (Interceptor) 不同于 J2EE 标准规范中的过滤器 (Filter),它是 Spring 提供的技术,可以在调度程序 Servlet 调用控制器之前和之后引用或处理请求和响应。也就是说,与在 Web 容器中运行的过滤器不同,拦截器是在 Spring 上下文中运行的。


调度程序 Servlet 通过处理映射查找适当的控制器以进行请求,并将执行链 (HandlerExecutionChain) 返回。因此,如果此执行链注册了一个或多个拦截器,则它将按顺序遍历拦截器以执行控制器,否则将直接执行控制器。


拦截器 (Interceptor) 实现

为了添加拦截器,您需要实现 org.springframework.web.servlet.HandlerInterceptor 接口,该接口包含以下三个方法。


  • preHandle 方法
    • preHandle 方法在调用控制器之前执行。因此,它可以用于在控制器之前处理任何预处理任务或处理和添加请求信息。
    • preHandle 方法的第三个参数 handler 是一个抽象对象,它包含带 @RequestMapping 的方法的信息。
    • preHandle 方法的返回值是 boolean,如果返回值为 true,则将继续执行到下一步,如果返回值为 false,则将停止执行,后续任务(下一个拦截器或控制器)将不会被执行。
  • postHandle 方法
    • postHandle 方法在调用控制器之后执行。因此,它可以用于处理控制器之后的任何后处理任务。
  • afterCompletion 方法
    • afterCompletion 方法顾名思义,在所有工作完成后执行,包括从所有视图生成最终结果。


示例代码

@Component
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 {
    }
}

@Configuration
public class WebMvcConfiguration implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new CustomInterceptor());
        registry.addInterceptor(new LoggingInterceptor());
    }


  • 将创建的拦截器注册为 Bean。
  • 将创建的拦截器注册到 WebMvcConfigurer 接口的 addInterceptors() 方法中。
  • 拦截器将按照在 InterceptorRegistry 中注册的顺序执行。


拦截器 (Interceptor) 用途

主要负责使用服务逻辑处理请求信息的完整性。


  • 身份验证/授权等通用操作
    • 例如,可以在将请求传递到控制器之前检查身份验证或授权等与客户端请求相关的操作。
  • API 调用的日志记录
    • 通过接收到的 HttpServletRequest 和 HttpServletResponse 对象,可以记录客户端的信息。
  • 处理传递给控制器的的数据
    • 可以处理接收到的 HttpServletRequest 和 HttpServletResponse 对象并将其传递给控制器。
  • 模仿 AOP
    • 您可以使用 preHandle() 方法的第三个参数 HandlerMethod 来了解要执行的方法的签名和其他信息,以便决定是否执行逻辑。


过滤器 (Filter) 与拦截器 (Interceptor)

  • 过滤器在 Web 上下文中运行,而拦截器在 Spring 上下文中运行,因此它们的执行时间不同。
  • 过滤器可以处理调度程序 Servlet 的前后,而拦截器可以处理控制器的前后。
  • 如果需要全局处理与 Spring 无关的任务,或者需要验证输入的请求参数本身,或者需要使用 ServletRequest 而不是 HttpServletRequest,则建议使用过滤器。
  • 如果需要在 Spring 级别全局处理与客户端请求相关的任务,或者需要混合使用服务逻辑,则建议使用拦截器。
  • 拦截器可以使用 @ControllerAdvice 和 @ExceptionHandler 处理异常,但过滤器无法使用它们来处理异常。
    • 过滤器通常使用 try~catch 语句将 doFilter() 方法包装起来,以立即处理该时间点发生的异常。


参数解析器

参数解析器含义

参数解析器可以间接地将请求到达控制器时,从请求中提取的值转换为所需的对象。


参数解析器用途

例如,假设请求与 JWT 令牌一起到达。我们需要验证令牌是否有效,然后从令牌中提取 id 并将其转换为登录用户对象。

在这种情况下,如果不使用参数解析器,则需要在每个控制器中实现验证令牌和将令牌转换为登录用户对象的步骤。这样,在需要用户验证的控制器中就会出现重复代码,并且控制器的责任会增加。参数解析器可以解决这些问题。


参数解析器实现

参数解析器可以通过实现 HandlerMethodArgumentResolver 来使用。该接口指定了要实现的以下两个方法。


boolean supportsParameter(MethodParameter parameter);

@Nullable


  • supportsParameter 方法
    • 在要执行 ArgumentResolver 的参数前面创建一个特定注解并将其附加。supportsParameter() 方法检查请求方法的参数是否包含所需的注解,如果包含,则返回 true。
  • resolveArgument 方法
    • 如果 supportsParameter 返回 true,即存在带有特定注解的方法,则该方法是将参数绑定到所需形式并返回该形式信息的方法。


使用参数解析器时,控制器的实现如下。


@GetMapping("/me")
public ResponseEntity findMemberOfMine(@AuthenticationPrincipal LoginMember loginMember) {
    MemberResponse memberResponse = memberService.findMember(loginMember.getId());
    return ResponseEntity.ok().body(memberResponse);


参数解析器与拦截器 (Interceptor) 的区别

  • 参数解析器在拦截器之后执行,当请求到达控制器时,它将从请求中提取的值转换为所需的对象。
  • 另一方面,拦截器在实际控制器执行之前拦截请求,并且无法返回特定对象。它只能返回 boolean 或 void 返回类型。


来源


预期面试问题和答案

什么是过滤器?

过滤器是在将请求传递到调度程序 Servlet 之前或之后,针对与 URL 模式匹配的所有请求处理附加操作的功能,它在 Servlet 容器中运行。


过滤器何时使用?

过滤器可以处理与 Spring 无关的全局任务。或者,当需要验证请求参数本身时使用它。

它主要处理与安全相关的通用操作,所有请求的日志记录,图像/数据压缩和字符串编码,以及 ServletRequest 自定义操作。


什么是拦截器?

拦截器是在调度程序 Servlet 调用控制器之前和之后引用或处理请求和响应的功能,它在 Spring 容器中运行。


拦截器何时使用?

拦截器可以处理与客户端请求相关的全局任务,并且通常在需要调用服务逻辑进行验证时使用。

它主要处理身份验证/授权等通用操作,API 调用的日志记录,以及传递给控制器的数据的处理。


过滤器和拦截器的区别?

过滤器在 Servlet 容器中运行,而拦截器在 Spring 容器中运行。

过滤器可以处理调度程序 Servlet 的前后,而拦截器可以处理控制器的前后。

因此,建议使用过滤器来全局处理与 Spring 无关的任务,而建议使用拦截器来全局处理与客户端请求相关的任务。


什么是参数解析器?

参数解析器是在请求到达控制器时,从请求中提取的值并将其转换为所需对象的功能。


参数解析器何时使用?

当请求与 JWT 令牌一起到达时,可以使用它来验证令牌是否有效,然后从令牌中提取 id 并将其转换为 LoginMember 对象。


拦截器和参数解析器的区别?

参数解析器在请求到达控制器时,将从请求中提取的值转换为所需的对象。另一方面,拦截器无法像这样返回对象,并且它在拦截器执行之后执行。

제이온
제이온
제이온
제이온
[Spring] @Async 使用方法 了解如何使用 Spring @Async 簡化 Java 異步處理的實作。透過 @Async 注解,您可以將同步方法轉換為異步方法,並透過執行緒池設定來提高效率。本文也會探討如何使用 Future、ListenableFuture 和 CompletableFuture 來有效管理異步處理結果。

2024年4月25日

[Java] 反射概念及使用方法 反射是 Java 程式執行時,能夠存取類別資訊並操作類別的 API。它允許在執行時建立類別實例,存取欄位和方法,但可能破壞封裝性並降低效能,因此應謹慎使用。在 Spring 框架等需要動態建立和管理物件的場合,它非常有用。

2024年4月25日

[Effective Java] 項目 1. 考慮使用靜態工廠方法而非建構函式 靜態工廠方法是一種比建構函式更靈活且有效率的建立實例的方法。它們可以具有名稱,並可返回符合特定條件的實例,並可透過快取來提高效能。與單例模式不同,靜態工廠方法可以建立和返回多種類型的實例,並且可以保持彈性,而無需使用反射。

2024年4月27日

[并发] 原子操作:内存栅栏和内存顺序 这篇博文将解释在原子操作中如何考虑内存顺序,以及排序选项的重要性。 它将详细解释各种排序选项,例如 Relaxed、Acquire、Release、AcqRel 和 SecCst,以及每个选项的优缺点, 并提供使用示例代码。
곽경직
곽경직
곽경직
곽경직
곽경직

2024年4月12日

什麼是 JWT (JSON Web Token)? JSON Web Token (JWT) 是一種用於安全傳輸資訊的公開標準,它使用已簽署的 Token 來維持資訊的完整性和安全性。 標頭包含 Token 類型和簽章演算法,載荷包含開發者想要的使用者資訊。已簽署的 JWT 採用無狀態的方式進行會話管理,適用於分散式系統。
Seize the day
Seize the day
Seize the day
Seize the day
Seize the day

2024年3月4日

[React Hook] useState 本文档详细介绍了 React 的 useState 钩子在重新渲染时重新渲染整个组件的原因、如何保持值以及内部实现结构。通过分析 ReactFiberHooks.js 代码,可以理解钩子的工作方式,并了解 mountState、updateState 和 rerenderState 函数的作用。
Sunrabbit
Sunrabbit
Sunrabbit
Sunrabbit

2024年3月14日

PHP 版本升級工具 rector 介紹 為了解決 GNU Board 5 在 PHP 版本升級時的兼容性問題,我們介紹了 Rector 工具。Rector 是一個靜態分析器,可以自動將 PHP 5.3 ~ 8.2 代碼升級到目標版本。 安裝 Composer 後,安裝 Rector 並創建配置文件,只需執行即可自動轉換源代碼。但是,它不會檢測運行時錯誤,因此需要單獨審查。
초록 기린
초록 기린
초록 기린
초록 기린

2024年3月24日

[濟州] 車歸島前往碼頭附近可以拍出漂亮照片的地方分享 在濟州車歸島碼頭附近找到了隱藏的拍照勝地! 以破舊的船隻、蔚藍的海洋、島嶼為背景,可以拍出美麗的照片, 推薦給前往車歸島碼頭的遊客。 特別適合步行濟州올레길 12號路線或騎自行車的人。
토보노의 트립로그(Tobono's TripLog)
토보노의 트립로그(Tobono's TripLog)
토보노의 트립로그(Tobono's TripLog)
토보노의 트립로그(Tobono's TripLog)

2024年5月2日

不要使用暗黑模式 暗黑模式是指网站为了欺骗用户或诱导用户进行非自愿行为而设计的巧妙界面,包括欺骗性营销、隐藏更新、虚假折扣等多种类型。
garan blog
garan blog
garan blog
garan blog

2024年1月23日