1、背景
咋一看過濾器和攔截器好像作用是一樣的,但是如果我們仔細對這兩個東西進行分析就可以得出結論。首先過濾器是對類級別進行阻擋。而攔截器是對方法級別進行阻擋。他們兩個的應用角度也有所不同。過濾器的作用可以是使請求進入後臺之前,我們做一些相應的處理,比如編碼集轉換,登錄校驗等等。而攔截器就比較靈活了,它可以攔下每個方法,這樣他不僅僅是可以做登錄校驗,還可以做方法的日誌打印,或者每一層之間切一個面出來進行提前處理類容。
2、過濾器使用方式
這裏我主要介紹的是Spring boot項目中的使用方式,當然傳統的web項目使用web.xml進行配置的過濾器大家應該已經非常清楚了。
首先在Spring boot項目中要使用過濾器,首先我們先寫個正常的過濾器如下
package com.trs.zhjm.filter;
import javax.servlet.*;
import java.io.IOException;
public class testFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
}
@Override
public void destroy() {
}
}
至於這裏面的方法是幹嘛的,相信我不說大家都很清楚了。下面我們需要的是寫配置類信息
package com.trs.zhjm.config;
import com.trs.zhjm.filter.testFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
@Configuration
public class testConfig {
@Bean
public FilterRegistrationBean loginFilter() {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(new testFilter());
registration.addUrlPatterns("/*");
registration.setName("checkLoginFilter");
registration.setOrder(Ordered.HIGHEST_PRECEDENCE);
return registration;
}
}
這樣寫完之後,我們就可以成功的對類進行過濾了。
下面我要說的是如何注入參數,在配置類裏面可以再加一行類容。
registration.addInitParameter("test", "注入參數");
那我們如何取呢?
public FilterConfig config;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
config = filterConfig;
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
FilterChain filterChain) throws IOException, ServletException {
String test= config.getInitParameter("test"); //獲取注入類容
}
按照這樣的寫法我們就可以直接使用了。這裏我們要注意的是,配置類必須是要在Spring boot啓動類掃描範圍內的,不然無法生效。
3、攔截器的使用方式
一個攔截器類其實只需要實現HandlerInterceptor 這個接口就可以了
package com.trs.zhjm.controller;
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 java.io.IOException;
import java.util.List;
@Component
public class PermissionsInterceptor implements HandlerInterceptor {
/**
* 進入方法之前攔截
*/
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws IOException {
return true//代表通過攔截
return false//代表不通過攔截
}
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
}
}
當然我們也需要配置類來對它進行配置。
package com.trs.zhjm.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import java.nio.charset.Charset;
/**
* 攔截器注入類
*/
@Configuration
@EnableWebMvc
public class PermissionsAdapter extends WebMvcConfigurerAdapter {
@Autowired
PermissionsInterceptor permissionsInterceptor;
@Bean
public HttpMessageConverter<String> responseBodyConverter() {
StringHttpMessageConverter converter = new StringHttpMessageConverter(
Charset.forName("gbk"));
return converter;
}
/**
* 注入攔截所有請求方法,放過login和exit
* @param registry
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(permissionsInterceptor).addPathPatterns("/**").excludePathPatterns("/login","/exit");
//代表攔截下/**的請求,放過 /login 和 /exit的請求
super.addInterceptors(registry);
}
}
同樣攔截器配置類也是需要寫在Spring boot 啓動類下面的。
4、總結
相對來說攔截器比過濾器用起來方便一些,因爲攔截器不需要考慮請求完成之後,又回到攔截器的問題,而過濾器當我們請求執行完成之後,還會回到過濾器,如果判斷沒有寫完整會出現一隻在過濾器裏面跑的問題。當然還有就是過濾器是基於serlet才能夠使用的,而攔截器只要是用Spring管理的項目就可以使用啦。
面向切面編程其實是對另外一種思維方式的改變,如果對全體方面考慮不夠周全其實能不使用我自己一般都不會考慮用這樣的方法的。