過濾器、攔截器、監聽器三者的區別與使用

目錄

監聽器、過濾器、攔截器的介紹

​過濾器:

攔截器:

監聽器:

監聽器的說明

監聽器的用途

監聽器實現的接口

servlet的監聽接口

springmvc的監聽器

監聽器配置流程(以ContextLoaderListener爲例)

web.xml文件

過濾器的說明

過濾器的用途

過濾器實現的接口

過濾器的配置流程

攔截器的說明

攔截器的用途

攔截器與過濾器的區別

攔截器實現接口

攔截器的配置

瞭解監聽器、過濾器、servlet的啓動順序

問題描述:

解決方法


監聽器、過濾器、攔截器的介紹


過濾器:

依賴於servlet容器。在實現上基於函數回調,可以對幾乎所有請求進行過濾,但是缺點是一個過濾器實例只能在容器初始化時調用一次。使用過濾器的目的是用來做一些過濾操作,獲取我們想要獲取的數據,比如:在過濾器中修改字符編碼;在過濾器中修改HttpServletRequest的一些參數,包括:過濾低俗文字、危險字符等。

攔截器:

依賴於web框架,在SpringMVC中就是依賴於SpringMVC框架。在實現上基於Java的反射機制,屬於面向切面編程(AOP)的一種運用。由於攔截器是基於web框架的調用,因此可以使用Spring的依賴注入(DI)進行一些業務操作,同時一個攔截器實例在一個controller生命週期之內可以多次調用。但是缺點是隻能對controller請求進行攔截,對其他的一些比如直接訪問靜態資源的請求則沒辦法進行攔截處理。

監聽器:

監聽器詳解地址
web監聽器是一種Servlet中的特殊的類,它們能幫助開發者監聽web中的特定事件,實現了javax.servlet.ServletContextListener 接口的服務器端程序,它也是隨web應用的啓動而啓動,只初始化一次,隨web應用的停止而銷燬。主要作用是:感知到包括request(請求域),session(會話域)和applicaiton(應用程序)的初始化和屬性的變化;

這裏寫圖片描述

監聽器的說明

監聽器的用途

  1. 通常使用Web監聽器做以下的內容:
  2. 統計在線人數,利用HttpSessionLisener
  3. 加載初始化信息:利用ServletContextListener
  4. 統計網站訪問量
  5. 實現訪問監控

這裏寫圖片描述

監聽器實現的接口

servlet的監聽接口

  1. ServletContextListener監聽web應用的啓動和關閉
  2. ServletContextAttributeListener監聽ServletContext範圍內屬性的改變
  3. ServletRequestListener監聽用戶的請求
  4. ServletRequestAttributeListener監聽ServletRequest範圍內(request)內屬性的變化
  5. HttpSessionListener監聽用戶session的開始和結束
  6. HttpSessionAttributeListener監聽HttpSession範圍內session內屬性的改變。

springmvc的監聽器

ContextLoaderListener(實現ServletContextListener)用於加載spring容器的配置文件。

監聽器配置流程(以ContextLoaderListener爲例)

web.xml文件

<!--加載spring容器的配置文件-->
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath*:/config/applicationContext.xml</param-value>
  </context-param>
    <listener>
  <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
  
   <servlet>
   <servlet-name>springMVC</servlet-name>
   <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath*:/config/dispatcher-context.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>springMVC</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>

注意:

  1. dispatcher-context.xml主要是spring mvc裏面的,控制器、攔截uri轉發view。
  2. ApplicationContext.xml 是spring 全局配置文件,用來控制spring 特性
  • 一個bean如果在兩個文件中都被定義了(比如兩個文件中都定義了component scan掃描相同的package), spring會在application context和 servlet context中都生成一個實例,他們處於不同的上下文空間中,他們的行爲方式是有可能不一樣的。
  • 如果在application context和 servlet context中都存在同一個 @Service 的實例, controller(在servlet context中) 通過 @Resource引用時, 會優先選擇servlet context中的實例。

最好的方法是:在applicationContext和dispatcher-servlet定義的bean最好不要重複, dispatcher-servlet最好只是定義controller類型的bean。

過濾器的說明

過濾器的用途

