自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Java中的過濾器和攔截器有什么區(qū)別么?

開發(fā) 前端
我們自定義一個(gè)獲取并返回某個(gè)靜態(tài)資源的內(nèi)容以及整個(gè)請(qǐng)求所花費(fèi)的時(shí)間攔截器,一般這個(gè)還是比較有用的,而且還可以加一個(gè)請(qǐng)求訪問的,然后來處理方法執(zhí)行時(shí)間的。

今天我們不談框架,我們來說說這個(gè) Java 基礎(chǔ)中的過濾器和攔截器,為什么要談呢?其實(shí)就有粉絲會(huì)問了不起,這個(gè)過濾器和攔截器他們有什么區(qū)別呢?為什么面試官在面試的時(shí)候經(jīng)常會(huì)問到這個(gè)過濾器和攔截器的區(qū)別,以及他們分別對(duì)應(yīng)的應(yīng)用場(chǎng)景呢?

今天了不起就來說說這個(gè)過濾器和攔截器。

過濾器

過濾器 Filter

什么是過濾器

過濾器是 Servlet 的高級(jí)特性之一,是實(shí)現(xiàn) Filter 接口的 Java 類。其基本功能就是對(duì) servlet 的調(diào)用進(jìn)行干預(yù),在 Servlet 請(qǐng)求和響應(yīng)的過程中增加一些特定的功能??梢允褂眠^濾器實(shí)現(xiàn)的功能有:統(tǒng)一編碼,URL級(jí)別的權(quán)限訪問控制,過濾敏感詞匯,壓縮請(qǐng)求信息.

我們來通過代碼來看 Filter 的執(zhí)行過程

public interface Filter {
    //用于執(zhí)行過濾器的初始化工作,web容器會(huì)在web項(xiàng)目啟動(dòng)時(shí)自動(dòng)調(diào)用該方法
    default void init(FilterConfig filterConfig) throws ServletException {
    }
 
    //當(dāng)請(qǐng)求和響應(yīng)被過濾器攔截后,都會(huì)交給doFilter來處理:其中兩個(gè)參數(shù)分別是被攔截request和response對(duì)象,可以使用chain的doFliter方法來放行
    void doFilter(ServletRequest var1, ServletResponse var2, FilterChain var3) throws IOException, ServletException;
    //用于釋放關(guān)閉Filter對(duì)象打開的資源,在web項(xiàng)目關(guān)閉時(shí),由web容器自動(dòng)調(diào)用該方法
    default void destroy() {
    }
}

在 Filter 中我們可以看到有三個(gè)方法,分別是

  • init
  • doFilter
  • destroy

至于每個(gè)方法的作用,了不起已經(jīng)把他們的功能寫在了注釋上面,他們實(shí)際上就是三個(gè)步驟:

1.初始化

2.處理請(qǐng)求和相應(yīng)過濾,完成操作

3.最后釋放資源

而實(shí)現(xiàn)一個(gè)自定義 Filter 也是比較簡單的,我們來實(shí)現(xiàn)一個(gè)簡單的自定義的 Filter。

@Component
@Slf4j
public class MyFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        log.info("初始化過濾器:" + filterConfig.getFilterName());
    }

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

        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;

        // 對(duì)請(qǐng)求進(jìn)行過濾操作處理
        log.info("MyFilter 開始對(duì)請(qǐng)求進(jìn)去過濾操作!");
        String requestURI = httpRequest.getRequestURI();
        log.info("請(qǐng)求地址:" + requestURI);

        // 繼續(xù)執(zhí)行下一個(gè) Filter,如果沒有其他 Filter 的話就執(zhí)行 Controller 層代碼
        long startTime = System.currentTimeMillis();
        chain.doFilter(request, response);

        // 執(zhí)行完用戶請(qǐng)求后,回到這里對(duì) response 響應(yīng)內(nèi)容做一些處理
        long endTime = System.currentTimeMillis();
        log.info("請(qǐng)求處理完畢,所花費(fèi)時(shí)間為:" + (endTime - startTime) + "ms");
    }

    @Override
    public void destroy() {
        log.info("銷毀過濾器 MyFilter");
    }

}

