spring boot(7)監聽器、過濾器和攔截器

1 監聽器、過濾器和攔截器

1.1 監聽器

      監聽器Listener,它是實現了javax.servlet.XXXListener接口的服務器端程序,它也是隨web應用的啓動而啓動,只初始化一次,隨web應用的中止而銷燬。主要做用是:作一些初始化的內容添加工做、設置一些基本的內容、好比一些參數或者是一些固定的對象等等。java

      在javax.servlet.XXXListener接口中定義了2種方法:web

      void contextInitialized(ServletContextEvent sce) 監聽器的初始化spring

      void contextDestroyed(ServletContextEvent sce) 監聽器銷燬json

1.2 過濾器

      Servlet中的過濾器Filter是實現了javax.servlet.Filter接口的服務器端程序,主要的用途是過濾字符編碼、作一些業務邏輯判斷等。其工做原理是,只要你在web.xml文件配置好要攔截的客戶端請求,它都會幫你攔截到請求,此時你就能夠對請求或響應(Request、Response)統一設置編碼,簡化操做;同時還能夠進行邏輯判斷,如用戶是否已經登陸、有沒有權限訪問該頁面等等工做,它是隨你的web應用啓動而啓動的,只初始化一次,之後就能夠攔截相關的請求,只有當你的web應用中止或從新部署的時候才能銷燬。服務器

       在javax.servlet.Filter接口中定義了3個方法:session

       void init(FilterConfig filterConfig) 用於完成過濾器的初始化app

       void destroy() 用於過濾器銷燬前,完成某些資源的回收ide

      void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) 實現過濾功能,該方法對每一個請求增長額外的處理工具

1.3 攔截器

       攔截器主要是用在插件上,擴展件上好比spring、struts2等有點相似面向切片的技術,它是基於java反射機制。定義攔截器: 實現HandlerInterceptor 接口,或者繼承實現了HandlerInterceptor 接口的類(經常使用) 。post

2 監聽器、過濾器和攔截器的關係及區別

      過濾器(Filter):當你有一堆東西的時候,你只但願選擇符合你要求的某一些東西。定義這些要求的工具,就是過濾器。 對請求起到過濾的做用,它在監聽器以後,做用在servlet以前,對請求進行過濾。
      攔截器(Interceptor):在一個流程正在進行的時候,你但願干預它的進展,甚至終止它進行,這是攔截器作的事情。
      監聽器(Listener):當一個事件發生的時候,你但願得到這個事件發生的詳細信息,而並不想幹預這個事件自己的進程,這就要用到監聽器。對項目起到監聽的做用,它能感知到包括request(請求域),session(會話域)和applicaiton(應用程序)的初始化和屬性的變化 。對請求和返回進行攔截,它做用在servlet的內部 。

      它們之間的關係,能夠用一張圖來表示:

      使用原則

      對整個流程清楚以後,而後就是各自的使用,在使用以前應該有一個使用規則,爲何這個說,由於有些功能好比判斷用戶是否登陸,既能夠用過濾器,也能夠用攔截器,用哪個纔是合理的呢?那麼若是有一個原則,使用起來就會更加合理。實際上這個原則是有的:把整個項目的流程比做一條河,那麼監聽器的做用就是可以聽到河流裏的全部聲音,過濾器就是可以過濾出其中的魚,而攔截器則是攔截其中的部分魚,而且做標記。因此當須要監聽到項目中的一些信息,而且不須要對流程作更改時,用監聽器;當須要過濾掉其中的部分信息,只留一部分時,就用過濾器;當須要對其流程進行更改,作相關的記錄時用攔截器。

3 監聽器實現過程

      代碼註冊方式

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

public class IndexListener implements ServletContextListener{
    @Override
    public void contextDestroyed(ServletContextEvent arg0) {
        System.out.println("IndexListener contextDestroyed method");
    }
  
    @Override
    public void contextInitialized(ServletContextEvent arg0) {
        System.out.println("IndexListener contextInitialized method");
    }
}
@Bean
public ServletListenerRegistrationBean servletListenerRegistrationBean(){
    ServletListenerRegistrationBean servletListenerRegistrationBean = new ServletListenerRegistrationBean();
    servletListenerRegistrationBean.setListener(new IndexListener());
    return servletListenerRegistrationBean;
}

      註解方式

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;

