博客優先發表在個人博客,後續更新可能忘記同步到CSDN,望理解。
個人博客本篇文章地址:https://www.xdx97.com/article/698261857995063296
一、先看一下目錄結構
二、我們先配置啓動類和配置文件
這裏面其實沒有什麼東西,但是爲了完整性還是都寫出來,防止有的朋友弄錯。
app
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
@SpringBootApplication
@ComponentScan(basePackages = {"www.xdx97"})
public class app {
public static void main(String[] args) {
SpringApplication.run(app.class,args);
}
}
application.yml
server:
port: 9000
Controller
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class Controller {
@GetMapping("/xdx/test")
public String test(){
System.out.println("哈哈");
return "haha";
}
}
三、配置攔截器
InterceptorOne
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Component
public class InterceptorOne extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("攔截器One - 過");
return true;
}
}
InterceptorTwo
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Component
public class InterceptorTwo implements HandlerInterceptor {
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("攔截器Two - 過");
return true;
}
}
WebAppConfig
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import www.xdx97.interceptor.InterceptorOne;
import www.xdx97.interceptor.InterceptorTwo;
/*
攔截器配置類
*/
@Configuration
public class WebAppConfig implements WebMvcConfigurer {
// 多個攔截器組成一個攔截器鏈
// addPathPatterns 用於添加攔截規則
// excludePathPatterns 用戶排除攔截
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new InterceptorOne())//添加攔截器
.addPathPatterns("/**") //攔截所有請求
.excludePathPatterns("/UserCon/**", "/Doctor/**", "/SMS/**");//對應的不攔截的請求
registry.addInterceptor(new InterceptorTwo())
.addPathPatterns("/**")
.excludePathPatterns("/UserCon/**", "/Doctor/**", "/SMS/**");
}
}
到這裏我們可以啓動我們的項目然後去訪問 http://localhost:9000/xdx/test 可以看到,兩個攔截器依次進入了。
在攔截器裏面我們可以做具體的業務,返回 true 是放行,false 就是不放行。
攔截器的順序就是在 addInterceptors 方法裏面加入的順序。
我們也可以看到要實現攔截器,我們有兩種方式,它們都是一樣的去重寫父類裏面的方法。
- implements HandlerInterceptor
- extends HandlerInterceptorAdapter
攔截器裏面的方法作用
- preHandle 開始進入地址攔截器
- postHandle 處理請求完成後視圖渲染之前的處理操作
- afterCompletion 視圖渲染之後的操作
四、配置過濾器
4-1、使用 @WebFilter 註解
FilterOne
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
@Component
@WebFilter(filterName = "FilterOne", urlPatterns = "/*")
@Order(3)
public class FilterOne implements Filter {
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("FilterOne");
filterChain.doFilter(servletRequest,servletResponse);
}
}
FilterTwo
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
@Component
@WebFilter(filterName = "FilterTwo", urlPatterns = "/*")
@Order(2)
public class FilterTwo implements Filter {
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("FilterTwo");
filterChain.doFilter(servletRequest,servletResponse);
}
}
這樣你再次啓動訪問就可以看到請求會先進入過濾器、再進入攔截器的
4-2、使用 @Bean 註解
FilterThree
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import java.io.IOException;
@Component
@Order(1)
public class FilterThree implements Filter {
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("FilterThree");
filterChain.doFilter(servletRequest,servletResponse);
}
}
在WebAppConfig裏面加入下面的方法,也可以在啓動類裏面加入
@Bean
public FilterRegistrationBean testFilterRegistration() {
FilterRegistrationBean registration = new FilterRegistrationBean(new FilterThree());
registration.addUrlPatterns("/**");
registration.setName("FilterThree");
return registration;
}
這時候你再啓動去訪問,就會看到請求也會進入 FilterThree
這個 @Order(1) 是表示優先度,數字越小優先度越高。
我看有很多人說這個註解無效,我以前寫了一篇文章也用到了這個註解,然後也有人評論說無效,但是我今天反覆測試這個註解是有效的
五、其它
使用這個攔截器來做登錄攔截的時候有一個很好的思路:我們寫一個註解 @Login 當方法有這個註解的時候我們才做登錄攔截,沒有就放行。
如果你的攔截器或者過濾器無效,看看他們是否在Spring掃描的範圍內。
關注公衆號回覆關鍵字獲取源碼噢: Filter&InterceptorDemo
參考:
https://blog.csdn.net/xiaodanjava/article/details/32125687
六、面試
如果是以前,這篇文章到五也就結束了,但是現在我覺得我得時刻爲面試做準備。怕了怕了!!!
你用過攔截器和過濾器吧?你簡單得說說它們
Filter: 它主要用於對用戶請求進行預處理,也可以對HttpServletResponse進行後處理,是個典型的處理鏈。Filter也可以對用戶請求生成響應,這一點與Servlet相同,但實際上很少會使用Filter向用戶請求生成響應。使用Filter完整的流程是:Filter對用戶請求進行預處理,接着將請求交給Servlet進行預處理並生成響應,最後Filter再對服務器響應進行後處理。
Interceptor: 攔截器,在AOP中用於在某個方法或字段被訪問之前,進行攔截,然後在之前或之後加入某些操作。
Filter和Interceptor的區別
- Filter是基於函數回調的,而Interceptor則是基於Java反射的。
- Filter依賴於Servlet容器,而Interceptor不依賴於Servlet容器。
- Filter對幾乎所有的請求起作用,而Interceptor只能對action請求起作用。
- Interceptor可以訪問Action的上下文,值棧裏的對象,而Filter不能。
- 在action的生命週期裏,Interceptor可以被多次調用,而Filter只能在容器初始化時調用一次。
Filter和Interceptor的執行順序
過濾前-攔截前-action執行-攔截後-過濾後
怎麼去實現一個Filter和Interceptor呢
Filter:首先去實現Filter接口,重寫裏面的doFilter方法,然後可以使用 @WebFilter或 @Bean來實現
Interceptor:可以通過實現HandlerInterceptor接口或者繼承HandlerInterceptorAdapter抽象類重寫裏面的方法,然後在攔截器配置類裏面配置即可