至于 Filter 的配置的話,了不起都不用解釋,現(xiàn)在幾乎沒有再去配置 xml 的方式了,都是配置類或者注解的方式。

注解方式:

@WebFilter(filterName = "myFilter",urlPatterns = {"/*"})

配置類方式:

@Configuration
public class MyFilterConfig {
 
    @Bean
    public FilterRegistrationBean myFilter(){
        FilterRegistrationBean fb = new FilterRegistrationBean();
        //設(shè)置filter啟動(dòng)順序
        fb.setOrder(1);
        fb.setFilter(new MyFilter());
        fb.addInitParameter("phone","183****5510");
        //設(shè)置攔截請(qǐng)求規(guī)則,這里攔截所有請(qǐng)求
        fb.addUrlPatterns("/*");
        return fb;
    }
}

我們看完了這個(gè)過濾器,接下來就得看看這個(gè)攔截器了。

攔截器

攔截器 Interceptor

什么是攔截器

Spring MVC 中的攔截器Interceptor類似于 ServLet 中的過濾器Filter,它主要用于攔截用戶請(qǐng)求并作出相應(yīng)的處理。例如通過攔截器可以進(jìn)行權(quán)限驗(yàn)證、記錄請(qǐng)求信息的日志、判斷用戶是否登錄等。

老規(guī)矩,直接看源代碼

public interface HandlerInterceptor {
    //預(yù)處理方法,本方法在控制器方法(MyController的方法)之前執(zhí)        行,用戶的請(qǐng)求最先到達(dá)此方法,在這個(gè)方法中可以獲取請(qǐng)求的信息,驗(yàn)證請(qǐng)求是否符合要求。以驗(yàn)證用戶是否登錄,驗(yàn)證用戶是否有權(quán)限訪問某個(gè)鏈接地址(url)。如果返回true則放行,返回false則攔截
    default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        return true;
    }
    //后處理方法。在controller中的方法之后執(zhí)行的。能夠獲取到處理器方法的返回值 mv,可以修改mv中的數(shù)據(jù)和視圖。可以影響到最后的執(zhí)行結(jié)果。主要是對(duì)原來的執(zhí)行結(jié)果做二次修正
    default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
    }
    //最后執(zhí)行的方法,在頁面渲染之后執(zhí)行。在請(qǐng)求處理完成后執(zhí)行的,框架中規(guī)定是當(dāng)你的視圖處理完成后,對(duì)視圖進(jìn)行了forword。就任務(wù)請(qǐng)求處理完成。
    default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
    }
}

其實(shí)也是三個(gè)步驟:

1.預(yù)處理

2.后處理

3.最后執(zhí)行

至于每一步的含義和內(nèi)容,了不起同樣的再注釋中表明了。

同樣的,自定義實(shí)現(xiàn)一個(gè)攔截器也很簡單:

public class MyInterceptor implements HandlerInterceptor {
    private static final Logger LOGGER = LoggerFactory.getLogger(MyInterceptor.class);

    private static final ThreadLocal<Long> START_THREAD_LOCAL = new ThreadLocal<>();

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        String uri = request.getRequestURI();
        LOGGER.info(uri + " preHandle");
        Long startTime = System.currentTimeMillis();    //獲取開始時(shí)間
        START_THREAD_LOCAL.set(startTime);  //線程綁定變量(該數(shù)據(jù)只有當(dāng)前請(qǐng)求的線程可見)
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                           ModelAndView modelAndView) throws Exception {
        String uri = request.getRequestURI();
        LOGGER.info(uri + " postHandle");
        Long startTime = START_THREAD_LOCAL.get();//得到線程綁定的局部變量(開始時(shí)間)
        Long endTime = System.currentTimeMillis();  //2、結(jié)束時(shí)間
        Long time = endTime - startTime;
        LOGGER.info("http request all time: " + time + "ms");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
                                Exception ex) throws Exception {
        String uri = request.getRequestURI();
        LOGGER.info(uri + " afterCompletion");
        if (START_THREAD_LOCAL != null) {
            START_THREAD_LOCAL.remove();    // 移除ThreadLocal中的局部變量
        }
    }
}