@WebListener
public class IndexListener2 implements ServletContextListener{
    @Override
    public void contextDestroyed(ServletContextEvent arg0) {
        System.out.println("IndexListener2 contextDestroyed method");
    }

    @Override
    public void contextInitialized(ServletContextEvent arg0) {
        System.out.println("IndexListener2 contextInitialized method");
    }
}
@SpringBootApplication
@ServletComponentScan
public class SpringBootSimpleApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringBootSimpleApplication.class, args);
    }
}

4 過濾器實現過程

      代碼註冊方式

public class TestFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        if (......) {
            ......
            response.getWriter().write(writeValueAsString);          
        } else {
            chain.doFilter(request, response);
        }

    }

    @Override
    public void destroy() {

    }

}
@Bean
public FilterRegistrationBean  filterRegistrationBean() {
    FilterRegistrationBean registrationBean = new FilterRegistrationBean();

    TestFilter testFilter = new TestFilter();
    registrationBean.setFilter(testFilter);
    List<String> urlPatterns = new ArrayList<String>();
    urlPatterns.add("/service/extract/json/*");

    registrationBean.setUrlPatterns(urlPatterns);

    return registrationBean;
}

      註解方式

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;  

/** 
 * 實現javax.servlet.Filter,覆蓋其三個方法 
 * @author Administrator 
 * 
 */  
@WebFilter(filterName="testFilter",urlPatterns="/*")  
public class TestFilter implements Filter{  
  
    @Override  
    public void destroy() {  
        System.out.println("TestFilter過濾器銷燬");  
          
    }  
  
    @Override  
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)  
            throws IOException, ServletException {  
        System.out.println("TestFilter指定過濾器操做......");  
        //執行操做後必須doFilter  
        chain.doFilter(request, response);  
    }  
  
    @Override  
    public void init(FilterConfig arg0) throws ServletException {  
        System.out.println("TestFilter初始化......");  
    }  
  
}
@SpringBootApplication
@ServletComponentScan
public class SpringBootSimpleApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringBootSimpleApplication.class, args);
    }
}

5 攔截器實現過程

  • 建立本身的攔截器實現HandlerInterceptor接口
  • 建立本身的攔截器鏈,繼承WebMvcConfigurerAdapter類,重寫addInterceptors方法。
  • 實例化本身的攔截器,並加入到攔截器鏈中。
import javax.servlet.http.HttpServletRequest;  
import javax.servlet.http.HttpServletResponse;  
import org.springframework.web.servlet.HandlerInterceptor;  
import org.springframework.web.servlet.ModelAndView;  
  
public class CustomInterceptor implements HandlerInterceptor {  
  
    @Override  
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object object,  
            Exception exception) throws Exception {  
        //在整個請求結束以後被調用,也就是在DispatcherServlet 渲染了對應的視圖以後執行(主要是用於進行資源清理工做)  
        System.out.println("3. 整個請求結束以後被調用......CustomInterceptor1......");  
    }  
  
    @Override  
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object object, ModelAndView view)  
            throws Exception {  
        // 請求處理以後進行調用,可是在視圖被渲染以前  
        System.out.println("2. 請求處理以後進行調用,可是在視圖被渲染以前......CustomInterceptor1......");  
    }  
  
    @Override  
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object object) throws Exception {  
        // 在請求處理以前進行調用  
        System.out.println("1. 在請求處理以前進行調用......CustomInterceptor1......");  
        // 只有返回true纔會繼續向下執行,返回false取消當前請求  
        return true;  
    }  
  
}
import org.springframework.context.annotation.Configuration;  
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;  
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;  
  
import com.example.Interceptor.CustomInterceptor;  
import com.example.Interceptor.CustomInterceptor2;  
  
/** 
 * 繼承WebMvcConfigurerAdapter,複寫addInterceptors方法 
 * @author Administrator 
 * 
 */  
@Configuration  
public class WebAdapter extends WebMvcConfigurerAdapter{  
    /** 
     * 主要方法說明: 
     * addPathPatterns 用於添加攔截規則 
     * excludePathPatterns 用於排除攔截 
     */  
    @Override  
    public void addInterceptors(InterceptorRegistry registry) {  
        //衆多的攔截器組成了一個攔截器鏈
        registry.addInterceptor(new CustomInterceptor()).addPathPatterns("/*");  

        super.addInterceptors(registry);  
    }  
}
相關文章
相關標籤/搜索