過濾器,攔截器,監聽器的區別


 

一.過濾器

二.攔截器

三.監聽器 

攔截器和過濾器的區別

過濾器和攔截器的區別:

  ①攔截器是基於java的反射機制的,而過濾器是基於函數回調。
  ②攔截器不依賴與servlet容器,過濾器依賴與servlet容器。
  ③攔截器只能對action請求起作用,而過濾器則可以對幾乎所有的請求起作用。
  ④攔截器可以訪問action上下文、值棧里的對象,而過濾器不能訪問。
  ⑤在action的生命周期中,攔截器可以多次被調用,而過濾器只能在容器初始化時被調用一次。

  ⑥攔截器可以獲取IOC容器中的各個bean,而過濾器就不行,這點很重要,在攔截器里注入一個service,可以調用業務邏輯。

 觸發時機

有個專業詞語叫觸發時機

1.過濾器和攔截器觸發時機不一樣:

  過濾器是在請求進入容器后,但請求進入servlet之前進行預處理的。請求結束返回也是,是在servlet處理完后,返回給前端之前。

總結:過濾器包裹住servlet,servlet包裹住攔截器。

如下圖所示:

2.過濾器的觸發時機是容器后,servlet之前,所以過濾器的doFilter(

ServletRequest request, ServletResponse response, FilterChain chain

)的入參是ServletRequest ,而不是httpservletrequest。因為過濾器是在httpservlet之前。

@Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        System.out.println("before...");
        chain.doFilter(request, response);
        System.out.println("after...");
    }
chain.doFilter(request, response);這個方法的調用作為分水嶺。事實上調用Servlet的doService()方法是在chain.doFilter(request, response);這個方法中進行的

3.過濾器是JavaEE標准,采用函數回調的方式進行。是在請求進入容器之后,還未進入Servlet之前進行預處理,並且在請求結束返回給前端這之間進行后期處理。

攔截器是被包裹在過濾器之中的。

 

  @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("preHandle");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("afterCompletion");
    }

 

a.preHandle()這個方法是在過濾器的chain.doFilter(request, response)方法的前一步執行,也就是在 [System.out.println("before...")][chain.doFilter(request, response)]之間執行。該方法將在請求處理之前進行調用,如果已經是最后一個Interceptor 的時候就會是調用當前請求的Controller 方法。

 

  b.postreHandle()方法之后,在return ModelAndView之前進行,可以操控Controller的ModelAndView內容。當前請求進行處理之后,也就是Controller 方法調用之后執行,但是它會在DispatcherServlet 進行視圖返回渲染之前被調用,所以我們可以在這個方法中對Controller 處理之后的ModelAndView 對象進行操作。postHandle 方法被調用的方向跟preHandle 是相反的,也就是說先聲明的Interceptor 的postHandle 方法反而會后執行,

 

  c.afterCompletion()方法是在過濾器返回給前端前一步執行,也就是在[chain.doFilter(request, response)][System.out.println("after...")]之間執行。

該方法將在整個請求結束之后,也就是在DispatcherServlet 渲染了對應的視圖之后執行。這個方法的主要作用是用於進行資源清理工作的。

3.SpringMVC的機制是由同一個Servlet來分發請求給不同的Controller,其實這一步是在Servlet的service()方法中執行的。所以過濾器、攔截器、service()方法,dispatc()方法的執行順序應該是這樣的,大致畫了個圖:其實非常好測試,自己寫一個過濾器,一個攔截器,然后在這些方法中都加個斷點,一路F8下去就得出了結論。

 

4.SpringMVC的機制是由同一個Servlet來分發請求給不同的Controller,其實這一步是在Servlet的service()方法中執行的。

5.還有,

截器是spring容器的,是spring支持的,

總結:攔截器功在對請求權限鑒定方面確實很有用處,在我所參與的這個項目之中,第三方的遠程調用每個請求都需要參與鑒定,所以這樣做非常方便,而且他是很獨立的邏輯,這樣做讓業務邏輯代碼很干凈。和框架的其他功能一樣,原理很簡單,使用起來也很簡單,大致看了下SpringMVC這一部分的源碼,其實還是比較容易理解的。

  我們項目中僅僅用到了preHandle這個方法,而未用其他的,框架提供了一個已經實現了攔截器接口的適配器類HandlerInterceptorAdapter,繼承這個類然后重寫一下需要用到的方法就行了,可以少幾行代碼,這種方式Java中很多地方都有體現。

 

 

 

一.過濾器 (過濾器依賴與servlet容器

SpringMVC框架是一個成熟的優秀java web開發框架,學習研究框架設計有助於我們更好的理解和掌握spring MVC,設計和寫出更符合的結構和代碼。

本節主要是研讀SpringMVC框架中的過濾器設置,以編碼處理過濾器為例來學習框架內是怎樣設置過濾器的。

如上所示的spring-web.jar包結構所示, Spring的web包中中提供有很多過濾器,這些過濾器位於org.springframework.web.filter並且理所當然地實現了javax.servlet.Filter,

不過實現的方式有以下幾類

        (1) 直接實現Filter,這一類過濾器只有CompositeFilter;

        (2) 繼承抽象類GenericFilterBean,該類實現了javax.servlet.Filter,這一類的過濾器只有一個,即DelegatingFilterProxy;

        (3) 繼承抽象類OncePerRequestFilter,該類為GenericFilterBean的直接子類,這一類過濾器包括CharacterEncodingFilter、HiddenHttpMethodFilter、HttpPutFormContentFilter、RequestContextFilter和ShallowEtagHeaderFilter;

        (4) 繼承抽象類AbstractRequestLoggingFilter,該類為OncePerRequestFilter的直接子類,這一類過濾器包括CommonsRequestLoggingFilter、Log4jNestedDiagnosticContextFilter和ServletContextRequestLoggingFilter。

過濾器放在容器結構的什么位置?

過濾器放在web資源之前,可以在請求抵達它所應用的web資源(可以是一個Servlet、一個Jsp頁面,甚至是一個HTML頁面)之前截獲進入的請求,並且在它返回到客戶之前截獲輸出請求。Filter:用來攔截請求,處於客戶端與被請求資源之間,目的是重用代碼。Filter鏈,在web.xml中哪個先配置,哪個就先調用。在filter中也可以配置一些初始化參數。

Java中的Filter 並不是一個標准的Servlet ,它不能處理用戶請求,也不能對客戶端生成響應。 主要用於對HttpServletRequest 進行預處理,也可以對HttpServletResponse 進行后處理,是個典型的處理鏈。 

Filter 有如下幾個種類:

l  用戶授權的Filter: Filter 負責檢查用戶請求,根據請求過濾用戶非法請求。 

l  日志Filter: 詳細記錄某些特殊的用戶請求。 

l  負責解碼的Filter: 包括對非標准編碼的請求解碼。 

l  能改變XML 內容的XSLTFilter 等。 

 

Filter 有如下幾個用處

l  在HttpServletRequest 到達Servlet 之前,攔截客戶的HttpServletRequest 。 

l  根據需要檢查HttpServletRequest ,也可以修改HttpServletRequest 頭和數據。 

l  在HttpServletResponse 到達客戶端之前,攔截HttpServletResponse 。 

l  根據需要檢查HttpServletResponse ,可以修改HttpServletResponse 頭和數據。

 

創建一個Filter 只需兩個步驟
(1)創建Filter 處理類: 

(2)在web.xml 文件中配置Filter 。

創建Filter 必須實現javax.servlet.Filter 接口,在該接口中定義了三個方法。 
• void init(FilterConfig config): 用於完成Filter 的初始化。 
• void destroy(): 用於Filter 銷毀前,完成某些資源的回收。 
• void doFilter(ServletRequest request, ServletResponse response,FilterChain chain): 實現過濾功能,該方法就是對每個請求及響應增加的額外處理。 

過濾器Filter也具有生命周期:init()->doFilter()->destroy(),由部署文件中的filter元素驅動。

參照編碼過濾器示例來查看怎么實現的

<!-- 編碼處理過濾器 -->

   <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>

      <init-param>

         <param-name>forceEncoding</param-name>

         <param-value>true</param-value>

      </init-param>

    </filter>   

    <filter-mapping>

       <filter-name>encodingFilter</filter-name>

       <url-pattern>*.do</url-pattern>

    </filter-mapping>

其中,filter-class 為過濾器Filter類,init-prama為注入的set參數

Filter-mapping中的url-pattern為過濾的url類型

類的繼承關系

CharacterEncodingFilter r類繼承了 OncePerRequestFilter 

public class CharacterEncodingFilter extends OncePerRequestFilter

 

OncePerRequestFilter 類又繼承了GenericFilterBean 

public abstract class OncePerRequestFilter extends GenericFilterBean 

public abstract class GenericFilterBean implements

       Filter, BeanNameAware, EnvironmentAware, ServletContextAware, InitializingBean, DisposableBean

設置編碼的核心代碼為

@Override

   protected void doFilterInternal(

         HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)

         throws ServletException, IOException {

 

      if (this.encoding != null && (this.forceEncoding || request.getCharacterEncoding() == null)) {

         request.setCharacterEncoding(this.encoding);

         if (this.forceEncoding) {

            response.setCharacterEncoding(this.encoding);

         }

      }

      filterChain.doFilter(request, response);

   }

其中filterChain為過濾器鏈,表示執行完這個過濾器之后接着執行下一個過濾器

區別

         我們在使用過濾器時,通常沒必要知道GenericFilterBean、OncePerRequestFilter和AbstractRequestLoggingFilter,但不防礙我們了解這幾個類,就上文所述,AbstractRequestLoggingFilter繼承自OncePerRequestFilter,OncePerRequestFilter繼承自GenericFilterBean,所以我們知道,genericFilterBean是任何類型的過濾器的一個比較方便的超類,這個類主要實現的就是從web.xml文件中取得init-param中設定的值,然后對Filter進行初始化(當然,其子類可以覆蓋init方法)。

         OncePerRequestFilter繼承自GenericFilterBean,那么它自然知道怎么去獲取配置文件中的屬性及其值,所以其重點不在於取值,而在於確保在接收到一個request后,每個filter只執行一次,它的子類只需要關注Filter的具體實現即doFilterInternal。

        AbstractRequestLoggingFilter是對OncePerRequestFilter的擴展,它除了遺傳了其父類及祖先類的所有功能外,還在doFilterInternal中決定了在過濾之前和之后執行的事件,它的子類關注的是beforeRequest和afterRequest。

       總體來說,這三個類分別執行了Filter的某部分功能,當然,具體如何執行由它們的子類規定,若你需要實現自己的過濾器,也可以根據上文所述繼承你所需要的類。

自定義過濾器

參數名稱相同,設置set方法可以自動初始化 

package com.my.dm.filter;

import java.io.IOException;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.web.filter.OncePerRequestFilter;

public class TestFilter extends OncePerRequestFilter{
    
    private Logger logger =LogManager.getLogger(TestFilter.class);
    private String demo;   
    
    

    /**
     * @return the demo
     */
    public String getDemo() {
        return demo;
    }

    /**
     * @param demo the demo to set
     */
    public void setDemo(String demo) {
        this.demo = demo;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {
        // TODO Auto-generated method stub
        // 請求的uri
        
        String url = request.getRequestURI();
        
        String hoString = request.getRemoteHost();
        
        String ip  = getIPAddress(request);
        logger.info("url : " + url);
        logger.info("ip : " + ip);    
        
        logger.info("demo : " + demo);    
        
        // 將請求轉發到目的地 
        filterChain.doFilter(request, response);        
    }
      
     public void destroy() {
       
     }
     
     public void init(){
         
     }
    
    
    //獲取真實ip
    public static String getIPAddress(HttpServletRequest request) {
        String ip = null;

        //X-Forwarded-For:Squid 服務代理
        String ipAddresses = request.getHeader("X-Forwarded-For");
    if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
            //Proxy-Client-IP:apache 服務代理
            ipAddresses = request.getHeader("Proxy-Client-IP");
        }
    if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
            //WL-Proxy-Client-IP:weblogic 服務代理
            ipAddresses = request.getHeader("WL-Proxy-Client-IP");
        }
    if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
            //HTTP_CLIENT_IP:有些代理服務器
            ipAddresses = request.getHeader("HTTP_CLIENT_IP");
        }
    if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
            //X-Real-IP:nginx服務代理
            ipAddresses = request.getHeader("X-Real-IP");
        }

        //有些網絡通過多層代理,那么獲取到的ip就會有多個,一般都是通過逗號(,)分割開來,並且第一個ip為客戶端的真實IP
        if (ipAddresses != null && ipAddresses.length() != 0) {
            ip = ipAddresses.split(",")[0];
        }

        //還是不能獲取到,最后再通過request.getRemoteAddr();獲取
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
            ip = request.getRemoteAddr();
        }
        return ip.equals("0:0:0:0:0:0:0:1")?"127.0.0.1":ip;
    }

}

 

<!-- 獲取登陸者信息 -->
    <filter>
        <filter-name>testFilter</filter-name>
        <filter-class>com.my.dm.filter.TestFilter</filter-class>
    
        <init-param>
            <param-name>demo</param-name>
            <param-value>112.2.36</param-value>
        </init-param>
        </filter>
    <filter-mapping>
        <filter-name>testFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
[21:31:48:620] [INFO] - url : /dm/device/toUploadFile - com.my.dm.filter.TestFilter.doFilterInternal(TestFilter.java:46)
[21:31:48:641] [INFO] - ip : 127.0.0.1 - com.my.dm.filter.TestFilter.doFilterInternal(TestFilter.java:47)
[21:31:48:641] [INFO] - demo : 112.2.36 - com.my.dm.filter.TestFilter.doFilterInternal(TestFilter.java:49) 

二.攔截器

springMVC 攔截器-用戶登錄攔截實戰

 

攔截器

 

不知道小伙伴們平時上網的時候有沒有注意到,尤其是上網購物的時候,不登錄賬號,就無法訪問一些功能頁面,比如你不登錄賬號,就沒法查看購物車里面有什么物品.這就是攔截器起到的作用.那么今天我們就來給之前的項目添加一個攔截器.

攔截器攔截器的概念

SpringMVC 中的Interceptor 攔截器的主要作用就是攔截用戶的 url 請求,並在執行 handler 方法的前中后加入某些特殊請求,類似於 servlet 里面的過濾器.

SpringMVC 中的Interceptor 攔截器也是相當重要和相當有用的,它的主要作用是攔截用戶的請求並進行相應的處理。比如通過它來進行權限驗證,或者是來判斷用戶是否登陸,或者是像12306 那樣子判斷當前時間是否是購票時間。

一、定義Interceptor實現類

SpringMVC 中的Interceptor 攔截請求是通過HandlerInterceptor 來實現的。在SpringMVC 中定義一個Interceptor 非常簡單,主要有兩種方式,

第一種方式是要定義的Interceptor類要實現了Spring 的HandlerInterceptor 接口,或者是這個類繼承實現了HandlerInterceptor 接口的類,比如Spring 已經提供的實現了HandlerInterceptor 接口的抽象類HandlerInterceptorAdapter ;

第二種方式是實現Spring的WebRequestInterceptor接口,或者是繼承實現了WebRequestInterceptor的類。

(一)實現HandlerInterceptor接口

HandlerInterceptor 接口中定義了三個方法,我們就是通過這三個方法來對用戶的請求進行攔截處理的。

(1 )preHandle (HttpServletRequest request, HttpServletResponse response, Object handle) 方法,顧名思義,該方法將在請求處理之前進行調用。SpringMVC 中的Interceptor 是鏈式的調用的,在一個應用中或者說是在一個請求中可以同時存在多個Interceptor 。每個Interceptor 的調用會依據它的聲明順序依次執行,而且最先執行的都是Interceptor 中的preHandle 方法,所以可以在這個方法中進行一些前置初始化操作或者是對當前請求的一個預處理,也可以在這個方法中進行一些判斷來決定請求是否要繼續進行下去。該方法的返回值是布爾值Boolean 類型的,當它返回為false 時,表示請求結束,后續的Interceptor 和Controller 都不會再執行;當返回值為true 時就會繼續調用下一個Interceptor 的preHandle 方法,如果已經是最后一個Interceptor 的時候就會是調用當前請求的Controller 方法。

(2 )postHandle (HttpServletRequest request, HttpServletResponse response, Object handle, ModelAndView modelAndView) 方法,由preHandle 方法的解釋我們知道這個方法包括后面要說到的afterCompletion 方法都只能是在當前所屬的Interceptor 的preHandle 方法的返回值為true 時才能被調用。postHandle 方法,顧名思義就是在當前請求進行處理之后,也就是Controller 方法調用之后執行,但是它會在DispatcherServlet 進行視圖返回渲染之前被調用,所以我們可以在這個方法中對Controller 處理之后的ModelAndView 對象進行操作。postHandle 方法被調用的方向跟preHandle 是相反的,也就是說先聲明的Interceptor 的postHandle 方法反而會后執行,這和Struts2 里面的Interceptor 的執行過程有點類型。Struts2 里面的Interceptor 的執行過程也是鏈式的,只是在Struts2 里面需要手動調用ActionInvocation 的invoke 方法來觸發對下一個Interceptor 或者是Action 的調用,然后每一個Interceptor 中在invoke 方法調用之前的內容都是按照聲明順序執行的,而invoke 方法之后的內容就是反向的。

(3 )afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handle, Exception ex) 方法,該方法也是需要當前對應的Interceptor 的preHandle 方法的返回值為true 時才會執行。顧名思義,該方法將在整個請求結束之后,也就是在DispatcherServlet 渲染了對應的視圖之后執行。這個方法的主要作用是用於進行資源清理工作的。

 

 

package com.my.dm.interceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

public class TestInterceptor implements HandlerInterceptor {

        private Logger logger =LogManager.getLogger(TestInterceptor.class);
                                                     
    @Override
    public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
            throws Exception {
        // TODO Auto-generated method stub
        logger.error("afterCompletion");
    }

    @Override
    public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
            throws Exception {
        // TODO Auto-generated method stub
        logger.error("postHandle");
    }

    @Override
    public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {
        // TODO Auto-generated method stub
        logger.error("preHandle");
        return true;
    }

}

攔截器在Springmvc中的配置

<!-- 配置攔截器 -->
    <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/**" />
            <bean class="com.my.dm.interceptor.TestInterceptor"></bean>
        </mvc:interceptor>
    </mvc:interceptors>

多個攔截器配置模板

<mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/employee/**" />
            <mvc:mapping path="/trainning/**" />
            <mvc:mapping path="/manage/**" /> 
            <mvc:exclude-mapping path="/**/fonts/*" />
            <mvc:exclude-mapping path="/**/*.css" />
            <mvc:exclude-mapping path="/**/*.js" />
            <mvc:exclude-mapping path="/**/*.png" />
            <mvc:exclude-mapping path="/**/*.gif" />
            <mvc:exclude-mapping path="/**/*.jpg" />
            <mvc:exclude-mapping path="/**/*.jpeg" />
            <bean class="com.pmo.interceptor.PageInterceptor" />
        </mvc:interceptor>
        <mvc:interceptor>  
                <mvc:mapping path="/**"/>
                <bean class="com.pmo.interceptor.LoginInterceptor"></bean>  
        </mvc:interceptor>
        <mvc:interceptor>  
                <mvc:mapping path="/**"/>
                <bean class="com.pmo.interceptor.UserAuthorityInterceptor"></bean>  
        </mvc:interceptor>
    </mvc:interceptors> 

 

 

三.監聽器

 

監聽器詳解

 springMVC監聽器主要的作用就是spring容器啟動的時候加載一些數據,最常用的功能就是開發權限系統的時候,當監聽器啟動的時候,從數據庫加載權限url。

一、ContextLoaderListener

ContextLoaderListener監聽器的作用就是啟動Web容器時,自動裝配ApplicationContext的配置信息。因為它實現了ServletContextListener這個接口,web.xml配置這個監聽器啟動容器時,就會默認執行它實現的方法。在ContextLoader-Listener中關聯了ContextLoader這個類,所以整個加載配置過程由ContextLoader來完成。ContextLoader可以由 ContextLoaderListener和ContextLoaderServlet生成。查看ContextLoaderServlet的API,它也關聯了ContextLoader這個類而且它實現了HttpServlet這個接口;ContextLoader創建的是XmlWebApplicationContext這樣一個類,實現的接口是WebApplicationContext->ConfigurableWebApplicationContext->ApplicationContext->BeanFactory。這樣一來spring中的所有bean都由這個類來創建。如果在web.xml中不寫任何參數配置信息,默認的路徑是/WEB-INF/applicationContext.xml,在WEB-INF目錄下創建的xml文件的名稱必須是applicationContext.xml;如果是要自定義文件名可以在web.xml里加入contextConfigLocation這個context參數:

<context-param>  
    <param-name>contextConfigLocation</param-name>  
    <param-value>  
        /WEB-INF/classes/applicationContext-*.xml   
    </param-value>
</context-param> 

  在<param-value></param-value>里指定相應的xml文件名,如果有多個xml文件,可以寫在一起並一“,”號分隔。上面的applicationContext-*.xml采用通配符,比如這那個目錄下有applicationContext-ibatis-base.xml,applicationContext-action.xml,applicationContext-ibatis-dao.xml等文件,都會一同被載入。由此可見applicationContext.xml的文件位置就可以有兩種默認實現:第一種:直接將之放到/WEB-INF下,之后在web.xml中聲明一個listener;第二種:將之放到classpath下,但是此時要在web.xml中加入<context-param>,用它來指明你的applicationContext.xml的位置以供web容器來加載。按照Struts2 整合spring的官方給出的檔案,寫成:

<context-param>  
    <param-name>contextConfigLocation</param-name>  
    <param-value>/WEB-INF/applicationContext-*.xml,classpath*:applicationContext-*.xml</param-value> 
</context-param>

自定義監聽器的配置

1配置自定義的監聽器需要配置spring容器監聽器,因為自定期監聽器需要從spring容器中拿取數據,並且自定義監聽器的配置文件位於spring監聽器之后

<?xml version="1.0" encoding="UTF-8"?>

<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee

http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">



    <display-name>Device Manage Web Application</display-name>

    <!-- 獲取登陸者信息 -->
    <filter>
        <filter-name>testFilter</filter-name>
        <filter-class>com.my.dm.filter.TestFilter</filter-class>
    
        <init-param>
            <param-name>demo</param-name>
            <param-value>112.2.36</param-value>
        </init-param>
        </filter>
    <filter-mapping>
        <filter-name>testFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <!-- 統一編碼 解決中文亂碼問題 -->
    <filter>
        <filter-name>charsetEncoding</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>
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>charsetEncoding</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <!-- DispatcherServlet -->
    <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/spring-mvc.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>

    <!--3. Load Spring Config File -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:config/beans.xml</param-value>
    </context-param>    
    
    <!-- 4.spring listener -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <listener>
        <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
    </listener>
    <!--5.spring 防內存溢出監聽器 -->
    <listener>
        <listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>
    </listener>    

    <!-- 6.common Page! -->
    <welcome-file-list>
        <welcome-file>/welcome.jsp</welcome-file>
    </welcome-file-list>

    <error-page>
        <error-code>404</error-code>
        <location>/WEB-INF/error/404.jsp</location>
    </error-page>
    
    <error-page>
        <error-code>500</error-code>
        <location>/WEB-INF/error/500.jsp</location>
    </error-page>    
    
    <!-- 自定義監聽器 -->
    <listener>
        <listener-class>com.my.dm.listener.TestListener</listener-class>
    </listener>    

</web-app>

2,springMC自定義監聽器需要實現ServletContextListener接口

package com.my.dm.listener;

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

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import com.my.dm.service.DeviceService;

public class TestListener implements ServletContextListener {
    private Logger logger = LogManager.getLogger(TestListener.class);

    /**
     * 當容器啟動完成之后
     */
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        // TODO Auto-generated method stub
        ApplicationContext ac = WebApplicationContextUtils.getWebApplicationContext(sce.getServletContext());

        DeviceService deviceService = ac.getBean(DeviceService.class);
        logger.error("This is test for TestListener!");
        logger.error(deviceService.getDeviceByNameIp("", "4.154.135.74").get(0));
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        // TODO Auto-generated method stub

    }

}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM