SpringMVC中的過濾器和攔截器
一、過濾器
過濾器
Filter是通過實現java.servlet.filter接口實現過濾器功能,作用是用於對傳入的request和響應的response進行一些處理,比如對請求參數進行校驗,或者設置、檢驗頭部信息,再或者對一些非法行為進行校驗。由實現的接口可知,過濾器是依賴於servlet容器。所以由於過濾器不依賴於spring容器,它也就無法獲取到容器中的對象。
創建一個過濾器類繼承java.servlet.filter接口,實現filter中的攔截方法。
package com.example.demo.modules.filter;
import javax.servlet.*;
import java.io.IOException;
/**
* @Description:
* @date : 2020/6/9
*/
public class MyFilter 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.example.demo.modules.filter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.servlet.Filter;
/**
* 創建兩個過濾器myFilter和myFilter2,並且分別添加到FilterRegistrationBean
* @Description:
* @date : 2020/6/9
*/
@Configuration
public class ConfigBean {
@Bean
public FilterRegistrationBean filterRegistrationBean(){
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
filterRegistrationBean.setFilter(myFilter());
filterRegistrationBean.setName("myFilter");
filterRegistrationBean.addUrlPatterns("/*");
filterRegistrationBean.setOrder(1);
return filterRegistrationBean;
}
@Bean
public FilterRegistrationBean filter2RegistrationBean(){
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
filterRegistrationBean.setFilter(myFilter2());
filterRegistrationBean.setName("myFilter2");
filterRegistrationBean.addUrlPatterns("/*");
filterRegistrationBean.setOrder(2);
return filterRegistrationBean;
}
@Bean
public Filter myFilter(){
return new MyFilter();
}
@Bean
public Filter myFilter2(){
return new MyFilter();
}
}
二、攔截器
攔截器
Interceptor是通過實現org.springframework.web.servlet包的HandlerInterceptor接口實現,這個接口是spring容器的接口,所以它是依賴於spring容器的。主要作用是AOP的思想,可以對某一個方法進行橫切,做一些業務邏輯。
1.編寫自定義攔截器類
package com.example.demo.modules.interceptor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @Description:
* @date : 2020/6/9
*/
@Slf4j
public class CustomHandlerInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
log.info("請求調用之前");
return false;
}
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
log.info("請求調用之后");
}
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
log.info("afterCompletion:請求調用完成后回調方法,即在視圖渲染完成后回調");
}
}
2.注冊自定義攔截器
package com.example.demo.modules.interceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
/**
* 在spring2.0中WebMvcConfigurerAdapter已經過時,這里只是為了演示效果,
* 有興趣可以看下spring2.0中的WebMvcConfigurer
* @Description:
* @date : 2020/6/9
*/
@Configuration
public class WebMvcConfigurer extends WebMvcConfigurerAdapter {
@Override
public void addInterceptors(InterceptorRegistry registry) {
//super.addInterceptors(registry);
registry.addInterceptor(getHandlerInterceptor()).addPathPatterns("/*");
}
@Bean
public static HandlerInterceptor getHandlerInterceptor(){
return new CustomHandlerInterceptor();
}
}
過濾器和攔截器執行過程圖
在請求到達容器前,進入Filter過濾器鏈,執行完過濾器鏈上每個Filter#doFilter()方法后,進入Servlet#service()方法,然后由dispatcher分發器將請求方法給對應映射成功的處理器controller,在進入controller具體方法之前,會被先進入Interceptor#preHandler()方法,然后再進入controller的具體返回,執行之后進入Interceptor#postHandler()這里主要是攔截了controller方法執行之后到返回的數據模型到達視圖解析器之前,接着進入Interceptor#afterCompletion()方法,主要可以操作返回客戶端之前的邏輯,最后返回到過濾鏈中各個Filter的調用點,可以處理返回到客戶端的跳轉等邏輯。

三、小結
過濾器是servlet中的接口,主要可以用於在請求進入到servlet之前攔截請求HttpServletRequest並根據需要進行一些檢查等邏輯操作,也可以在HttpServletResponse返回到客戶端之前進行一些邏輯操作。
攔截器是spring中的接口,所以它可以獲取到spring中的一些bean和其他的一些資源,在面向切面編程中應用比較廣,攔截其實就是一種AOP策略。