我們自定義一個(gè)獲取并返回某個(gè)靜態(tài)資源的內(nèi)容以及整個(gè)請(qǐng)求所花費(fèi)的時(shí)間攔截器,一般這個(gè)還是比較有用的,而且還可以加一個(gè)請(qǐng)求訪問的,然后來處理方法執(zhí)行時(shí)間的。

配置攔截器其實(shí)在項(xiàng)目中是非常的常見。

@Configuration
public class MyInterceptorConfig implements WebMvcConfigurer {
 
    /**
     * 配置攔截器
     * @param registry
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry){
        registry.addInterceptor(myInterceptor())
                .addPathPatterns("/api/v1/**")//需要攔截的請(qǐng)求
                .addPathPatterns("/api/v1/**")//需要攔截的請(qǐng)求
                .excludePathPatterns("/api/debug/**")//不攔截的請(qǐng)求
                .excludePathPatterns("api/page/getName");//不攔截的請(qǐng)求
    }
 
    /**
     * 注入攔截器到spring容器
     * @return
     */
    @Bean
    public MyInterceptor myInterceptor(){
        return new MyInterceptor();
    }
}

我們看完了過濾器和攔截器的實(shí)現(xiàn),接下來就得來看看這個(gè)過濾器和攔截器之間的區(qū)別了。

1.依賴點(diǎn)不同

  • 過濾器依賴與servlet容器,而攔截器不依賴與servlet容器
  • 過濾器屬于Servlet,而攔截器屬于springmvc

2.實(shí)現(xiàn)原理不同

  • 過濾器是基于函數(shù)回調(diào),而攔截器是基于java的反射機(jī)制的

3.作用域不同

  • 過濾器則可以對(duì)幾乎所有的請(qǐng)求起作用,而攔截器只能對(duì)action請(qǐng)求起作用

4.生命周期不同

  • 在action的生命周期中,攔截器可以多次被調(diào)用,而過濾器只能在容器初始化時(shí)被調(diào)用一次

這是區(qū)別,其實(shí)二者的相同點(diǎn)也是有的,比如,攔截器和過濾器實(shí)際上都是 Spring 中 AOP 的體現(xiàn),都能實(shí)現(xiàn)一些權(quán)限和日志方面的功能。

你知道他們是什么區(qū)別了么?

責(zé)任編輯:武曉燕 來源: Java極客技術(shù)
相關(guān)推薦

2023-02-20 07:19:14

2022-01-13 10:04:21

攔截器Interceptor過濾器

2023-09-15 11:26:16

2020-09-14 12:46:25

過濾器攔截器Filter

2024-01-17 08:56:31

2024-01-08 08:33:53

AOPSpring攔截器

2016-12-07 09:56:13

JavaFilter過濾器

2020-06-04 07:45:07

過濾器和攔截器

2009-07-08 15:30:56

Servlet過濾器

2024-01-05 09:04:35

隆過濾器數(shù)據(jù)結(jié)構(gòu)哈希函數(shù)

2022-08-31 08:33:54

Bash操作系統(tǒng)Linux

2024-11-04 08:45:48

布隆過濾器元數(shù)據(jù)指紋值

2021-09-03 06:33:24

布隆過濾器高并發(fā)

2020-08-02 23:20:36

JavaScriptmap()forEach()

2021-07-05 15:22:03

Servlet過濾器客戶端

2022-09-02 09:02:44

TypeInterface

2021-03-27 10:56:17

promisethenfinally

2020-07-20 09:18:43

存儲(chǔ)數(shù)據(jù)技術(shù)

2025-04-27 08:15:00

FlinkSavepointCheckpoint

2009-06-18 10:13:00

Hibernate過濾
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)