實現過濾請求有兩種方式:
一種就是用攔截器,一種就是過濾器
攔截器相對來說比較專業,而過濾器雖然不專業但是也能完成基本的攔截請求要求。
一、攔截器方式
1、配置HandlerInterceptor
下面這個也是我們公司項目攔截器的寫法,總體來說感覺還不錯,我就記錄了下來。
利用了一個靜態Pattern變量存儲不走攔截器的路徑,然后在preHandle方法當中進行過濾,讓他返回true。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
|
@Component public class LoginInterceptor implements HandlerInterceptor{ private static final Pattern SHOULD_NOT_FILTER_URL_PATTERN; static { List<String> urlList = new ArrayList<>(); // 將不走攔截器的請求存放到Pattern urlList.add( "(socket/.*)" ); urlList.add( "(user/findUserList)" ); StringBuilder sb = new StringBuilder(); for (String url : urlList) { sb.append(url); sb.append( "|" ); } sb.setLength(sb.length() - 1 ); SHOULD_NOT_FILTER_URL_PATTERN = Pattern.compile(sb.toString()); } /** * 在請求處理之前進行調用(Controller方法調用之前) */ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { HttpSession session = request.getSession(); // 獲取訪問的url String servletPath = request.getServletPath(); // 排除特定請求 if (SHOULD_NOT_FILTER_URL_PATTERN.matcher(servletPath).find()) { return true ; } if (session.getAttribute( "user" ) != null ) { // 可能有的項目在校驗完session,還會校驗token String token = request.getHeader( "access_token" ); // 此處業務省略。。。 return true ; } return false ; } /** * 請求處理之后進行調用,但是在視圖被渲染之前(Controller方法調用之后) */ @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { // TODO Auto-generated method stub } /** * 在整個請求結束之后被調用,也就是在DispatcherServlet 渲染了對應的視圖之后執行(主要是用于進行資源清理工作) */ @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { // TODO Auto-generated method stub } } |
2、注冊攔截器
配置完上面的攔截器還需要注冊攔截器。
WebMvcConfigurerAdapter類是 Spring內部的一種配置方式
采用JavaBean的形式來代替傳統的xml配置文件形式進行針對框架個性化定制
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
@Configuration public class MyWebAppConfigurer extends WebMvcConfigurerAdapter { @Autowired private LoginInterceptor loginInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { // 多個攔截器組成一個攔截器鏈 // addPathPatterns 用于添加攔截規則 // excludePathPatterns 用戶排除攔截 registry.addInterceptor(loginInterceptor).addPathPatterns( "/**" ); super .addInterceptors(registry); } } |
3、使用攔截器的坑
繼承WebMvcConfigurerAdapter 重寫addInterceptors方法的時候,一定要使用注入方式,將loginInterceptor注入到變量當中,要么就使用@Bean注解的方式,將loginInterceptor(攔截器)注入到容器。
之所以這么搞是因為攔截器在 Bean 初始化之前進行,所以在攔截器中無法像這樣注入 Bean。
就算加了@Component,他是存放于容器當中了,但是他存放容器當中的對象屬性,是空屬性。
在WebMvcConfigurerAdapter 使用@Autowired注入了一遍攔截器,屬性就有值了。
說白了不管采用哪種方案,目的只有一個,讓對象的屬性有值,因為攔截器比其他對象初始化早,導致屬性為空,想讓他有值,就想辦法讓他重新走一遍spring注入容器,也可以采用這種方式:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
@Configuration public class MyWebAppConfigurer extends WebMvcConfigurerAdapter { // 這么寫的目的是為了在SessionInterceptor中能注入spring中的service @Bean LoginInterceptor loginInterceptor() { return new LoginInterceptor(); } @Override public void addInterceptors(InterceptorRegistry registry) { // 多個攔截器組成一個攔截器鏈 // addPathPatterns 用于添加攔截規則 // excludePathPatterns 用戶排除攔截 registry.addInterceptor(loginInterceptor()).addPathPatterns( "/**" ); super .addInterceptors(registry); } } |
二、過濾器方式
本人這一篇博客寫了關于filter的一些知識:http://www.jfrwli.cn/article/207461.html
1、實現Filter接口
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
|
import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.regex.Pattern; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import org.springframework.stereotype.Component; @Component @WebFilter (filterName = "requestParamFilter" ,urlPatterns = "/*" ) public class RequestParamFilter implements Filter { private static final Pattern SHOULD_NOT_FILTER_URL_PATTERN; static { List<String> urlList = new ArrayList<>(); // 將不走攔截器的請求存放到Pattern urlList.add( "(socket/.*)" ); urlList.add( "(user/findUserList)" ); StringBuilder sb = new StringBuilder(); for (String url : urlList) { sb.append(url); sb.append( "|" ); } sb.setLength(sb.length() - 1 ); SHOULD_NOT_FILTER_URL_PATTERN = Pattern.compile(sb.toString()); } @Override public void init(FilterConfig filterConfig) throws ServletException { } // 發送請求會執行這個方法 // 一個doFilter相當于攔截器的執行前和執行后 // filterChain.doFilter后面的內容就是執行后的內容,假如不執行filterChain.doFilter方法相當于方法被攔截 @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { System.out.println( "sunhan---請求參數過濾器!---test1" ); HttpServletRequest request = (HttpServletRequest)servletRequest; HttpSession session = request.getSession(); // 獲取訪問的url String servletPath = request.getServletPath(); // 排除特定請求 if (SHOULD_NOT_FILTER_URL_PATTERN.matcher(servletPath).find()) { filterChain.doFilter(servletRequest,servletResponse); } System.out.println( "開始攔截了................" ); //業務代碼 } @Override public void destroy() { } } |
2、使用過濾器需要注意的
攔截器可以獲取IOC容器中的各個bean,而過濾器就不行,這點很重要,在攔截器里注入一個service,可以調用業務邏輯
執行順序如下:
到此這篇關于淺談Springboot實現攔截器的兩種方式的文章就介紹到這了,更多相關Springboot 攔截器內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!
原文鏈接:https://blog.csdn.net/weixin_43888891/article/details/119778754