過濾特定請求資源、請求信息和響應信息。一個請求來到時,web容器會判斷是否有過濾器與該信息資源相關聯,如果有則交給過濾器處理,然後再交給目標資源,響應的時候則以相反的順序交給過濾器處理,最後再返回給用戶瀏覽器。一個filter 包括:

  • 在servlet被調用之前截獲;
  • 在servlet被調用之前檢查servlet request;
  • 根據需要修改request頭和request數據;
  • 根據需要修改response頭和response數據;
  • 在servlet被調用之後截獲.

過濾器實現的接口

public interface Filter {
    void init(FilterConfig var1) throws ServletException;

    void doFilter(ServletRequest var1, ServletResponse var2, 
    FilterChain var3) throws IOException, ServletException;

    void destroy();
}

過濾器的配置流程

web.xml文件

<filter>
  <filter-name>encodingFilter</filter-name>
  <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
  <init-param>
      <param-name>encoding</param-name>
      <param-value>UTF-8</param-value>
  </init-param>
</filter>
<!--過濾的url地址-->
<filter-mapping>
  <filter-name>encodingFilter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

攔截器的說明

攔截器的用途

  1. 亂碼問題:用request,response參數去設置編碼;
  2. 解決權限驗證問題(是否登陸,取session對象查看);

攔截器與過濾器的區別

  1. 攔截器Interceptor依賴於框架容器,基於反射機制,只過濾請求;
  2. 過濾器Filter依賴於Servlet容器,基於回調函數,過濾範圍大

攔截器實現接口

  • 自定義一個實現了Interceptor接口的類,或者繼承抽象類AbstractInterceptor。
  • 在配置文件中註冊定義的攔截器。
  • 在需要使用Action中引用上述定義的攔截器,爲了方便也可以將攔截器定義爲默認的攔截器,這樣在不加特殊說明的情況下,所有的Action都被這個攔截器攔截。
public abstract class HandlerInterceptorAdapter implements HandlerInterceptor{  
    // 在業務處理器處理請求之前被調用  
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception{  
        return true;  
    }  
    // 在業務處理器處理請求完成之後,生成視圖之前執行  
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)  
      throws Exception{  
    }  
    // 在DispatcherServlet完全處理完請求之後被調用,可用於清理資源  
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)  
      throws Exception{  
    }  
}  

攔截器的配置

在dispatch-servlet.xml中配置

<!--配置攔截器, 多個攔截器,順序執行 -->
<mvc:interceptors>
    <mvc:interceptor>
        <!-- 匹配的是url路徑, 如果不配置或/**,將攔截所有的Controller -->
        <mvc:mapping path="/**"/>
        <bean class="com.cckj.util.auth.AuthInterceptor"></bean>
    </mvc:interceptor>
    <!-- 當設置多個攔截器時,先按順序調用preHandle方法,然後逆序調用每個攔截器的postHandle和afterCompletion方法 -->
</mvc:interceptors>

瞭解監聽器、過濾器、servlet的啓動順序

問題描述:

filter中使用@Autowired或@Resource注入bean時注入失敗,bean一直爲空。

web應用啓動的順序是:listener->filter->servlet,先初始化listener,然後再來就filter的初始化,再接着纔到我們的dispathServlet的初始化,因此,當我們需要在filter裏注入一個註解的bean時,就會注入失敗,因爲filter初始化時,註解的bean還沒初始化,沒法注入。

解決方法

/**
 * 解決Filter中注入Bean失敗
 */
@Slf4j
@Component
public class SpringUtils implements ApplicationContextAware {

    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext)
            throws BeansException {
        if (SpringUtils.applicationContext == null) {
            SpringUtils.applicationContext = applicationContext;
        }

    }

    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    //根據name
    public static Object getBean(String name) {
        return getApplicationContext().getBean(name);
    }

    //根據類型
    public static <T> T getBean(Class<T> clazz) {
        return getApplicationContext().getBean(clazz);
    }

    public static <T> T getBean(String name, Class<T> clazz) {
        return getApplicationContext().getBean(name, clazz);
    }

}

在使用時調用SpringUtils.getBean(String name)或SpringUtils.getBean(Class<T> clazz)方法,轉換相應類型即可

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章