關於spring boot中過濾器與攔截器的實現與區別!!!簡單通俗易懂~新手進

我們一個一個的的來!!!

一、什麼是過濾器??

過濾器就是過濾的作用,在web開發中過濾一些我們指定的url。它能夠在請求傳送給 Servlet 之前,對 ServletRequest 和 ServletResponse 做檢查和修改,起到了過濾的作用。那麼它能幫我們過濾什麼呢?那功能可就多了:
比如過攔截掉我們不需要的接口請求
修改請求(request)和響應(response)內容
完成CORS跨域請求等等。過濾器的工作流程去下圖所示:

在這裏插入圖片描述

1.1 如何在springboot中實現過濾器(兩個步驟)

第一步 自定義過濾器

由於spring boot中的過濾器屬於servlet容器,所以自定義的類必須繼承Filter接口。

public class MyFilter implements Filter  {
	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
	}
 
	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)//在這裏進行過濾操作
			throws IOException, ServletException {
		HttpServletRequest req = (HttpServletRequest) request;
		System.out.println("MyFilter: "+ req.getRequestURI());
		chain.doFilter(request, response);//這裏是對請求放行,程序繼續執行!
	}
 
	@Override
	public void destroy() {
	
	}
}

ps:注意這裏需要將ServletRequest強轉爲HttpServletRequest,不然後面會出問題!!

第二步 註冊過濾器(這裏有三個方法)

方法一: 在配置類中實現一個 FilterRegistrationBean 對象

@Configuration
public class WebConfig {
	   @Bean
	   public FilterRegistrationBean<MyFilter> abcFilter() {
		   FilterRegistrationBean<MyFilter> filterRegBean = new FilterRegistrationBean<>();
		   filterRegBean.setFilter(new MyFilter());//設置過濾器 對應上面的過濾器
		   filterRegBean.addUrlPatterns("/*"); //在這裏指定過濾地址
		   //如果出現多個過濾器,order可以設置過濾器執行順序。 1>2>3 這裏的LOWEST_PRECEDENCE是最低優先級
		   filterRegBean.setOrder(Ordered.LOWEST_PRECEDENCE);
		   return filterRegBean;
	   }
}

方法2:使用@Component 和@Order 註解註冊

@Order(Ordered.LOWEST_PRECEDENCE -1)
@Component
public class MyFilter implements Filter  {
	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		
	}
 
	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		HttpServletRequest req = (HttpServletRequest) request;
		System.out.println("MyFilter: "+ req.getRequestURI());
		chain.doFilter(request, response);//這步使得請求能夠繼續傳導下去,如果沒有的話,請求就在此結束
	}
 
	@Override
	public void destroy() {
	
	}
}

這種方法的缺點是不能再指定 UrlPatterns,默認的 URL 模式就是/*

方法三: 使用@WebFilter 和@ServletComponentScan 註解,@WebFilter 註解是 Servlet3.0 中的註解,SpringBoot 能夠支持該註解,通過@ServletComponentScan 註解,能夠掃描並註冊到 Servlet 容器中

@WebFilter(urlPatterns="/api/*")
public class MyFilter implements Filter  {
	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
	}
 
	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		HttpServletRequest req = (HttpServletRequest) request;
		System.out.println("MyFilter: "+ req.getRequestURI());
		chain.doFilter(request, response);//這步使得請求能夠繼續傳導下去,如果沒有的話,請求就在此結束
	}
 
	@Override
	public void destroy() {
	
	}
}

還需要在springboot啓動類中加入@ServletComponentScan註解

@ServletComponentScan
@SpringBootApplication
public class SpringbootlearnApplication {
 
	public static void main(String[] args) {
		SpringApplication.run(SpringbootlearnApplication.class, args);
	}
}

@WebFilter 方式,可以支持 UrlPatterns 的設置,但是不支持 Order 的設置。
綜上所述,第 1 種方法是最靈活的,也是最常用的一種。

二、攔截器

上面我們看了過濾的配置方法,下面我們來看一下攔截器的。網上常用的是實現HandlerInterceptor接口,這裏我用的是另一種差不多的方法繼承HandlerInterceptorAdapter。(建議用HandlerInterceptorAdapter,可以根據需求覆蓋方法)

自定義DjmIntercepter類

public class DjmIntercepter extends HandlerInterceptorAdapter {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("preHandle調用");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle調用");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
    }

    @Override
    public void afterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    }
}

ps:主要包括三個方法,preHandle是請求執行前執行的,postHandler是請求結束執行的,但只有preHandle方法返回true的時候纔會執行,afterCompletion是視圖渲染完成後才執行,同樣需要preHandle返回true,該方法通常用於清理資源等工作。afterConcurrentHandlingStarted用的比較少 大家可以自行百度!! 然後需要配置WebConfigurer類,通過實現WebMvcConfigurer接口。

WebConfigurer類 註冊自定義攔截器

@Configuration
public class WebConfigurer implements WebMvcConfigurer {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        //用於攔截靜態資源
    }

    @Bean
    public HttpMessageConverter<String> responseBodyConverter() {
        return new StringHttpMessageConverter(Charset.forName("UTF-8"));
    }

    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        converters.add(responseBodyConverter());
    }

    /**
     *  這個方法用來註冊攔截器,我們自己寫好的攔截器需要通過這裏添加註冊才能生效
     * @param registry 攔截器
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new DjmIntercepter()).addPathPatterns("/*");
        super.addInterceptors(registry);
    }
}

然後啓動項目,在任意地址運行。結果如下:

MyFilter: /ddddd
preHandle調用
postHandle調用
preHandle調用
postHandle調用

通過以上的例子,想必大家也知道了過濾器與攔截器的一些區別。下面我給大家總結一下:

1、過濾器和攔截器觸發時機不一樣,過濾器是在請求進入容器後,但請求進入servlet之前進行預處理的。請求結束返回也是,是在servlet處理完後,返回給前端之前。

在這裏插入圖片描述

2、攔截器可以獲取IOC容器中的各個bean,而過濾器就不行,因爲攔截器是spring提供並管理的,spring的功能可以被攔截器使用,在攔截器裏注入一個service,可以調用業務邏輯。而過濾器是JavaEE標準,只需依賴servlet api ,不需要依賴spring。

這裏有一張圖很好的展示了過濾器與攔截器的使用:
在這裏插入圖片描述

3、過濾器的實現基於回調函數。而攔截器(代理模式)的實現基於反射,代理分靜態代理和動態代理,動態代理是攔截器的簡單實現。

何時使用攔截器?何時使用過濾器?
如果是非spring項目,那麼攔截器不能用,只能使用過濾器。
如果是處理controller前後,既可以使用攔截器也可以使用過濾器。
如果是處理dispaterServlet前後,只能使用過濾器。

以上就是spring boot中過濾器與攔截器的實現與區別!!!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章