攔截器詳解


網絡上關於Interceptor的文章,但感覺內容都大同小異,而且知識點零零散散,不太方便閱讀。因此,整理一篇關於攔截器的文章,在此分享給大家,以供大家參考閱讀。

1.概念

  java里的攔截器是動態攔截Action調用的對象,它提供了一種機制可以使開發者在一個Action執行的前后執行一段代碼,也可以在一個Action執行前阻止其執行,同時也提供了一種可以提取Action中可重用部分代碼的方式。在AOP中,攔截器用於在某個方法或者字段被訪問之前進行攔截,然后再之前或者之后加入某些操作。

       談到攔截器,還有一個詞大家應該知道——攔截器鏈(Interceptor Chain,在Struts 2中稱為攔截器棧Interceptor Stack)。攔截器鏈就是將攔截器按一定的順序聯結成一條鏈。在訪問被攔截的方法或字段時,攔截器鏈中的攔截器就會按其之前定義的順序被調用。

2.攔截器的原理
      大部分時候,攔截器方法都是通過代理的方式來調用的。是基於反射實現的,Struts2的攔截器實現相對簡單。當請求到達Struts2的ServletDispatcher時,Struts2會查找配置文件,並根據配置實例化相對的攔截器對象,然后串成一個列表(List),最后一個一個的調用列表中的攔截器。Struts2的攔截器是可插拔的,攔截器是AOP的一個實現。Struts2攔截器棧就是將攔截器按一定的順序連接成一條鏈。在訪問被攔截的方法或者字段時,Struts2攔截器鏈中的攔截器就會按照之前定義的順序進行調用。

3.自定義攔截器的步驟
  1)、創建我們自己的攔截器類並實現 HandlerInterceptor 接口。
  2)、創建一個Java類繼承WebMvcConfigurerAdapter,並重寫 addInterceptors 方法。
  3)、實例化我們自定義的攔截器,然后將對像手動添加到攔截器鏈中(在addInterceptors方法中添加)。

4.代碼示例

IndexInterceptor.java類代碼:

package com.example.interceptor;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.HandlerInterceptor;

import org.springframework.web.servlet.ModelAndView;

public class IndexInterceptor implements HandlerInterceptor{

  @Override

  public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)

      throws Exception {

    System.out.println(">>>IndexInterceptor>>>>>>>在整個請求結束之后被調用,也就是在DispatcherServlet 渲染了對應的視圖之后執行(主要是用於進行資源清理工作)");

  }

  @Override

  public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)

      throws Exception {

    System.out.println(">>>IndexInterceptor>>>>>>>請求處理之后進行調用,但是在視圖被渲染之前(Controller方法調用之后)");

  }

  @Override

  public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {

     System.out.println(">>>IndexInterceptor>>>>>>>在請求處理之前進行調用(Controller方法調用之前)");

     // 只有返回true才會繼續向下執行,返回false取消當前請求

     return true;

  }

}

IndexInterceptor2.java類代碼:

package com.example.interceptor;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.HandlerInterceptor;

import org.springframework.web.servlet.ModelAndView;

public class IndexInterceptor2 implements HandlerInterceptor{

  @Override

  public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)

      throws Exception {

    System.out.println(">>>IndexInterceptor2>>>>>>>在整個請求結束之后被調用,也就是在DispatcherServlet 渲染了對應的視圖之后執行(主要是用於進行資源清理工作)");

  }

  @Override

  public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)

      throws Exception {

    System.out.println(">>>IndexInterceptor2>>>>>>>請求處理之后進行調用,但是在視圖被渲染之前(Controller方法調用之后)");

  }

  @Override

  public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {

     System.out.println(">>>IndexInterceptor2>>>>>>>在請求處理之前進行調用(Controller方法調用之前)");

     // 只有返回true才會繼續向下執行,返回false取消當前請求

     return false;

  }

}

SimpleWebAppConfigurer.java類代碼:

package com.example.config;

import org.springframework.context.annotation.Configuration;

import org.springframework.web.servlet.config.annotation.InterceptorRegistry;

import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

import com.example.interceptor.IndexInterceptor;

import com.example.interceptor.IndexInterceptor2;

//只要能被springboot掃描到即可

@Configuration

public class SimpleWebAppConfigurer extends WebMvcConfigurerAdapter{

  @Override

  public void addInterceptors(InterceptorRegistry registry) {

    // 多個攔截器組成一個攔截器鏈

    // addPathPatterns 用於添加攔截規則

    // excludePathPatterns 用戶排除攔截

    registry.addInterceptor(new IndexInterceptor()).addPathPatterns("/**");

    registry.addInterceptor(new IndexInterceptor2()).addPathPatterns("/**");

    super.addInterceptors(registry);

  }

}

5.應用場景

1、日志記錄,可以記錄請求信息的日志,以便進行信息監控、信息統計等。

2、權限檢查:如登陸檢測,進入處理器檢測是否登陸,如果沒有直接返回到登陸頁面。

3、性能監控:典型的是慢日志

6.注意點

在一個工程中,可以配置多個攔截器,使用多個攔截器,則要注意的是 :多個攔截器使用的時候,prehandler是順序執行的,而posthandler和afterhandler是倒序執行的;

所以 :如果統一日志處理器攔截器,需要改攔截器prehandler一定要返回true,且將它放在攔截器配置的第一個位置;

      如果登陸認證攔截器,放在攔截器的配置中的第一個位置(有日志處理的話,放在日志處理下面);

      如果有權限校驗攔截器,則放在登陸攔截器之后,因為登陸通過后,才可以進行校驗權限;


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM