淺談Springboot實(shí)現(xiàn)攔截器的兩種方式
實(shí)現(xiàn)過(guò)濾請(qǐng)求有兩種方式:
一種就是用攔截器,一種就是過(guò)濾器
攔截器相對(duì)來(lái)說(shuō)比較專業(yè),而過(guò)濾器雖然不專業(yè)但是也能完成基本的攔截請(qǐng)求要求。
一、攔截器方式
1、配置HandlerInterceptor
下面這個(gè)也是我們公司項(xiàng)目攔截器的寫法,總體來(lái)說(shuō)感覺(jué)還不錯(cuò),我就記錄了下來(lái)。
利用了一個(gè)靜態(tài)Pattern變量存儲(chǔ)不走攔截器的路徑,然后在preHandle方法當(dāng)中進(jìn)行過(guò)濾,讓他返回true。
@Component
public class LoginInterceptor implements HandlerInterceptor{
private static final Pattern SHOULD_NOT_FILTER_URL_PATTERN;
static {
List<String> urlList = new ArrayList<>();
// 將不走攔截器的請(qǐng)求存放到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());
}
/**
* 在請(qǐng)求處理之前進(jìn)行調(diào)用(Controller方法調(diào)用之前)
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
HttpSession session = request.getSession();
// 獲取訪問(wèn)的url
String servletPath = request.getServletPath();
// 排除特定請(qǐng)求
if (SHOULD_NOT_FILTER_URL_PATTERN.matcher(servletPath).find()) {
return true;
}
if (session.getAttribute("user") != null) {
// 可能有的項(xiàng)目在校驗(yàn)完session,還會(huì)校驗(yàn)token
String token = request.getHeader("access_token");
// 此處業(yè)務(wù)省略。。。
return true;
}
return false;
}
/**
* 請(qǐng)求處理之后進(jìn)行調(diào)用,但是在視圖被渲染之前(Controller方法調(diào)用之后)
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
// TODO Auto-generated method stub
}
/**
* 在整個(gè)請(qǐng)求結(jié)束之后被調(diào)用,也就是在DispatcherServlet 渲染了對(duì)應(yīng)的視圖之后執(zhí)行(主要是用于進(jìn)行資源清理工作)
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
// TODO Auto-generated method stub
}
}
2、注冊(cè)攔截器
配置完上面的攔截器還需要注冊(cè)攔截器。
WebMvcConfigurerAdapter類是 Spring內(nèi)部的一種配置方式
采用JavaBean的形式來(lái)代替?zhèn)鹘y(tǒng)的xml配置文件形式進(jìn)行針對(duì)框架個(gè)性化定制
@Configuration
public class MyWebAppConfigurer extends WebMvcConfigurerAdapter {
@Autowired
private LoginInterceptor loginInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 多個(gè)攔截器組成一個(gè)攔截器鏈
// addPathPatterns 用于添加攔截規(guī)則
// excludePathPatterns 用戶排除攔截
registry.addInterceptor(loginInterceptor).addPathPatterns("/**");
super.addInterceptors(registry);
}
}
3、使用攔截器的坑
繼承WebMvcConfigurerAdapter 重寫addInterceptors方法的時(shí)候,一定要使用注入方式,將loginInterceptor注入到變量當(dāng)中,要么就使用@Bean注解的方式,將loginInterceptor(攔截器)注入到容器。
之所以這么搞是因?yàn)閿r截器在 Bean 初始化之前進(jìn)行,所以在攔截器中無(wú)法像這樣注入 Bean。
就算加了@Component,他是存放于容器當(dāng)中了,但是他存放容器當(dāng)中的對(duì)象屬性,是空屬性。

在WebMvcConfigurerAdapter 使用@Autowired注入了一遍攔截器,屬性就有值了。
說(shuō)白了不管采用哪種方案,目的只有一個(gè),讓對(duì)象的屬性有值,因?yàn)閿r截器比其他對(duì)象初始化早,導(dǎo)致屬性為空,想讓他有值,就想辦法讓他重新走一遍spring注入容器,也可以采用這種方式:
@Configuration
public class MyWebAppConfigurer extends WebMvcConfigurerAdapter {
// 這么寫的目的是為了在SessionInterceptor中能注入spring中的service
@Bean
LoginInterceptor loginInterceptor() {
return new LoginInterceptor();
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 多個(gè)攔截器組成一個(gè)攔截器鏈
// addPathPatterns 用于添加攔截規(guī)則
// excludePathPatterns 用戶排除攔截
registry.addInterceptor(loginInterceptor()).addPathPatterns("/**");
super.addInterceptors(registry);
}
}
二、過(guò)濾器方式
本人這一篇博客寫了關(guān)于filter的一些知識(shí):http://www.dhdzp.com/article/204084.htm
1、實(shí)現(xiàn)Filter接口
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<>();
// 將不走攔截器的請(qǐng)求存放到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 {
}
// 發(fā)送請(qǐng)求會(huì)執(zhí)行這個(gè)方法
// 一個(gè)doFilter相當(dāng)于攔截器的執(zhí)行前和執(zhí)行后
// filterChain.doFilter后面的內(nèi)容就是執(zhí)行后的內(nèi)容,假如不執(zhí)行filterChain.doFilter方法相當(dāng)于方法被攔截
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
FilterChain filterChain) throws IOException, ServletException {
System.out.println("sunhan---請(qǐng)求參數(shù)過(guò)濾器!---test1");
HttpServletRequest request = (HttpServletRequest)servletRequest;
HttpSession session = request.getSession();
// 獲取訪問(wèn)的url
String servletPath = request.getServletPath();
// 排除特定請(qǐng)求
if (SHOULD_NOT_FILTER_URL_PATTERN.matcher(servletPath).find()) {
filterChain.doFilter(servletRequest,servletResponse);
}
System.out.println("開(kāi)始攔截了................");
//業(yè)務(wù)代碼
}
@Override
public void destroy() {
}
}
2、使用過(guò)濾器需要注意的
攔截器可以獲取IOC容器中的各個(gè)bean,而過(guò)濾器就不行,這點(diǎn)很重要,在攔截器里注入一個(gè)service,可以調(diào)用業(yè)務(wù)邏輯
執(zhí)行順序如下:

到此這篇關(guān)于淺談Springboot實(shí)現(xiàn)攔截器的兩種方式的文章就介紹到這了,更多相關(guān)Springboot 攔截器內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Jmeter關(guān)聯(lián)實(shí)現(xiàn)及參數(shù)化使用解析
這篇文章主要介紹了Jmeter關(guān)聯(lián)實(shí)現(xiàn)及參數(shù)化使用解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-08-08
解決JDK異常處理No appropriate protocol問(wèn)題
這篇文章主要介紹了解決JDK異常處理No appropriate protocol問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-06-06
Mybatis-plus如何通過(guò)反射實(shí)現(xiàn)動(dòng)態(tài)排序不同字段功能
這篇文章主要介紹了Mybatis-plus如何通過(guò)反射實(shí)現(xiàn)動(dòng)態(tài)排序不同字段功能,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-02-02
基于多網(wǎng)卡環(huán)境下Eureka服務(wù)注冊(cè)IP的選擇問(wèn)題
這篇文章主要介紹了基于多網(wǎng)卡環(huán)境下Eureka服務(wù)注冊(cè)IP的選擇問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03
Spring Cloud Feign統(tǒng)一設(shè)置驗(yàn)證token實(shí)現(xiàn)方法解析
這篇文章主要介紹了Spring Cloud Feign統(tǒng)一設(shè)置驗(yàn)證token實(shí)現(xiàn)方法解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-08-08
Java 實(shí)現(xiàn)隨機(jī)驗(yàn)證碼功能簡(jiǎn)單實(shí)例
這篇文章主要介紹了Java 實(shí)現(xiàn)隨機(jī)驗(yàn)證碼功能簡(jiǎn)單實(shí)例的相關(guān)資料,需要的朋友可以參考下2017-04-04

